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 f801957c961d9ae443a3bc3c8ded1daa07eed71f
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Fri Apr 24 06:09:31 2020 +0200

    ISIS-2340: share logic of ObjectAdapterAccessHelper/UpdateHelper (2)
---
 .../binding/interaction/ActionInteractor.java      |  36 +++++++
 .../binding/interaction/CollectionInteractor.java  |  35 +++++++
 .../binding/interaction/InteractionResponse.java   |  21 ++++-
 .../binding/interaction/MemberInteractor.java      |  57 +++++++++++
 .../binding/interaction/ObjectInteractor.java      |  21 ++++-
 .../binding/interaction/PropertyInteractor.java    |  35 +++++++
 .../resources/DomainObjectResourceServerside.java  |  12 ++-
 .../viewer/resources/DomainResourceHelper.java     |  12 +--
 .../resources/ObjectAdapterAccessHelper.java       | 105 ++++++++++-----------
 9 files changed, 261 insertions(+), 73 deletions(-)

diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ActionInteractor.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ActionInteractor.java
new file mode 100644
index 0000000..3136316
--- /dev/null
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ActionInteractor.java
@@ -0,0 +1,36 @@
+package org.apache.isis.viewer.common.model.binding.interaction;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.internal.base._Either;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import 
org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto;
+import 
org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent;
+
+import lombok.val;
+
+public class ActionInteractor extends MemberInteractor {
+
+    public ActionInteractor(ObjectInteractor objectInteractor) {
+        super(objectInteractor);
+    }
+
+    public _Either<ObjectAction, InteractionResponse> 
getActionThatIsVisibleForIntent(
+            final String actionId,
+            final Where where,
+            final AccessIntent intent) {
+
+        val managedObject = objectInteractor.getManagedObject();
+        
+        val spec = managedObject.getSpecification();
+        val action = spec.getObjectAction(actionId).orElse(null);
+        
+        if(action==null) {
+            return _Either.right(InteractionResponse.failed(Veto.NOT_FOUND));
+        }
+        
+        return super.memberThatIsVisibleForIntent(
+                MemberType.ACTION,
+                action, where, intent);
+    }
+
+}
diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/CollectionInteractor.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/CollectionInteractor.java
new file mode 100644
index 0000000..1459243
--- /dev/null
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/CollectionInteractor.java
@@ -0,0 +1,35 @@
+package org.apache.isis.viewer.common.model.binding.interaction;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.internal.base._Either;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import 
org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto;
+import 
org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent;
+
+import lombok.val;
+
+public class CollectionInteractor extends MemberInteractor {
+
+    public CollectionInteractor(ObjectInteractor objectInteractor) {
+        super(objectInteractor);
+    }
+
+    public _Either<OneToManyAssociation, InteractionResponse> 
getPropertyThatIsVisibleForIntent(
+            final String collectionId,
+            final Where where,
+            final AccessIntent intent) {
+
+        val managedObject = objectInteractor.getManagedObject();
+        
+        val spec = managedObject.getSpecification();
+        val collection = spec.getAssociation(collectionId).orElse(null);
+        if(collection==null || !collection.isOneToOneAssociation()) {
+            return _Either.right(InteractionResponse.failed(Veto.NOT_FOUND));
+        }
+        
+        return super.memberThatIsVisibleForIntent(
+                MemberType.COLLECTION,
+                (OneToManyAssociation) collection, where, intent);
+    }
+
+}
diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java
index 49820b8..feee940 100644
--- 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java
@@ -20,16 +20,25 @@ package 
org.apache.isis.viewer.common.model.binding.interaction;
 
 import lombok.AccessLevel;
 import lombok.Getter;
