/* * Copyright 2010 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package integration.delete; import static omero.rtypes.rlong; import static omero.rtypes.rstring; import integration.AbstractServerTest; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import omero.RLong; import omero.RString; import omero.cmd.Delete2; import omero.gateway.util.Requests; import omero.model.Annotation; import omero.model.AnnotationAnnotationLink; import omero.model.AnnotationAnnotationLinkI; import omero.model.Channel; import omero.model.FileAnnotation; import omero.model.FileAnnotationI; import omero.model.IObject; import omero.model.Image; import omero.model.ImageAnnotationLink; import omero.model.ImageAnnotationLinkI; import omero.model.LongAnnotation; import omero.model.LongAnnotationI; import omero.model.OriginalFile; import omero.model.PlaneInfo; import omero.model.Roi; import omero.model.TagAnnotation; import omero.model.TagAnnotationI; import omero.sys.EventContext; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; /** * Tests for deleting user ratings. * * @see ticket:2997 * @see ticket:2994 * @since 4.2.1 */ @Test(groups = "ticket:2615") public class AnnotationDeleteTest extends AbstractServerTest { /** Reference to the <code>Rating</code> name space. */ public final static RString RATING = rstring(omero.constants.metadata.NSINSIGHTRATING.value); /** * Tests that the object, an annotation, and the link are all deleted. * * @param obj * The Object to annotate. * @param command * The command indicating the object to delete. * @param id * The identifier of the object to delete. */ private void annotateSaveDeleteAndCheck(IObject obj, String command, RLong id) throws Exception { annotateSaveDeleteAndCheck(obj, command, id, true); } /** * Tests that the object, the annotation link, and optionally the annotation * are all deleted. * * @param obj * The Object to annotate. * @param command * The command indicating the object to delete. * @param id * The identifier of the object to delete. * @param annIsDeleted * Pass <code>true</code> if the annotation is deleted, * <code>false</code> otherwise. */ private void annotateSaveDeleteAndCheck(IObject obj, String command, RLong id, boolean annIsDeleted) throws Exception { Annotation ann = (Annotation) iUpdate .saveAndReturnObject(new TagAnnotationI()); IObject link = mmFactory.createAnnotationLink(obj.proxy(), ann); link = iUpdate.saveAndReturnObject(link); final Delete2 dc = Requests.delete(command, id.getValue()); callback(true, client, dc); assertDoesNotExist(obj); assertDoesNotExist(link); if (annIsDeleted) { assertDoesNotExist(ann); } else { assertExists(ann); } } /** * Test to delete the file annotation of a given namespace. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = { "ticket:2994" }) public void testDeleteFileAnnotationOfGivenNamespace() throws Exception { newUserAndGroup("rw----"); List<RString> ns = new ArrayList<RString>(); ns.add(omero.rtypes.rstring("Test")); FileAnnotation fa; OriginalFile file; Iterator<RString> i = ns.iterator(); while (i.hasNext()) { fa = new FileAnnotationI(); fa.setNs(i.next()); fa.setFile(mmFactory.createOriginalFile()); fa = (FileAnnotation) iUpdate.saveAndReturnObject(fa); file = fa.getFile(); final Delete2 dc = Requests.delete("Annotation", fa.getId().getValue()); callback(true, client, dc); assertDoesNotExist(fa); assertDoesNotExist(file); } } /** * Test to make sure that the ratings linked to an image are deleted when * the image is deleted even if the ratings where made by others. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = "ticket:2997") public void testOtherUsersRatingsIsDeleted() throws Exception { EventContext owner = newUserAndGroup("rwrw--"); Image i1 = (Image) iUpdate.saveAndReturnObject(mmFactory.createImage()); disconnect(); newUserInGroup(owner); LongAnnotation rating = new LongAnnotationI(); rating.setNs(RATING); rating.setLongValue(rlong(1L)); ImageAnnotationLink link = new ImageAnnotationLinkI(); link.link((Image) i1.proxy(), rating); link = (ImageAnnotationLink) iUpdate.saveAndReturnObject(link); rating = (LongAnnotation) link.getChild(); disconnect(); loginUser(owner); final Delete2 dc = Requests.delete("Image", i1.getId().getValue()); callback(true, client, dc); assertDoesNotExist(i1); assertDoesNotExist(link); assertDoesNotExist(rating); disconnect(); } // // Tests for the less common annotated types // /** * Test to make sure that the annotations linked to an annotation are * deleted when the annotation is deleted. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = { "ticket:3002", "ticket:3015" }) public void testAnnotationsRemovedFromAnnotation() throws Exception { newUserAndGroup("rw----"); Annotation ann = (Annotation) iUpdate .saveAndReturnObject(new TagAnnotationI()); annotateSaveDeleteAndCheck(ann, Annotation.class.getSimpleName(), ann.getId()); } /** * Test to make sure that the annotations linked to a channel are deleted * when the channel is deleted. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = { "ticket:3002" }) public void testAnnotationsRemovedFromChannel() throws Exception { newUserAndGroup("rw----"); Image image = (Image) iUpdate.saveAndReturnObject(mmFactory .createImage()); Channel ch = image.getPrimaryPixels().getChannel(0); annotateSaveDeleteAndCheck(ch, Image.class.getSimpleName(), image.getId()); } /** * Test to make sure that the annotations linked to an original file are * deleted when the original file is deleted. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = { "ticket:3002" }) public void testAnnotationsRemovedFromOriginalFile() throws Exception { newUserAndGroup("rw----"); OriginalFile file = (OriginalFile) iUpdate .saveAndReturnObject(mmFactory.createOriginalFile()); annotateSaveDeleteAndCheck(file, OriginalFile.class.getSimpleName(), file.getId()); } /** * Test to make sure that the annotations linked to a plane info are deleted * when the plane info is deleted. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = { "ticket:3002" }) public void testAnnotationsRemovedFromPlaneInfo() throws Exception { newUserAndGroup("rw----"); Image image = (Image) iUpdate.saveAndReturnObject(mmFactory .createImage()); PlaneInfo info = image.getPixels(0).copyPlaneInfo().get(0); annotateSaveDeleteAndCheck(info, Image.class.getSimpleName(), image.getId()); } /** * Test to make sure that the annotations linked to an ROI are deleted when * the ROI is deleted. * * @throws Exception * Thrown if an error occurred. */ @Test(groups = { "ticket:3002" }) public void testAnnotationsRemovedFromRoi() throws Exception { newUserAndGroup("rw----"); Image image = (Image) iUpdate.saveAndReturnObject(mmFactory .createImageWithRoi()); Roi roi = image.copyRois().get(0); annotateSaveDeleteAndCheck(roi, Roi.class.getSimpleName(), roi.getId()); } /* child options to try using in deletion */ private enum Option { NONE, INCLUDE, EXCLUDE, BOTH }; /** * Test deletion of tag sets with variously linked tags. * @param option the child option to use in the deletion * @throws Exception unexpected */ @Test(dataProvider = "child option") public void testDeleteTargetSharedTag(Option option) throws Exception { /* ensure a connection to the server */ newUserAndGroup("rwra--"); /* create two tag sets */ final List<TagAnnotation> tagsets = new ArrayList<TagAnnotation>(); for (int i = 1; i <= 2; i++) { final TagAnnotation tagset = new TagAnnotationI(); tagset.setName(rstring("tagset #" + i)); tagset.setNs(rstring(omero.constants.metadata.NSINSIGHTTAGSET.value)); tagsets.add((TagAnnotation) iUpdate.saveAndReturnObject(tagset).proxy()); } /* create three tags */ final List<TagAnnotation> tags = new ArrayList<TagAnnotation>(); for (int i = 1; i <= 3; i++) { final TagAnnotation tag = new TagAnnotationI(); tag.setName(rstring("tag #" + i)); tags.add((TagAnnotation) iUpdate.saveAndReturnObject(tag).proxy()); } /* define how to link the tag sets to the tags */ final SetMultimap<TagAnnotation, TagAnnotation> members = HashMultimap.create(); members.put(tagsets.get(0), tags.get(0)); members.put(tagsets.get(0), tags.get(1)); members.put(tagsets.get(1), tags.get(1)); members.put(tagsets.get(1), tags.get(2)); /* perform the linking */ for (final Map.Entry<TagAnnotation, TagAnnotation> toLink : members.entries()) { final AnnotationAnnotationLink link = new AnnotationAnnotationLinkI(); link.setParent(toLink.getKey()); link.setChild(toLink.getValue()); iUpdate.saveObject(link); } /* delete the first tag set */ final Delete2 request; final Long tagset0Id = tagsets.get(0).getId().getValue(); switch (option) { case NONE: request = Requests.delete("Annotation", tagset0Id); break; case INCLUDE: request = Requests.delete("Annotation", tagset0Id, Requests.option("Annotation", null)); break; case EXCLUDE: request = Requests.delete("Annotation", tagset0Id, Requests.option(null, "Annotation")); break; case BOTH: request = Requests.delete("Annotation", tagset0Id, Requests.option("Annotation", "Annotation")); break; default: request = null; Assert.fail("unexpected option for delete"); } doChange(request); /* check that the tag set is deleted and the other remains */ assertDoesNotExist(tagsets.get(0)); assertExists(tagsets.get(1)); /* check that only the expected tags are deleted */ switch (option) { case NONE: assertDoesNotExist(tags.get(0)); assertExists(tags.get(1)); assertExists(tags.get(2)); break; case BOTH: /* include overrides exclude */ case INCLUDE: assertDoesNotExist(tags.get(0)); assertDoesNotExist(tags.get(1)); assertExists(tags.get(2)); break; case EXCLUDE: assertExists(tags.get(0)); assertExists(tags.get(1)); assertExists(tags.get(2)); /* delete the tag that is not in the second tag set */ doChange(Requests.delete("Annotation", tags.get(0).getId().getValue())); break; } /* delete the second tag set */ doChange(Requests.delete("Annotation", tagsets.get(1).getId().getValue())); /* check that the tag set and the remaining tags are deleted */ assertNoneExist(tagsets); assertNoneExist(tags); } /** * @return the child options to try using in deletion */ @DataProvider(name = "child option") public Object[][] provideChildOption() { final Option[] values = Option.values(); final Object[][] testCases = new Object[values.length][1]; int index = 0; for (final Option value : values) { testCases[index++][0] = value; } return testCases; } }