From 9ce41a75d440cfd5c97bb288ba9901a15bd4a36a Mon Sep 17 00:00:00 2001
From: felmer <franz-josef.elmer@id.ethz.ch>
Date: Thu, 14 Nov 2019 09:28:28 +0100
Subject: [PATCH] SSDM-4600: GetRightsExecutor refactored. Checking experiment
 creation right implemented. tests added to GetRightsTest

---
 .../v3/executor/rights/GetRightsExecutor.java | 237 ++++++++++++------
 .../systemtest/asapi/v3/GetRightsTest.java    |  54 ++--
 2 files changed, 194 insertions(+), 97 deletions(-)

diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/rights/GetRightsExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/rights/GetRightsExecutor.java
index d0756a2fc6f..77bcd6fdfe3 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/rights/GetRightsExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/rights/GetRightsExecutor.java
@@ -18,8 +18,11 @@ package ch.ethz.sis.openbis.generic.server.asapi.v3.executor.rights;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -29,9 +32,11 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.CreationId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.IObjectId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.IDataSetId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentIdentifier;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.IExperimentId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.id.ProjectIdentifier;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.rights.Right;
@@ -59,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
 
 /**
  * @author Franz-Josef Elmer
@@ -94,14 +100,19 @@ public class GetRightsExecutor implements IGetRightsExecutor
     public Map<IObjectId, Rights> getRights(IOperationContext context, List<? extends IObjectId> objectIds, RightsFetchOptions fetchOptions)
     {
         Map<IObjectId, Rights> result = new HashMap<>();
-        List<IHandler> handlers = createHandlers();
+        Map<Class<? extends IObjectId>, IHandler> handlersByObjectIdClass = getHandlersByObjectIdClassMap();
         for (IObjectId id : objectIds)
         {
-            for (IHandler handler : handlers)
+            if (id != null)
             {
-                handler.handle(id);
+                IHandler handler = handlersByObjectIdClass.get(id.getClass());
+                if (handler != null)
+                {
+                    handler.handle(id);
+                }
             }
         }
+        Set<IHandler> handlers = new LinkedHashSet<>(handlersByObjectIdClass.values());
         for (IHandler handler : handlers)
         {
             handler.addRights(context, result);
@@ -109,9 +120,21 @@ public class GetRightsExecutor implements IGetRightsExecutor
         return result;
     }
 
-    private List<IHandler> createHandlers()
+    private Map<Class<? extends IObjectId>, IHandler> getHandlersByObjectIdClassMap()
     {
-        return Arrays.asList(new SampleHandler(), new ExperimentHandler(), new DataSetHandler());
+        Map<Class<? extends IObjectId>, IHandler> map = new LinkedHashMap<>();
+
+        IHandler sampleHandler = new SampleHandler();
+        map.put(SampleIdentifier.class, sampleHandler);
+        map.put(SamplePermId.class, sampleHandler);
+
+        IHandler experimentHandler = new ExperimentHandler();
+        map.put(ExperimentIdentifier.class, experimentHandler);
+        map.put(ExperimentPermId.class, experimentHandler);
+
+        IHandler dataSetHandler = new DataSetHandler();
+        map.put(DataSetPermId.class, dataSetHandler);
+        return map;
     }
 
     private static interface IHandler
@@ -121,48 +144,55 @@ public class GetRightsExecutor implements IGetRightsExecutor
         void addRights(IOperationContext context, Map<IObjectId, Rights> rightsByIds);
     }
 
-    private class SampleHandler implements IHandler
+    private static abstract class AbstractHandler<ID extends IObjectId, ENTITY> implements IHandler
     {
-        private List<ISampleId> sampleIds = new ArrayList<>();
+        private Class<ID> idClass;
+
+        private List<ID> ids = new ArrayList<>();
+
+        AbstractHandler(Class<ID> idClass)
+        {
+            this.idClass = idClass;
+        }
 
+        @SuppressWarnings("unchecked")
         @Override
         public void handle(IObjectId id)
         {
-            if (id instanceof ISampleId)
+            if (idClass.isAssignableFrom(id.getClass()))
             {
-                sampleIds.add((ISampleId) id);
+                ids.add((ID) id);
             }
         }
 
         @Override
         public void addRights(IOperationContext context, Map<IObjectId, Rights> rightsByIds)
         {
-            Map<ISampleId, SamplePE> map = mapSampleByIdExecutor.map(context, sampleIds);
-            Set<ISampleId> unknownSamples = new HashSet<>(sampleIds);
-            for (Entry<ISampleId, SamplePE> entry : map.entrySet())
+            Map<ID, ENTITY> entitiesByIds = getEntitiesByIds(context, ids);
+            Set<ID> unknownIds = new HashSet<>(ids);
+            for (Entry<ID, ENTITY> entry : entitiesByIds.entrySet())
             {
                 Set<Right> rights = new HashSet<>();
-                ISampleId id = entry.getKey();
-                SamplePE object = entry.getValue();
-
+                ID id = entry.getKey();
+                ENTITY entity = entry.getValue();
                 try
                 {
-                    sampleAuthorizationExecutor.canUpdate(context, id, object);
+                    canUpdate(context, id, entity);
                     rights.add(Right.UPDATE);
                 } catch (AuthorizationFailureException e)
                 {
                     // silently ignored
                 }
                 rightsByIds.put(id, new Rights(rights));
-                unknownSamples.remove(id);
+                unknownIds.remove(id);
             }
-            for (ISampleId id : unknownSamples)
+            for (ID id : unknownIds)
             {
                 Set<Right> rights = new HashSet<>();
                 try
                 {
-                    SamplePE sample = createDummySample(context, id);
-                    sampleAuthorizationExecutor.canCreate(context, sample);
+                    ENTITY entity = createDummyEntity(context, id);
+                    canCreate(context, entity);
                     rights.add(Right.CREATE);
                 } catch (AuthorizationFailureException e)
                 {
@@ -171,95 +201,142 @@ public class GetRightsExecutor implements IGetRightsExecutor
                 rightsByIds.put(id, new Rights(rights));
             }
         }
+
+        abstract Map<ID, ENTITY> getEntitiesByIds(IOperationContext context, Collection<ID> ids);
+
+        abstract void canUpdate(IOperationContext context, ID id, ENTITY entity);
+
+        abstract ENTITY createDummyEntity(IOperationContext context, ID id);
+
+        abstract void canCreate(IOperationContext context, ENTITY entity);
+
     }
 
-    private SamplePE createDummySample(IOperationContext context, ISampleId sampleId)
+    private class SampleHandler extends AbstractHandler<ISampleId, SamplePE>
     {
-        if (sampleId == null)
-        {
-            throw new UserFailureException("Unspecified sample id.");
-        }
-        if (sampleId instanceof CreationId)
+        SampleHandler()
         {
-            throw new UserFailureException("Sample id '" + sampleId + "' can not be a CreationId.");
+            super(ISampleId.class);
         }
-        if (sampleId instanceof SamplePermId)
+
+        @Override
+        Map<ISampleId, SamplePE> getEntitiesByIds(IOperationContext context, Collection<ISampleId> ids)
         {
-            throw new UserFailureException("Sample id '" + sampleId + "' can not be a SamplePermId.");
+            return mapSampleByIdExecutor.map(context, ids);
         }
-        if (sampleId instanceof SampleIdentifier == false)
+
+        @Override
+        void canUpdate(IOperationContext context, ISampleId id, SamplePE entity)
         {
-            throw new UserFailureException("Sample id '" + sampleId + "' is of unknown type "
-                    + sampleId.getClass().getName() + ".");
+            sampleAuthorizationExecutor.canUpdate(context, id, entity);
         }
-        SpacePE homeSpace = context.getSession().tryGetHomeGroup();
-        FullSampleIdentifier sampleIdentifier = new FullSampleIdentifier(((SampleIdentifier) sampleId).getIdentifier(),
-                homeSpace == null ? null : homeSpace.getCode());
-        SampleIdentifierParts parts = sampleIdentifier.getParts();
-        SamplePE samplePE = new SamplePE();
-        samplePE.setCode(sampleIdentifier.getSampleCode());
-        String spaceCode = parts.getSpaceCodeOrNull();
-        if (StringUtils.isNotBlank(spaceCode))
+
+        @Override
+        SamplePE createDummyEntity(IOperationContext context, ISampleId sampleId)
         {
-            SpacePermId spacePermId = new SpacePermId(spaceCode);
-            SpacePE spacePE = mapSpaceByIdExecutor.map(context, Arrays.asList(spacePermId)).get(spacePermId);
-            if (spacePE == null)
+            if (sampleId instanceof SamplePermId)
             {
-                throw new UserFailureException("Unknown space in sample identifier '" + sampleId + "'.");
+                throw new UserFailureException("Unknown sample with perm id " + sampleId + ".");
             }
-            samplePE.setSpace(spacePE);
-        }
-        String projectCode = parts.getProjectCodeOrNull();
-        if (StringUtils.isNotBlank(projectCode))
-        {
-            if (StringUtils.isBlank(spaceCode))
+            if (sampleId instanceof SampleIdentifier == false)
             {
-                throw new UserFailureException("Unknown space in sample identifier '" + sampleId + "'.");
+                throw new UserFailureException("Sample identifier of unsupported type ("
+                        + sampleId.getClass().getName() + "): " + sampleId);
             }
-            ProjectIdentifier projectIdentifier = new ProjectIdentifier(spaceCode, projectCode);
-            ProjectPE projectPE = mapProjectByIdExecutor.map(context, Arrays.asList(projectIdentifier)).get(projectIdentifier);
-            if (projectPE == null)
+            SpacePE homeSpace = context.getSession().tryGetHomeGroup();
+            FullSampleIdentifier sampleIdentifier = new FullSampleIdentifier(((SampleIdentifier) sampleId).getIdentifier(),
+                    homeSpace == null ? null : homeSpace.getCode());
+            SampleIdentifierParts parts = sampleIdentifier.getParts();
+            SamplePE samplePE = new SamplePE();
+            samplePE.setCode(sampleIdentifier.getSampleCode());
+            String spaceCode = parts.getSpaceCodeOrNull();
+            if (StringUtils.isNotBlank(spaceCode))
             {
-                throw new UserFailureException("Unknown project in sample identifier '" + sampleId + "'.");
+                SpacePermId spacePermId = new SpacePermId(spaceCode);
+                SpacePE spacePE = mapSpaceByIdExecutor.map(context, Arrays.asList(spacePermId)).get(spacePermId);
+                if (spacePE == null)
+                {
+                    throw new UserFailureException("Unknown space in sample identifier '" + sampleId + "'.");
+                }
+                samplePE.setSpace(spacePE);
+            }
+            String projectCode = parts.getProjectCodeOrNull();
+            if (StringUtils.isNotBlank(projectCode))
+            {
+                if (StringUtils.isBlank(spaceCode))
+                {
+                    throw new UserFailureException("Unknown space in sample identifier '" + sampleId + "'.");
+                }
+                ProjectIdentifier projectIdentifier = new ProjectIdentifier(spaceCode, projectCode);
+                ProjectPE projectPE = mapProjectByIdExecutor.map(context, Arrays.asList(projectIdentifier)).get(projectIdentifier);
+                if (projectPE == null)
+                {
+                    throw new UserFailureException("Unknown project in sample identifier '" + sampleId + "'.");
+                }
+                samplePE.setProject(projectPE);
             }
-            samplePE.setProject(projectPE);
+            return samplePE;
+        }
+
+        @Override
+        void canCreate(IOperationContext context, SamplePE sample)
+        {
+            sampleAuthorizationExecutor.canCreate(context, sample);
         }
-        return samplePE;
     }
 
-    private class ExperimentHandler implements IHandler
+    private class ExperimentHandler extends AbstractHandler<IExperimentId, ExperimentPE>
     {
-        private List<IExperimentId> experimentIds = new ArrayList<>();
+        ExperimentHandler()
+        {
+            super(IExperimentId.class);
+        }
 
         @Override
-        public void handle(IObjectId id)
+        Map<IExperimentId, ExperimentPE> getEntitiesByIds(IOperationContext context, Collection<IExperimentId> ids)
         {
-            if (id instanceof IExperimentId)
-            {
-                experimentIds.add((IExperimentId) id);
-            }
+            return mapExperimentByIdExecutor.map(context, ids);
         }
 
         @Override
-        public void addRights(IOperationContext context, Map<IObjectId, Rights> rightsByIds)
+        void canUpdate(IOperationContext context, IExperimentId id, ExperimentPE entity)
+        {
+            experimentAuthorizationExecutor.canUpdate(context, id, entity);
+        }
+
+        @Override
+        ExperimentPE createDummyEntity(IOperationContext context, IExperimentId id)
         {
-            Map<IExperimentId, ExperimentPE> map = mapExperimentByIdExecutor.map(context, experimentIds);
-            for (Entry<IExperimentId, ExperimentPE> entry : map.entrySet())
+            if (id instanceof ExperimentPermId)
             {
-                Set<Right> rights = new HashSet<>();
-                IExperimentId id = entry.getKey();
-                ExperimentPE object = entry.getValue();
+                throw new UserFailureException("Unknown experiment with perm id " + id + ".");
+            }
+            if (id instanceof ExperimentIdentifier == false)
+            {
+                throw new UserFailureException("Experiment identifier of unsupported type ("
+                        + id.getClass().getName() + "): " + id);
+            }
 
-                try
-                {
-                    experimentAuthorizationExecutor.canUpdate(context, id, object);
-                    rights.add(Right.UPDATE);
-                } catch (AuthorizationFailureException e)
-                {
-                    // silently ignored
-                }
-                rightsByIds.put(id, new Rights(rights));
+            ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier expeId =
+                    ExperimentIdentifierFactory.parse(((ExperimentIdentifier) id).getIdentifier());
+
+            ProjectIdentifier projectIdentifier = new ProjectIdentifier(expeId.getSpaceCode(), expeId.getProjectCode());
+            ProjectPE projectPE = mapProjectByIdExecutor.map(context, Arrays.asList(projectIdentifier)).get(projectIdentifier);
+            if (projectPE == null)
+            {
+                throw new UserFailureException("Unknown project in experiment identifier '" + id + "'.");
             }
+            ExperimentPE experimentPE = new ExperimentPE();
+            experimentPE.setProject(projectPE);
+            experimentPE.setCode(expeId.getExperimentCode());
+            return experimentPE;
+        }
+
+        @Override
+        void canCreate(IOperationContext context, ExperimentPE entity)
+        {
+            experimentAuthorizationExecutor.canCreate(context, entity);
+
         }
     }
 
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetRightsTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetRightsTest.java
index 3d393cd59c4..d8bdb27da09 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetRightsTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetRightsTest.java
@@ -27,6 +27,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.CreationId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.IObjectId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentIdentifier;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.rights.Rights;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.rights.fetchoptions.RightsFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.id.SampleIdentifier;
@@ -47,9 +48,10 @@ public class GetRightsTest extends AbstractTest
         IObjectId s3 = new SampleIdentifier("/CISD/NEW");
         IObjectId s4 = new SampleIdentifier("/CISD/NEMO/NEW");
         IObjectId s5 = new SampleIdentifier("/TEST-SPACE/NOE/NEW");
+        IObjectId s6 = new CreationId("123-45");
 
         // When
-        Map<IObjectId, Rights> map = v3api.getRights(sessionToken, Arrays.asList(s1, s2, s3, s4, s5), new RightsFetchOptions());
+        Map<IObjectId, Rights> map = v3api.getRights(sessionToken, Arrays.asList(s1, s2, s3, s4, s5, s6), new RightsFetchOptions());
 
         // Then
         assertEquals(map.get(s1).getRights().toString(), "[]");
@@ -57,10 +59,11 @@ public class GetRightsTest extends AbstractTest
         assertEquals(map.get(s3).getRights().toString(), "[CREATE]");
         assertEquals(map.get(s4).getRights().toString(), "[CREATE]");
         assertEquals(map.get(s5).getRights().toString(), "[]");
+        assertEquals(map.size(), 5);
     }
 
     @Test
-    public void testGetSampleCreationRightForSamplePermId()
+    public void testGetSampleCreationRightForUnknownSamplePermId()
     {
         // Given
         String sessionToken = v3api.login(TEST_ROLE_V3, PASSWORD);
@@ -69,20 +72,7 @@ public class GetRightsTest extends AbstractTest
         // When
         assertUserFailureException(Void -> v3api.getRights(sessionToken, Arrays.asList(s1), new RightsFetchOptions()),
                 // Then
-                "Sample id '123-45' can not be a SamplePermId.");
-    }
-
-    @Test
-    public void testGetSampleCreationRightForCreationId()
-    {
-        // Given
-        String sessionToken = v3api.login(TEST_ROLE_V3, PASSWORD);
-        IObjectId s1 = new CreationId("123-45");
-
-        // When
-        assertUserFailureException(Void -> v3api.getRights(sessionToken, Arrays.asList(s1), new RightsFetchOptions()),
-                // Then
-                "Sample id '123-45' can not be a CreationId.");
+                "Unknown sample with perm id 123-45.");
     }
 
     @Test
@@ -118,13 +108,43 @@ public class GetRightsTest extends AbstractTest
         String sessionToken = v3api.login(TEST_ROLE_V3, PASSWORD);
         IObjectId s1 = new ExperimentIdentifier("/TEST-SPACE/TEST-PROJECT/EXP-SPACE-TEST");
         IObjectId s2 = new ExperimentIdentifier("/CISD/NEMO/EXP1");
+        IObjectId s3 = new ExperimentIdentifier("/CISD/NEMO/NEW");
+        IObjectId s4 = new ExperimentIdentifier("/TEST-SPACE/NOE/NEW");
 
         // When
-        Map<IObjectId, Rights> map = v3api.getRights(sessionToken, Arrays.asList(s1, s2), new RightsFetchOptions());
+        Map<IObjectId, Rights> map = v3api.getRights(sessionToken, Arrays.asList(s1, s2, s3, s4), new RightsFetchOptions());
 
         // Then
         assertEquals(map.get(s1).getRights().toString(), "[]");
         assertEquals(map.get(s2).getRights().toString(), "[UPDATE]");
+        assertEquals(map.get(s3).getRights().toString(), "[CREATE]");
+        assertEquals(map.get(s4).getRights().toString(), "[]");
+    }
+
+    @Test
+    public void testGetExperimentCreationRightForUnknownExperimentPermId()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_ROLE_V3, PASSWORD);
+        IObjectId s1 = new ExperimentPermId("123-45");
+
+        // When
+        assertUserFailureException(Void -> v3api.getRights(sessionToken, Arrays.asList(s1), new RightsFetchOptions()),
+                // Then
+                "Unknown experiment with perm id 123-45.");
+    }
+
+    @Test
+    public void testGetExperimentCreationRightInMissingProject()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_ROLE_V3, PASSWORD);
+        IObjectId s1 = new ExperimentIdentifier("/TEST-SPACE/NO-PROJECT/NEW");
+
+        // When
+        assertUserFailureException(Void -> v3api.getRights(sessionToken, Arrays.asList(s1), new RightsFetchOptions()),
+                // Then
+                "Unknown project in experiment identifier '/TEST-SPACE/NO-PROJECT/NEW'.");
     }
 
     @Test
-- 
GitLab