+import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 
 @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE)
 public class InteractionResponse {
     
-    private final static InteractionResponse SUCCESS = of(null);
+    public static enum Veto {
+        NOT_FOUND,
+        HIDDEN,
+        FORBIDDEN,
+        UNAUTHORIZED, 
+    }
+    
+    private final static InteractionResponse SUCCESS = of(null, null);
+    @Getter private final Veto veto;
     @Getter private final String failureMessage;
     
     public boolean isSuccess() {
-        return failureMessage==null;
+        return veto==null;
     }
     
     public boolean isFailure() {
@@ -38,8 +47,12 @@ public class InteractionResponse {
     
     // -- FACTORIES
     
-    public static InteractionResponse failed(String reason) {
-        return of(reason);
+    public static InteractionResponse failed(@NonNull Veto veto) {
+        return of(veto, "unspecified");
+    }
+    
+    public static InteractionResponse failed(@NonNull Veto veto, String 
reason) {
+        return of(veto, reason);
     }
 
     public static InteractionResponse success() {
diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/MemberInteractor.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/MemberInteractor.java
new file mode 100644
index 0000000..a9168d0
--- /dev/null
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/MemberInteractor.java
@@ -0,0 +1,57 @@
+package org.apache.isis.viewer.common.model.binding.interaction;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.internal.base._Either;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import 
org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto;
+import 
org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent;
+
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+@RequiredArgsConstructor
+public class MemberInteractor {
+    
+    // only used to create failure messages
+    static enum MemberType {
+        PROPERTY,
+        COLLECTION,
+        ACTION
+    }
+    
+    protected final ObjectInteractor objectInteractor;
+
+    public <T extends ObjectMember> 
+    _Either<T, InteractionResponse> memberThatIsVisibleForIntent(
+            final MemberType memberType,
+            final T objectMember, 
+            final Where where, 
+            final AccessIntent intent) {
+
+        val managedObject = objectInteractor.getManagedObject();
+        val visibilityConsent =
+                objectMember.isVisible(
+                        managedObject, InteractionInitiatedBy.USER, where);
+        if (visibilityConsent.isVetoed()) {
+            val memberId = objectMember.getId();
+            return _Either.right(InteractionResponse.failed(
+                    Veto.HIDDEN,
+                    String.format("%s '%s' either does not exist, is disabled 
or is not visible", 
+                            memberId, 
+                            memberType.name().toLowerCase())));
+        }
+        if (intent.isMutate()) {
+            final Consent usabilityConsent = objectMember.isUsable(
+                    managedObject, InteractionInitiatedBy.USER, where);
+            if (usabilityConsent.isVetoed()) {
+                return _Either.right(InteractionResponse.failed(
+                        Veto.FORBIDDEN,
+                        usabilityConsent.getReason()));
+            }
+        }
+        return _Either.left(objectMember);
+    }
+    
+}
diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
index 8693986..105a4db 100644
--- 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
@@ -29,7 +29,9 @@ import 
org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.viewer.common.model.binding.UiComponentFactory;
+import 
org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto;
 
+import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
@@ -44,6 +46,7 @@ public class ObjectInteractor {
         }
     }
 
+    @Getter
     private final ManagedObject managedObject;
     
     public String getTitle() {
@@ -80,7 +83,7 @@ public class ObjectInteractor {
         
         val consent = property.isAssociationValid(managedObject, 
proposedNewValue, InteractionInitiatedBy.USER);
         if (consent.isVetoed()) {
-            return InteractionResponse.failed(consent.getReason());
+            return InteractionResponse.failed(Veto.UNAUTHORIZED, 
consent.getReason());
         }
         
         property.set(managedObject, proposedNewValue, 
InteractionInitiatedBy.USER);
@@ -124,6 +127,22 @@ public class ObjectInteractor {
                 .filter(collection->Objects.equals(id, collection.getId()))
                 .findFirst();
     }
+
+    public MemberInteractor getMemberInteractor() {
+        return new MemberInteractor(this);
+    }
+
+    public ActionInteractor getActionInteractor() {
+        return new ActionInteractor(this);
+    }
+    
+    public PropertyInteractor getPropertyInteractor() {
+        return new PropertyInteractor(this);
+    }
+    
+    public CollectionInteractor getCollectionInteractor() {
+        return new CollectionInteractor(this);
+    }
     
     
 }
diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/PropertyInteractor.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/PropertyInteractor.java
new file mode 100644
index 0000000..83352d5
--- /dev/null
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/PropertyInteractor.java
@@ -0,0 +1,35 @@
+package org.apache.isis.viewer.common.model.binding.interaction;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.internal.base._Either;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import 
org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto;
+import 
org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent;
+
+import lombok.val;
+
+public class PropertyInteractor extends MemberInteractor {
+
+    public PropertyInteractor(ObjectInteractor objectInteractor) {
+        super(objectInteractor);
+    }
+
+    public _Either<OneToOneAssociation, InteractionResponse> 
getPropertyThatIsVisibleForIntent(
+            final String propertyId,
+            final Where where,
+            final AccessIntent intent) {
+
+        val managedObject = objectInteractor.getManagedObject();
+        
+        val spec = managedObject.getSpecification();
+        val property = spec.getAssociation(propertyId).orElse(null);
+        if(property==null || !property.isOneToOneAssociation()) {
+            return _Either.right(InteractionResponse.failed(Veto.NOT_FOUND));
+        }
+        
+        return super.memberThatIsVisibleForIntent(
+                MemberType.PROPERTY,
+                (OneToOneAssociation)property, where, intent);
+    }
+
+}
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
index f767583..daf605e 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
@@ -451,7 +451,7 @@ public class DomainObjectResourceServerside extends 
ResourceAbstract implements
 
         val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, 
instanceId);
         val domainResourceHelper = 
DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter);
-        val accessHelper = new ObjectAdapterAccessHelper(resourceContext, 
objectAdapter);
+        val accessHelper = ObjectAdapterAccessHelper.of(resourceContext, 
objectAdapter);
 
         val property = 
accessHelper.getPropertyThatIsVisibleForIntent(propertyId,
                 ObjectInteractor.AccessIntent.MUTATE);
@@ -460,6 +460,8 @@ public class DomainObjectResourceServerside extends 
ResourceAbstract implements
                 .parseAsMapWithSingleValue(Util.asStringUtf8(body));
 
         val objectInteractor = ObjectInteractor.bind(objectAdapter);
+        
+        
         val iResponse = objectInteractor.modifyProperty(property, 
proposedNewValue);
         if (iResponse.isFailure()) {
             throw RestfulObjectsApplicationException
@@ -489,7 +491,7 @@ public class DomainObjectResourceServerside extends 
ResourceAbstract implements
 
         val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, 
instanceId);
         val domainResourceHelper = 
DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter);
-        val accessHelper = new ObjectAdapterAccessHelper(resourceContext, 
objectAdapter);
+        val accessHelper = ObjectAdapterAccessHelper.of(resourceContext, 
objectAdapter);
 
         val property = accessHelper.getPropertyThatIsVisibleForIntent(
                 propertyId, ObjectInteractor.AccessIntent.MUTATE);
@@ -551,7 +553,7 @@ public class DomainObjectResourceServerside extends 
ResourceAbstract implements
 
         val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, 
instanceId);
         val domainResourceHelper = 
DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter);
-        final ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        final ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final OneToManyAssociation collection = 
accessHelper.getCollectionThatIsVisibleForIntent(
                 collectionId, ObjectInteractor.AccessIntent.MUTATE);
