diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java index 373684999714fadd99c323f4364e7d8b128523dd..a4c4f996d165ade3c66df09109b5bab80674a2c3 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApi.java @@ -39,6 +39,7 @@ import ch.ethz.sis.openbis.generic.server.api.v3.executor.experiment.IDeleteExpe import ch.ethz.sis.openbis.generic.server.api.v3.executor.experiment.IMapExperimentByIdExecutor; import ch.ethz.sis.openbis.generic.server.api.v3.executor.experiment.ISearchExperimentExecutor; import ch.ethz.sis.openbis.generic.server.api.v3.executor.experiment.IUpdateExperimentExecutor; +import ch.ethz.sis.openbis.generic.server.api.v3.executor.material.IDeleteMaterialExecutor; import ch.ethz.sis.openbis.generic.server.api.v3.executor.material.IMapMaterialByIdExecutor; import ch.ethz.sis.openbis.generic.server.api.v3.executor.sample.ICreateSampleExecutor; import ch.ethz.sis.openbis.generic.server.api.v3.executor.sample.IDeleteSampleExecutor; @@ -64,6 +65,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.IApplicationServerApi; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.Deletion; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.dataset.DataSetDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.experiment.ExperimentDeletionOptions; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.material.MaterialDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.sample.SampleDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.space.SpaceDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSet; @@ -174,6 +176,9 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi> @Autowired private ISearchSpaceExecutor searchSpaceExecutor; + @Autowired + private IDeleteMaterialExecutor deleteMaterialsExecutor; + @Autowired private ISearchExperimentExecutor searchExperimentExecutor; @@ -599,6 +604,10 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi> } @Override + @Transactional + @DatabaseCreateOrDeleteModification(value = { ObjectKind.DATA_SET, ObjectKind.DELETION }) + @RolesAllowed({ RoleWithHierarchy.SPACE_POWER_USER, RoleWithHierarchy.SPACE_ETL_SERVER }) + @Capability("DELETE_DATA_SET") public IDeletionId deleteDataSets(String sessionToken, List<? extends IDataSetId> dataSetIds, DataSetDeletionOptions deletionOptions) { Session session = getSession(sessionToken); @@ -615,6 +624,27 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi> } } + @Override + @Transactional + @DatabaseCreateOrDeleteModification(value = { ObjectKind.MATERIAL, ObjectKind.DELETION }) + @RolesAllowed({ RoleWithHierarchy.INSTANCE_ADMIN, RoleWithHierarchy.INSTANCE_ETL_SERVER }) + @Capability("DELETE_MATERIAL") + public void deleteMaterials(String sessionToken, List<? extends IMaterialId> materialIds, MaterialDeletionOptions deletionOptions) + { + Session session = getSession(sessionToken); + OperationContext context = new OperationContext(session); + try + { + deleteMaterialsExecutor.delete(context, materialIds, deletionOptions); + } catch (Throwable t) + { + throw ExceptionUtils.create(context, t); + } finally + { + getDAOFactory().getSessionFactory().getCurrentSession().clear(); + } + } + @Override @Transactional @DatabaseCreateOrDeleteModification(value = { ObjectKind.SAMPLE, ObjectKind.DELETION }) diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApiLogger.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApiLogger.java index d77147dedc1f46fbc98aae47933d8a7f6f663308..2a920046ecc98b751a3378af6ef285bb1c33725c 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApiLogger.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/ApplicationServerApiLogger.java @@ -23,6 +23,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.IApplicationServerApi; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.Deletion; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.dataset.DataSetDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.experiment.ExperimentDeletionOptions; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.material.MaterialDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.sample.SampleDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.space.SpaceDeletionOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSet; @@ -262,4 +263,10 @@ public class ApplicationServerApiLogger extends AbstractServerLogger implements logAccess(sessionToken, "confirm-deletions", "DELETION_IDS(%s)", deletionIds); } + @Override + public void deleteMaterials(String sessionToken, List<? extends IMaterialId> materialIds, MaterialDeletionOptions deletionOptions) + { + logAccess(sessionToken, "delete-materials", "MATERIAL_IDS(%s) DELETION_OPTIONS(%s)", materialIds, deletionOptions); + } + } diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/material/DeleteMaterialExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/material/DeleteMaterialExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..5247135ec4ec7cdc51c1cfef8d1e964599777199 --- /dev/null +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/material/DeleteMaterialExecutor.java @@ -0,0 +1,80 @@ +/* + * Copyright 2014 ETH Zuerich, Scientific IT Services + * + * Licensed 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 ch.ethz.sis.openbis.generic.server.api.v3.executor.material; + +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import ch.ethz.sis.openbis.generic.server.api.v3.executor.IOperationContext; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.material.MaterialDeletionOptions; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.material.IMaterialId; +import ch.systemsx.cisd.openbis.generic.server.ComponentNames; +import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory; +import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO; +import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; +import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE; + +/** + * @author Jakub Straszewski + */ +@Component +public class DeleteMaterialExecutor implements IDeleteMaterialExecutor +{ + + @Resource(name = ComponentNames.COMMON_BUSINESS_OBJECT_FACTORY) + ICommonBusinessObjectFactory businessObjectFactory; + + @Autowired + IMapMaterialByIdExecutor mapMaterialByIdExecutor; + + @Override + public void delete(IOperationContext context, List<? extends IMaterialId> materialIds, MaterialDeletionOptions deletionOptions) + { + if (context == null) + { + throw new IllegalArgumentException("Context cannot be null"); + } + if (materialIds == null) + { + throw new IllegalArgumentException("Space ids cannot be null"); + } + if (deletionOptions == null) + { + throw new IllegalArgumentException("Deletion options cannot be null"); + } + if (deletionOptions.getReason() == null) + { + throw new IllegalArgumentException("Deletion reason cannot be null"); + } + + IMaterialBO materialBO = businessObjectFactory.createMaterialBO(context.getSession()); + Map<IMaterialId, MaterialPE> materialMap = mapMaterialByIdExecutor.map(context, materialIds); + + for (Map.Entry<IMaterialId, MaterialPE> entry : materialMap.entrySet()) + { + MaterialPE material = entry.getValue(); + + materialBO.deleteByTechId(new TechId(material.getId()), deletionOptions.getReason()); + } + } + +} diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/material/IDeleteMaterialExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/material/IDeleteMaterialExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..0b71caf772bd68c24a253ae4aa23d7b18c6ee056 --- /dev/null +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/material/IDeleteMaterialExecutor.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 ETH Zuerich, CISD + * + * Licensed 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 ch.ethz.sis.openbis.generic.server.api.v3.executor.material; + +import java.util.List; + +import ch.ethz.sis.openbis.generic.server.api.v3.executor.IOperationContext; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.material.MaterialDeletionOptions; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.material.IMaterialId; + +/** + * @author Jakub Straszewski + */ +public interface IDeleteMaterialExecutor +{ + public void delete(IOperationContext context, List<? extends IMaterialId> materialIds, MaterialDeletionOptions deletionOptions); + +} diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/AbstractDeletionTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/AbstractDeletionTest.java index edcc4f6901407cef7525b01301268d9c8792a8bc..cffda5d2c1c68084ed32bb752ea2e741cfd9d369 100644 --- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/AbstractDeletionTest.java +++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/AbstractDeletionTest.java @@ -26,16 +26,19 @@ import junit.framework.Assert; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.Deletion; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.experiment.Experiment; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.experiment.ExperimentCreation; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.material.Material; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.sample.Sample; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.sample.SampleCreation; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.deletion.DeletionFetchOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.experiment.ExperimentFetchOptions; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.material.MaterialFetchOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sample.SampleFetchOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.DataSetPermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.deletion.IDeletionId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.entitytype.EntityTypePermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentPermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.IExperimentId; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.material.IMaterialId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.project.ProjectIdentifier; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.ISampleId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SamplePermId; @@ -122,6 +125,23 @@ public class AbstractDeletionTest extends AbstractTest Assert.assertEquals(exists ? 1 : 0, map.size()); } + protected void assertMaterialExists(IMaterialId materialId) + { + assertMaterialExists(materialId, true); + } + + protected void assertMaterialDoesNotExist(IMaterialId materialId) + { + assertMaterialExists(materialId, false); + } + + private void assertMaterialExists(IMaterialId materialId, boolean exists) + { + String sessionToken = v3api.login(TEST_USER, PASSWORD); + Map<IMaterialId, Material> map = v3api.mapMaterials(sessionToken, Collections.singletonList(materialId), new MaterialFetchOptions()); + Assert.assertEquals(exists ? 1 : 0, map.size()); + } + protected void assertDataSetExists(DataSetPermId dataSetId) { assertDataSetExists(dataSetId, true); diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/DeleteMaterialsTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/DeleteMaterialsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..814d1085095838113e452f9e97de8ed320af821a --- /dev/null +++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/DeleteMaterialsTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 ETH Zuerich, Scientific IT Services + * + * Licensed 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 ch.ethz.sis.openbis.systemtest.api.v3; + +import java.util.Collections; + +import org.testng.annotations.Test; + +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.deletion.material.MaterialDeletionOptions; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.material.MaterialPermId; +import ch.systemsx.cisd.common.action.IDelegatedAction; + +/** + * @author Jakub Straszewski + */ +public class DeleteMaterialsTest extends AbstractDeletionTest +{ + + private static MaterialDeletionOptions options; + + public static MaterialDeletionOptions getOptions() + { + if (options == null) + { + options = new MaterialDeletionOptions(); + options.setReason("Just for testing"); + } + return options; + } + + @Test + public void testDeleteMaterial() + { + String sessionToken = v3api.login(TEST_USER, PASSWORD); + MaterialPermId materialId = new MaterialPermId("796", "GENE"); + v3api.deleteMaterials(sessionToken, Collections.singletonList(materialId), getOptions()); + assertMaterialDoesNotExist(materialId); + } + + @Test + public void testDeleteMaterialLinkedAsAProperty() + { + final String sessionToken = v3api.login(TEST_USER, PASSWORD); + final MaterialPermId materialId = new MaterialPermId("BACTERIUM-X", "BACTERIUM"); + + assertUserFailureException(new IDelegatedAction() + { + + @Override + public void execute() + { + v3api.deleteMaterials(sessionToken, Collections.singletonList(materialId), getOptions()); + } + }, "BACTERIUM-X (BACTERIUM) is being used. Delete all connected data first."); + + } +}