@@ -590,7 +592,7 @@ public class DomainObjectResourceServerside extends 
ResourceAbstract implements
 
         val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, 
instanceId);
         val domainResourceHelper = 
DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter);
-        final ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        final ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final OneToManyAssociation collection = 
accessHelper.getCollectionThatIsVisibleForIntent(
                 collectionId, ObjectInteractor.AccessIntent.MUTATE);
@@ -629,7 +631,7 @@ public class DomainObjectResourceServerside extends 
ResourceAbstract implements
 
         val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, 
instanceId);
         val domainResourceHelper = 
DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter);
-        final ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        final ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final OneToManyAssociation collection = 
accessHelper.getCollectionThatIsVisibleForIntent(
                 collectionId, ObjectInteractor.AccessIntent.MUTATE);
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
index b82338d..279e5ab 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
@@ -107,7 +107,7 @@ class DomainResourceHelper {
             final String propertyId,
             final MemberReprMode memberMode) {
 
-        ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final OneToOneAssociation property = 
accessHelper.getPropertyThatIsVisibleForIntent(propertyId, 
ObjectInteractor.AccessIntent.ACCESS);
 
@@ -125,7 +125,7 @@ class DomainResourceHelper {
             final String collectionId,
             final MemberReprMode memberMode) {
 
-        ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final OneToManyAssociation collection = 
accessHelper.getCollectionThatIsVisibleForIntent(collectionId, 
ObjectInteractor.AccessIntent.ACCESS);
 
@@ -141,7 +141,7 @@ class DomainResourceHelper {
      */
     public Response actionPrompt(final String actionId) {
 
-        ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final ObjectAction action = 
accessHelper.getObjectActionThatIsVisibleForIntent(actionId, 
ObjectInteractor.AccessIntent.ACCESS);
 
@@ -161,7 +161,7 @@ class DomainResourceHelper {
      */
     public Response invokeActionQueryOnly(final String actionId, final 
JsonRepresentation arguments) {
 
-        final ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        final ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final ObjectAction action = 
accessHelper.getObjectActionThatIsVisibleForIntent(actionId, 
ObjectInteractor.AccessIntent.MUTATE);
 
@@ -185,7 +185,7 @@ class DomainResourceHelper {
      */
     public Response invokeActionIdempotent(final String actionId, final 
JsonRepresentation arguments) {
 
-        final ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        final ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final ObjectAction action = 
accessHelper.getObjectActionThatIsVisibleForIntent(actionId, 
ObjectInteractor.AccessIntent.MUTATE);
 
@@ -203,7 +203,7 @@ class DomainResourceHelper {
      */
     public Response invokeAction(final String actionId, final 
JsonRepresentation arguments) {
 
-        ObjectAdapterAccessHelper accessHelper = new 
ObjectAdapterAccessHelper(resourceContext, objectAdapter);
+        ObjectAdapterAccessHelper accessHelper = 
ObjectAdapterAccessHelper.of(resourceContext, objectAdapter);
 
         final ObjectAction action = 
accessHelper.getObjectActionThatIsVisibleForIntent(actionId, 
ObjectInteractor.AccessIntent.MUTATE);
 
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
index b8b8b2f..2785cee 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
@@ -19,28 +19,30 @@
 package org.apache.isis.viewer.restfulobjects.viewer.resources;
 
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.core.metamodel.consent.Consent;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 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.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import 
org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse;
+import 
org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor;
 import 
org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent;
 import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse;
 import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
 import 
org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 import 
org.apache.isis.viewer.restfulobjects.rendering.domainobjects.MemberType;
 
+import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 /**
  * Utility class that encapsulates the logic for checking access to the 
specified
  * {@link ManagedObject}'s members.
  */
+@RequiredArgsConstructor
 public class ObjectAdapterAccessHelper {
 
-    public static RestfulObjectsApplicationException notFoundException(final 
String memberId, final MemberType memberType) {
+    public static RestfulObjectsApplicationException notFoundException(
+            final String memberId, final MemberType memberType) {
         final String memberTypeStr = memberType.name().toLowerCase();
         return RestfulObjectsApplicationException.createWithMessage(
                 RestfulResponse.HttpStatusCode.NOT_FOUND, 
@@ -48,78 +50,67 @@ public class ObjectAdapterAccessHelper {
                 memberTypeStr,
                 memberId);
     }
-
-    private final ManagedObject objectAdapter;
-    private final IResourceContext resourceContext;
-
-    public ObjectAdapterAccessHelper(IResourceContext resourceContext, 
ManagedObject objectAdapter) {
-        this.objectAdapter = objectAdapter;
-        this.resourceContext = resourceContext;
+    
+    public static ObjectAdapterAccessHelper of(
+            final IResourceContext resourceContext,
+            final ManagedObject managedObject) {
+        return new ObjectAdapterAccessHelper(
+                ObjectInteractor.bind(managedObject),
+                resourceContext.getWhere());
     }
 
+    private final ObjectInteractor objectInteractor;
+    private final Where where;
+
     public OneToOneAssociation getPropertyThatIsVisibleForIntent(
             final String propertyId, final AccessIntent intent) {
+        
+        val propertyInteractor = objectInteractor.getPropertyInteractor();
+        
+        val check = 
propertyInteractor.getPropertyThatIsVisibleForIntent(propertyId, where, intent);
+        check.right()
+        .ifPresent(failure->handleFailure(failure, propertyId, 
MemberType.PROPERTY));
 
-        val spec = objectAdapter.getSpecification();
-        val association = spec.getAssociation(propertyId)
-                .orElseThrow(()->notFoundException(propertyId, 
MemberType.PROPERTY));
-
-        if (!association.isOneToOneAssociation()) {
-            throw notFoundException(propertyId, MemberType.PROPERTY);
-        }
-
-        final OneToOneAssociation property = (OneToOneAssociation) association;
-        return memberThatIsVisibleForIntent(property, MemberType.PROPERTY, 
intent);
+        return check.leftIfAny();
     }
 
     public OneToManyAssociation getCollectionThatIsVisibleForIntent(
             final String collectionId, final AccessIntent intent) {
-
-        val spec = objectAdapter.getSpecification();
-        val association = spec.getAssociation(collectionId)
-                .orElseThrow(()->notFoundException(collectionId, 
MemberType.COLLECTION));
         
-        if (!association.isOneToManyAssociation()) {
-            throw notFoundException(collectionId, MemberType.COLLECTION);
-        }
+        val propertyInteractor = objectInteractor.getCollectionInteractor();
         
-        final OneToManyAssociation collection = (OneToManyAssociation) 
association;
-        return memberThatIsVisibleForIntent(collection, MemberType.COLLECTION, 
intent);
+        val check = 
propertyInteractor.getPropertyThatIsVisibleForIntent(collectionId, where, 
intent);
+        check.right()
+        .ifPresent(failure->handleFailure(failure, collectionId, 
MemberType.COLLECTION));
+
+        return check.leftIfAny();
     }
 
     public ObjectAction getObjectActionThatIsVisibleForIntent(
             final String actionId, final AccessIntent intent) {
 
-        val spec = objectAdapter.getSpecification();
-        val action = spec.getObjectAction(actionId)
-                .orElseThrow(()->notFoundException(actionId, 
MemberType.ACTION));
+        val actionInteractor = objectInteractor.getActionInteractor();
+        
+        val check = actionInteractor.getActionThatIsVisibleForIntent(actionId, 
where, intent);
+        check.right()
+        .ifPresent(failure->handleFailure(failure, actionId, 
MemberType.ACTION));
 
-        return memberThatIsVisibleForIntent(action, MemberType.ACTION, intent);
+        return check.leftIfAny();
     }
 
-    public <T extends ObjectMember> T memberThatIsVisibleForIntent(
-            final T objectMember, final MemberType memberType, final 
AccessIntent intent) {
-
-        final Where where = resourceContext.getWhere();
-
-        final String memberId = objectMember.getId();
-        final Consent visibilityConsent =
-                objectMember.isVisible(
-                        objectAdapter, InteractionInitiatedBy.USER, where);
-        if (visibilityConsent.isVetoed()) {
-            throw notFoundException(memberId, memberType);
-        }
-        if (intent.isMutate()) {
-            final Consent usabilityConsent = objectMember.isUsable(
-                    objectAdapter, InteractionInitiatedBy.USER, where
-                    );
-            if (usabilityConsent.isVetoed()) {
-                throw 
RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.FORBIDDEN,
-                        usabilityConsent.getReason());
-            }
+    private void handleFailure(final InteractionResponse failure, String 
memberId, MemberType memberType) {
+        switch(failure.getVeto()) {
+        case NOT_FOUND:
+        case HIDDEN:
+            throw RestfulObjectsApplicationException
+            .createWithMessage(RestfulResponse.HttpStatusCode.NOT_FOUND,
+                    failure.getFailureMessage());
+        case UNAUTHORIZED:
+        case FORBIDDEN:
+            throw RestfulObjectsApplicationException
+            .createWithMessage(RestfulResponse.HttpStatusCode.FORBIDDEN,
+                    failure.getFailureMessage());
         }
-        return objectMember;
     }
-
-
+    
 }

Reply via email to