/* * Copyright (C) 2015-2016 University of Dundee & Open Microscopy Environment. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package integration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import omero.RLong; import omero.RString; import omero.RType; import omero.ServerError; import omero.cmd.Delete2; import omero.cmd.Duplicate; import omero.cmd.DuplicateResponse; import omero.cmd.ERR; import omero.cmd.SkipHead; import omero.gateway.util.Requests; import omero.model.Annotation; import omero.model.AnnotationAnnotationLink; import omero.model.AnnotationAnnotationLinkI; import omero.model.Channel; import omero.model.Dataset; import omero.model.DatasetImageLink; import omero.model.DatasetImageLinkI; import omero.model.DoubleAnnotationI; import omero.model.Ellipse; import omero.model.EllipseI; 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.ImageI; import omero.model.Line; import omero.model.LineI; import omero.model.LogicalChannel; import omero.model.LongAnnotation; import omero.model.LongAnnotationI; import omero.model.MapAnnotationI; import omero.model.Pixels; import omero.model.PlaneInfo; import omero.model.Point; import omero.model.PointI; import omero.model.Rectangle; import omero.model.RectangleI; import omero.model.Roi; import omero.model.RoiI; import omero.model.Shape; import omero.model.StatsInfo; import omero.model.TagAnnotationI; import omero.model.TextAnnotation; import omero.model.XmlAnnotationI; import omero.sys.Parameters; import omero.sys.ParametersI; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.SetMultimap; import com.google.common.collect.Sets; /** * Tests that {@link Duplicate} behaves as expected. * @author m.t.b.carroll@dundee.ac.uk * @since 5.2.1 */ public class DuplicationTest extends AbstractServerTest { /** * A <em>Z</em>, <em>T</em>, <em>C</em> key for indexing {@link PlaneInfo} instances in hash tables. * @author m.t.b.carroll@dundee.ac.uk * @since 5.2.1 */ private static class PlaneInfoKey { private final int z, t, c; /** * Construct a new key. * @param planeInfo the {@link PlaneInfo} to which this key is to correspond */ PlaneInfoKey(PlaneInfo planeInfo) { this.z = planeInfo.getTheZ().getValue(); this.t = planeInfo.getTheT().getValue(); this.c = planeInfo.getTheC().getValue(); } @Override public boolean equals(Object object) { if (this == object) { return true; } else if (object instanceof PlaneInfoKey) { final PlaneInfoKey other = (PlaneInfoKey) object; return this.z == other.z && this.t == other.t && this.c == other.c; } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getClass(), z, t, c); } } private final List<Long> testImages = Collections.synchronizedList(new ArrayList<Long>()); /** * Clear the list of test images. */ @BeforeClass public void clearTestImages() { testImages.clear(); } /** * Delete the test images then clear the list. * @throws Exception unexpected */ @AfterClass public void deleteTestImages() throws Exception { final Delete2 delete = Requests.delete().target("Image").id(testImages).build(); doChange(root, root.getSession(), delete, true); clearTestImages(); } /** * Assert that the given instances have the same property values. * (The properties to compare are based on the behavior of {@link ModelMockFactory#createImage(int, int, int, int, int)}.) * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Image original, Image duplicate) { Assert.assertEquals(duplicate.getDescription().getValue(), original.getDescription().getValue()); Assert.assertEquals(duplicate.getFormat().getValue(), original.getFormat().getValue()); Assert.assertEquals(duplicate.getName().getValue(), original.getName().getValue()); Assert.assertEquals(duplicate.getSeries().getValue(), original.getSeries().getValue()); } /** * Assert that the given instances have the same property values. * (The properties to compare are based on the behavior of {@link ModelMockFactory#createImage(int, int, int, int, int)}.) * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Pixels original, Pixels duplicate) { Assert.assertEquals(duplicate.getPhysicalSizeX().getUnit(), original.getPhysicalSizeX().getUnit()); Assert.assertEquals(duplicate.getPhysicalSizeX().getValue(), original.getPhysicalSizeX().getValue()); Assert.assertEquals(duplicate.getPhysicalSizeY().getUnit(), original.getPhysicalSizeY().getUnit()); Assert.assertEquals(duplicate.getPhysicalSizeY().getValue(), original.getPhysicalSizeY().getValue()); Assert.assertEquals(duplicate.getPhysicalSizeZ().getUnit(), original.getPhysicalSizeZ().getUnit()); Assert.assertEquals(duplicate.getPhysicalSizeZ().getValue(), original.getPhysicalSizeZ().getValue()); Assert.assertEquals(duplicate.getSizeX().getValue(), original.getSizeX().getValue()); Assert.assertEquals(duplicate.getSizeY().getValue(), original.getSizeY().getValue()); Assert.assertEquals(duplicate.getSizeZ().getValue(), original.getSizeZ().getValue()); Assert.assertEquals(duplicate.getSizeT().getValue(), original.getSizeT().getValue()); Assert.assertEquals(duplicate.getSizeC().getValue(), original.getSizeC().getValue()); Assert.assertEquals(duplicate.getSha1().getValue(), original.getSha1().getValue()); Assert.assertEquals(duplicate.getDimensionOrder().getValue().getValue(), original.getDimensionOrder().getValue().getValue()); Assert.assertEquals(duplicate.getPixelsType().getBitSize().getValue(), original.getPixelsType().getBitSize().getValue()); Assert.assertEquals(duplicate.getPixelsType().getValue().getValue(), original.getPixelsType().getValue().getValue()); } /** * Assert that the given instances have the same property values. * (The properties to compare are based on the behavior of {@link ModelMockFactory#createImage(int, int, int, int, int)}.) * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Channel original, Channel duplicate) { // nothing } /** * Assert that the given instances have the same property values. * (The properties to compare are based on the behavior of {@link ModelMockFactory#createImage(int, int, int, int, int)}.) * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(LogicalChannel original, LogicalChannel duplicate) { Assert.assertEquals(duplicate.getContrastMethod().getValue().getValue(), original.getContrastMethod().getValue().getValue()); Assert.assertEquals(duplicate.getEmissionWave().getUnit(), original.getEmissionWave().getUnit()); Assert.assertEquals(duplicate.getEmissionWave().getValue(), original.getEmissionWave().getValue()); Assert.assertEquals(duplicate.getIllumination().getValue(), original.getIllumination().getValue()); Assert.assertEquals(duplicate.getMode().getValue().getValue(), original.getMode().getValue().getValue()); } /** * Assert that the given instances have the same property values. * (The properties to compare are based on the behavior of {@link ModelMockFactory#createImage(int, int, int, int, int)}.) * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(PlaneInfo original, PlaneInfo duplicate) { Assert.assertEquals(duplicate.getTheZ().getValue(), original.getTheZ().getValue()); Assert.assertEquals(duplicate.getTheT().getValue(), original.getTheT().getValue()); Assert.assertEquals(duplicate.getTheC().getValue(), original.getTheC().getValue()); Assert.assertEquals(duplicate.getDeltaT().getUnit(), original.getDeltaT().getUnit()); Assert.assertEquals(duplicate.getDeltaT().getValue(), original.getDeltaT().getValue()); } /** * Assert that the given instances have the same property values. * (The properties to compare are based on the behavior of {@link ModelMockFactory#createImage(int, int, int, int, int)}.) * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(StatsInfo original, StatsInfo duplicate) { Assert.assertEquals(duplicate.getGlobalMin().getValue(), original.getGlobalMin().getValue()); Assert.assertEquals(duplicate.getGlobalMax().getValue(), original.getGlobalMax().getValue()); } /** * Assert that the given instances have the same property values. * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Rectangle original, Rectangle duplicate) { Assert.assertEquals(duplicate.getTheZ().getValue(), original.getTheZ().getValue()); Assert.assertEquals(duplicate.getTheT().getValue(), original.getTheT().getValue()); Assert.assertEquals(duplicate.getTheC().getValue(), original.getTheC().getValue()); Assert.assertEquals(duplicate.getX().getValue(), original.getX().getValue()); Assert.assertEquals(duplicate.getY().getValue(), original.getY().getValue()); Assert.assertEquals(duplicate.getWidth().getValue(), original.getWidth().getValue()); Assert.assertEquals(duplicate.getHeight().getValue(), original.getHeight().getValue()); } /** * Assert that the given instances have the same property values. * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Ellipse original, Ellipse duplicate) { Assert.assertEquals(duplicate.getTheZ().getValue(), original.getTheZ().getValue()); Assert.assertEquals(duplicate.getTheT().getValue(), original.getTheT().getValue()); Assert.assertEquals(duplicate.getTheC().getValue(), original.getTheC().getValue()); Assert.assertEquals(duplicate.getCx().getValue(), original.getCx().getValue()); Assert.assertEquals(duplicate.getCy().getValue(), original.getCy().getValue()); Assert.assertEquals(duplicate.getRx().getValue(), original.getRx().getValue()); Assert.assertEquals(duplicate.getRy().getValue(), original.getRy().getValue()); } /** * Assert that the given instances have the same property values. * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Line original, Line duplicate) { Assert.assertEquals(duplicate.getTheZ().getValue(), original.getTheZ().getValue()); Assert.assertEquals(duplicate.getTheT().getValue(), original.getTheT().getValue()); Assert.assertEquals(duplicate.getTheC().getValue(), original.getTheC().getValue()); Assert.assertEquals(duplicate.getX1().getValue(), original.getX1().getValue()); Assert.assertEquals(duplicate.getY1().getValue(), original.getY1().getValue()); Assert.assertEquals(duplicate.getX2().getValue(), original.getX2().getValue()); Assert.assertEquals(duplicate.getY2().getValue(), original.getY2().getValue()); } /** * Assert that the given instances have the same property values. * @param original the original instance * @param duplicate the duplicate instance that is expected to correspond to the original */ private static void assertSameProperties(Point original, Point duplicate) { Assert.assertEquals(duplicate.getTheZ().getValue(), original.getTheZ().getValue()); Assert.assertEquals(duplicate.getTheT().getValue(), original.getTheT().getValue()); Assert.assertEquals(duplicate.getTheC().getValue(), original.getTheC().getValue()); Assert.assertEquals(duplicate.getCx().getValue(), original.getCx().getValue()); Assert.assertEquals(duplicate.getCy().getValue(), original.getCy().getValue()); } /** * Get the IDs of an image's annotations. * @param imageId the ID of an image * @return the IDs of the annotations on the image * @throws ServerError unexpected */ private Set<Long> getImageAnnotations(long imageId) throws ServerError { final Set<Long> annotationIds = new HashSet<Long>(); for (final List<RType> result : iQuery.projection( "SELECT child.id FROM ImageAnnotationLink WHERE parent.id = :id", new ParametersI().addId(imageId))) { annotationIds.add(((RLong) result.get(0)).getValue()); } return annotationIds; } private String followLongAnnotations(LongAnnotation start, int depth) throws ServerError { if (depth < 1) { return ""; } final StringBuilder sb = new StringBuilder(); sb.append('['); sb.append(start.getLongValue().getValue()); for (final IObject result : iQuery.findAllByQuery( "SELECT l.child FROM AnnotationAnnotationLink AS l WHERE l.parent.id = :id ORDER BY l.child.longValue", new ParametersI().addId(start.getId().getValue()))) { if (result instanceof LongAnnotation) { sb.append(followLongAnnotations((LongAnnotation) result, depth - 1)); } } sb.append(']'); return sb.toString(); } /** * Create then duplicate an image and test that the properties of the instances in it and its subgraph are correctly duplicated. * @throws Exception unexpected */ @Test public void testDuplicateImageProperties() throws Exception { newUserAndGroup("rwr---"); /* create and save an image */ final Image originalImage = (Image) iUpdate.saveAndReturnObject(mmFactory.createImage(1,2,3,4,5)); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalImage.getId().getValue(); testImages.add(originalImageId); final Pixels originalPixels = originalImage.getPrimaryPixels(); final long originalPixelsId = originalPixels.getId().getValue(); final List<Channel> originalChannels = new ArrayList<Channel>(originalPixels.sizeOfChannels()); final Set<Long> originalChannelIds = new HashSet<Long>(); final List<LogicalChannel> originalLogicalChannels = new ArrayList<LogicalChannel>(originalChannels.size()); final Set<Long> originalLogicalChannelIds = new HashSet<Long>(); final List<StatsInfo> originalStatsInfos = new ArrayList<StatsInfo>(originalChannels.size()); final Set<Long> originalStatsInfoIds = new HashSet<Long>(); for (int channelIndex = 0; channelIndex < originalPixels.sizeOfChannels(); channelIndex++) { final Channel originalChannel = originalPixels.getChannel(channelIndex); originalChannels.add(originalChannel); originalChannelIds.add(originalChannel.getId().getValue()); final LogicalChannel originalLogicalChannel = originalChannel.getLogicalChannel(); originalLogicalChannels.add(originalLogicalChannel); originalLogicalChannelIds.add(originalLogicalChannel.getId().getValue()); final StatsInfo originalStatsInfo = originalChannel.getStatsInfo(); originalStatsInfos.add(originalStatsInfo); originalStatsInfoIds.add(originalStatsInfo.getId().getValue()); } final Map<PlaneInfoKey, PlaneInfo> originalPlaneInfos = new HashMap<PlaneInfoKey, PlaneInfo>(); final Set<Long> originalPlaneInfoIds = new HashSet<Long>(); for (final PlaneInfo originalPlaneInfo : originalPixels.copyPlaneInfo()) { originalPlaneInfos.put(new PlaneInfoKey(originalPlaneInfo), originalPlaneInfo); originalPlaneInfoIds.add(originalPlaneInfo.getId().getValue()); } /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* find out which objects the duplication claims to have created */ Assert.assertEquals(response.duplicates.size(), 6); final Set<Long> remainingImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); final Set<Long> remainingPixelsIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Pixels")); final Set<Long> remainingChannelIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Channel")); final Set<Long> remainingLogicalChannelIds = new HashSet<Long>(response.duplicates.get("ome.model.core.LogicalChannel")); final Set<Long> remainingStatsInfoIds = new HashSet<Long>(response.duplicates.get("ome.model.stats.StatsInfo")); final Set<Long> remainingPlaneInfoIds = new HashSet<Long>(response.duplicates.get("ome.model.core.PlaneInfo")); /* check that the new image's subgraph is a set of new IDs that match the response and whose properties are as expected */ final Long duplicateImageId = remainingImageIds.iterator().next(); testImages.add(duplicateImageId); final Parameters parameters = new ParametersI().addId(duplicateImageId); final Image duplicateImage = (Image) iQuery.findByQuery( "SELECT i FROM Image i " + "JOIN FETCH i.pixels AS p " + "JOIN FETCH i.format " + "JOIN FETCH p.dimensionOrder " + "JOIN FETCH p.pixelsType " + "JOIN FETCH p.channels AS c " + "JOIN FETCH p.planeInfo AS pi " + "JOIN FETCH c.logicalChannel AS lc " + "JOIN FETCH lc.contrastMethod " + "JOIN FETCH lc.illumination " + "JOIN FETCH lc.mode " + "JOIN FETCH c.statsInfo " + "WHERE i.id = :id", parameters); Assert.assertNotEquals(originalImageId, duplicateImageId); Assert.assertTrue(remainingImageIds.remove(duplicateImageId)); assertSameProperties(originalImage, duplicateImage); final Pixels duplicatePixels = duplicateImage.getPrimaryPixels(); final long duplicatePixelsId = duplicatePixels.getId().getValue(); Assert.assertNotEquals(originalPixelsId, duplicatePixelsId); Assert.assertTrue(remainingPixelsIds.remove(duplicatePixelsId)); assertSameProperties(originalPixels, duplicatePixels); for (int channelIndex = 0; channelIndex < duplicatePixels.sizeOfChannels(); channelIndex++) { final Channel duplicateChannel = duplicatePixels.getChannel(channelIndex); final long duplicateChannelId = duplicateChannel.getId().getValue(); Assert.assertFalse(originalChannelIds.contains(duplicateChannelId)); Assert.assertTrue(remainingChannelIds.remove(duplicateChannelId)); assertSameProperties(originalChannels.get(channelIndex), duplicateChannel); final LogicalChannel duplicateLogicalChannel = duplicateChannel.getLogicalChannel(); final long duplicateLogicalChannelId = duplicateLogicalChannel.getId().getValue(); Assert.assertFalse(originalLogicalChannelIds.contains(duplicateLogicalChannelId)); Assert.assertTrue(remainingLogicalChannelIds.remove(duplicateLogicalChannelId)); assertSameProperties(originalLogicalChannels.get(channelIndex), duplicateLogicalChannel); final StatsInfo duplicateStatsInfo = duplicateChannel.getStatsInfo(); final long duplicateStatsInfoId = duplicateStatsInfo.getId().getValue(); Assert.assertFalse(originalStatsInfoIds.contains(duplicateStatsInfoId)); Assert.assertTrue(remainingStatsInfoIds.remove(duplicateStatsInfoId)); assertSameProperties(originalStatsInfos.get(channelIndex), duplicateStatsInfo); } for (final PlaneInfo duplicatePlaneInfo : duplicatePixels.copyPlaneInfo()) { final long duplicatePlaneInfoId = duplicatePlaneInfo.getId().getValue(); Assert.assertFalse(originalPlaneInfoIds.contains(duplicatePlaneInfoId)); Assert.assertTrue(remainingPlaneInfoIds.remove(duplicatePlaneInfoId)); assertSameProperties(originalPlaneInfos.get(new PlaneInfoKey(duplicatePlaneInfo)), duplicatePlaneInfo); } /* check that the response reported no IDs for instances whose properties we did not check */ Assert.assertTrue(remainingImageIds.isEmpty()); Assert.assertTrue(remainingPixelsIds.isEmpty()); Assert.assertTrue(remainingChannelIds.isEmpty()); Assert.assertTrue(remainingLogicalChannelIds.isEmpty()); Assert.assertTrue(remainingStatsInfoIds.isEmpty()); Assert.assertTrue(remainingPlaneInfoIds.isEmpty()); } /** * Create then duplicate an image in dry-run mode and test that the image's subgraph is returned in the response. * @throws Exception unexpected */ @Test public void testDuplicateImageDryRun() throws Exception { newUserAndGroup("rwr---"); /* create and save an image */ final Image originalImage = (Image) iUpdate.saveAndReturnObject(mmFactory.createImage(1,2,3,4,5)); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalImage.getId().getValue(); testImages.add(originalImageId); final Pixels originalPixels = originalImage.getPrimaryPixels(); final long originalPixelsId = originalPixels.getId().getValue(); final Set<Long> originalChannelIds = new HashSet<Long>(); final Set<Long> originalLogicalChannelIds = new HashSet<Long>(); final Set<Long> originalStatsInfoIds = new HashSet<Long>(); for (int channelIndex = 0; channelIndex < originalPixels.sizeOfChannels(); channelIndex++) { final Channel originalChannel = originalPixels.getChannel(channelIndex); originalChannelIds.add(originalChannel.getId().getValue()); final LogicalChannel originalLogicalChannel = originalChannel.getLogicalChannel(); originalLogicalChannelIds.add(originalLogicalChannel.getId().getValue()); final StatsInfo originalStatsInfo = originalChannel.getStatsInfo(); originalStatsInfoIds.add(originalStatsInfo.getId().getValue()); } final Set<Long> originalPlaneInfoIds = new HashSet<Long>(); for (final PlaneInfo originalPlaneInfo : originalPixels.copyPlaneInfo()) { originalPlaneInfoIds.add(originalPlaneInfo.getId().getValue()); } /* duplicate the image in dry-run mode */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); dup.dryRun = true; final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* find out which objects the duplication reports as being targets for processing */ Assert.assertEquals(response.duplicates.size(), 6); final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); final Set<Long> reportedPixelsIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Pixels")); final Set<Long> reportedChannelIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Channel")); final Set<Long> reportedLogicalChannelIds = new HashSet<Long>(response.duplicates.get("ome.model.core.LogicalChannel")); final Set<Long> reportedStatsInfoIds = new HashSet<Long>(response.duplicates.get("ome.model.stats.StatsInfo")); final Set<Long> reportedPlaneInfoIds = new HashSet<Long>(response.duplicates.get("ome.model.core.PlaneInfo")); /* check that the duplication reported exactly the expected targets */ Assert.assertEquals(reportedImageIds, Collections.singleton(originalImageId)); Assert.assertEquals(reportedPixelsIds, Collections.singleton(originalPixelsId)); Assert.assertEquals(reportedChannelIds, originalChannelIds); Assert.assertEquals(reportedLogicalChannelIds, originalLogicalChannelIds); Assert.assertEquals(reportedStatsInfoIds, originalStatsInfoIds); Assert.assertEquals(reportedPlaneInfoIds, originalPlaneInfoIds); } /** * Test duplication of an annotated image with duplication of its annotation. * @throws Exception unexpected */ @Test public void testDuplicateImageWithAnnotation() throws Exception { newUserAndGroup("rwra--"); /* create an annotated image */ final String annotationText = getClass().getSimpleName() + ':' + System.nanoTime(); final Image originalImage = mmFactory.simpleImage(); final TextAnnotation originalAnnotation = new XmlAnnotationI(); originalAnnotation.setTextValue(omero.rtypes.rstring(annotationText)); ImageAnnotationLink originalLink = new ImageAnnotationLinkI(); originalLink.setParent(originalImage); originalLink.setChild(originalAnnotation); originalLink = (ImageAnnotationLink) iUpdate.saveAndReturnObject(originalLink); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalLink.getParent().getId().getValue(); final long originalAnnotationId = originalLink.getChild().getId().getValue(); final long originalLinkId = originalLink.getId().getValue(); testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image, link, and annotation */ final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); final Set<Long> reportedAnnotationIds = new HashSet<Long>(response.duplicates.get("ome.model.annotations.XmlAnnotation")); final Set<Long> reportedLinkIds = new HashSet<Long>(response.duplicates.get("ome.model.annotations.ImageAnnotationLink")); Assert.assertEquals(reportedImageIds.size(), 1); Assert.assertEquals(reportedAnnotationIds.size(), 1); Assert.assertEquals(reportedLinkIds.size(), 1); /* check that the reported image, link, and annotation each have a new ID */ final long reportedImageId = reportedImageIds.iterator().next(); final long reportedAnnotationId = reportedAnnotationIds.iterator().next(); final long reportedLinkId = reportedLinkIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); Assert.assertNotEquals(originalAnnotationId, reportedAnnotationId); Assert.assertNotEquals(originalLinkId, reportedLinkId); /* check that the annotations on the images are exactly as expected */ Assert.assertEquals(getImageAnnotations(originalImageId), Collections.singleton(originalAnnotationId)); Assert.assertEquals(getImageAnnotations(reportedImageId), Collections.singleton(reportedAnnotationId)); /* check that the annotation is indeed a duplicate of the original */ final TextAnnotation duplicatedAnnotation = (TextAnnotation) iQuery.findByQuery( "FROM Annotation WHERE id = :id", new ParametersI().addId(reportedAnnotationId)); Assert.assertEquals(duplicatedAnnotation.getTextValue().getValue(), annotationText); } /** * Test duplication of an annotated image such that it links to the original's annotation. * @throws Exception unexpected */ @Test public void testDuplicateImageWithPreviousAnnotation() throws Exception { newUserAndGroup("rwra--"); /* create an annotated image */ final String annotationText = getClass().getSimpleName() + ':' + System.nanoTime(); final Image originalImage = mmFactory.simpleImage(); final TextAnnotation originalAnnotation = new XmlAnnotationI(); originalAnnotation.setTextValue(omero.rtypes.rstring(annotationText)); ImageAnnotationLink originalLink = new ImageAnnotationLinkI(); originalLink.setParent(originalImage); originalLink.setChild(originalAnnotation); originalLink = (ImageAnnotationLink) iUpdate.saveAndReturnObject(originalLink); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalLink.getParent().getId().getValue(); final long originalAnnotationId = originalLink.getChild().getId().getValue(); final long originalLinkId = originalLink.getId().getValue(); testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); dup.typesToReference = ImmutableList.of("TextAnnotation"); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image and link, but not an annotation */ final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.XmlAnnotation")); final Set<Long> reportedLinkIds = new HashSet<Long>(response.duplicates.get("ome.model.annotations.ImageAnnotationLink")); Assert.assertEquals(reportedImageIds.size(), 1); Assert.assertEquals(reportedLinkIds.size(), 1); /* check that the reported image and annotation each have a new ID */ final long reportedImageId = reportedImageIds.iterator().next(); final long reportedLinkId = reportedLinkIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); Assert.assertNotEquals(originalLinkId, reportedLinkId); /* check that the annotations on the images are exactly as expected */ Assert.assertEquals(getImageAnnotations(originalImageId), Collections.singleton(originalAnnotationId)); Assert.assertEquals(getImageAnnotations(reportedImageId), Collections.singleton(originalAnnotationId)); } /** * Test duplication of an annotated image such that it does not link to an annotation. * @throws Exception unexpected */ @Test public void testDuplicateImageWithNoAnnotation() throws Exception { newUserAndGroup("rwra--"); /* create an annotated image */ final String annotationText = getClass().getSimpleName() + ':' + System.nanoTime(); final Image originalImage = mmFactory.simpleImage(); final TextAnnotation originalAnnotation = new XmlAnnotationI(); originalAnnotation.setTextValue(omero.rtypes.rstring(annotationText)); ImageAnnotationLink originalLink = new ImageAnnotationLinkI(); originalLink.setParent(originalImage); originalLink.setChild(originalAnnotation); originalLink = (ImageAnnotationLink) iUpdate.saveAndReturnObject(originalLink); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalLink.getParent().getId().getValue(); final long originalAnnotationId = originalLink.getChild().getId().getValue(); final long originalLinkId = originalLink.getId().getValue(); testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); dup.typesToIgnore = ImmutableList.of("IAnnotationLink"); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image and link, but not an annotation */ final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.XmlAnnotation")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.ImageAnnotationLink")); Assert.assertEquals(reportedImageIds.size(), 1); /* check that the reported image and annotation each have a new ID */ final long reportedImageId = reportedImageIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); /* check that the annotations on the images are exactly as expected */ Assert.assertEquals(getImageAnnotations(originalImageId), Collections.singleton(originalAnnotationId)); Assert.assertEquals(getImageAnnotations(reportedImageId), Collections.emptySet()); } /** * Test duplication of an annotated image such that it does not duplicate an attachment. * @throws Exception unexpected */ @Test public void testDuplicateImageWithFileAnnotation() throws Exception { newUserAndGroup("rwra--"); /* create an image with an attachment */ final Image originalImage = mmFactory.simpleImage(); final FileAnnotation originalAttachment = new FileAnnotationI(); ImageAnnotationLink originalLink = new ImageAnnotationLinkI(); originalLink.setParent(originalImage); originalLink.setChild(originalAttachment); originalLink = (ImageAnnotationLink) iUpdate.saveAndReturnObject(originalLink); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalLink.getParent().getId().getValue(); final long originalAttachmentId = originalLink.getChild().getId().getValue(); final long originalLinkId = originalLink.getId().getValue(); testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image and link, but not the attachment */ final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.FileAnnotation")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.ImageAnnotationLink")); Assert.assertEquals(reportedImageIds.size(), 1); /* check that the reported image and annotation each have a new ID */ final long reportedImageId = reportedImageIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); /* check that the annotations on the images are exactly as expected */ Assert.assertEquals(getImageAnnotations(originalImageId), Collections.singleton(originalAttachmentId)); Assert.assertEquals(getImageAnnotations(reportedImageId), Collections.emptySet()); } /** * Tests duplication of a cyclic subgraph. * @throws Exception unexpected */ @Test public void testDuplicateImageWithCyclicAnnotation() throws Exception { newUserAndGroup("rwra--"); /* create a graph of annotations */ final Image originalImage = mmFactory.simpleImage(); final List<LongAnnotation> originalAnnotations = new ArrayList<LongAnnotation>(); List<IObject> originalLinks = new ArrayList<IObject>(); /* create a string of annotations */ for (int index = 0; index < 5; index++) { originalAnnotations.add(new LongAnnotationI()); originalAnnotations.get(index).setLongValue(omero.rtypes.rlong(index)); if (index > 0) { final AnnotationAnnotationLink annotationLink = new AnnotationAnnotationLinkI(); annotationLink.setParent((Annotation) originalAnnotations.get(index - 1)); annotationLink.setChild(originalAnnotations.get(index)); originalLinks.add(annotationLink); } } /* add a back-link within the string of annotations */ final AnnotationAnnotationLink annotationLink = new AnnotationAnnotationLinkI(); annotationLink.setParent((Annotation) originalAnnotations.get(3)); annotationLink.setChild(originalAnnotations.get(1)); originalLinks.add(annotationLink); /* annotate an image with the graph */ ImageAnnotationLink originalImageLink = new ImageAnnotationLinkI(); originalImageLink.setParent(originalImage); originalImageLink.setChild(originalAnnotations.get(0)); originalLinks.add(0, originalImageLink); originalLinks = iUpdate.saveAndReturnArray(originalLinks); originalImageLink = (ImageAnnotationLink) originalLinks.get(0); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalImageLink.getParent().getId().getValue(); final long originalImageLinkId = ((ImageAnnotationLink) originalLinks.get(0)).getId().getValue(); final Set<Long> originalAnnotationIds = new HashSet<Long>(); final Set<Long> originalAnnotationLinkIds = new HashSet<Long>(); for (final IObject object : originalLinks.subList(1, originalLinks.size())) { final AnnotationAnnotationLink link = (AnnotationAnnotationLink) object; originalAnnotationIds.add(link.getParent().getId().getValue()); originalAnnotationIds.add(link.getChild().getId().getValue()); originalAnnotationLinkIds.add(link.getId().getValue()); } testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image and annotations and the links among them */ final Set<Long> reportedImageIds = new HashSet<Long>( response.duplicates.get("ome.model.core.Image")); final Set<Long> reportedAnnotationIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.LongAnnotation")); final Set<Long> reportedImageLinkIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.ImageAnnotationLink")); final Set<Long> reportedAnnotationLinkIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.AnnotationAnnotationLink")); Assert.assertEquals(reportedImageIds.size(), 1); Assert.assertEquals(reportedAnnotationIds.size(), originalAnnotations.size()); Assert.assertEquals(reportedImageLinkIds.size() + reportedAnnotationLinkIds.size(), originalLinks.size()); /* check that the reported image and annotation each have a new ID */ final long reportedImageId = reportedImageIds.iterator().next(); final long reportedImageLinkId = reportedImageLinkIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); Assert.assertNotEquals(originalImageLinkId, reportedImageLinkId); Assert.assertTrue(Sets.intersection(originalAnnotationIds, reportedAnnotationIds).isEmpty()); Assert.assertTrue(Sets.intersection(originalAnnotationLinkIds, reportedAnnotationLinkIds).isEmpty()); /* check that the duplicate image has a different annotation from the original image */ final Set<Long> originalImageAnnotationIds = getImageAnnotations(originalImageId); final Set<Long> duplicateImageAnnotationIds = getImageAnnotations(reportedImageId); Assert.assertEquals(originalImageAnnotationIds.size(), 1); Assert.assertEquals(duplicateImageAnnotationIds.size(), 1); final long originalImageAnnotationId = originalImageAnnotationIds.iterator().next(); final long duplicateImageAnnotationId = duplicateImageAnnotationIds.iterator().next(); Assert.assertNotEquals(originalImageAnnotationId, duplicateImageAnnotationId); /* check that the structure of the cyclic graph of annotations has been correctly duplicated */ final LongAnnotation originalImageAnnotation = (LongAnnotation) iQuery.get("LongAnnotation", originalImageAnnotationId); final LongAnnotation duplicateImageAnnotation = (LongAnnotation) iQuery.get("LongAnnotation", duplicateImageAnnotationId); Assert.assertEquals(followLongAnnotations(originalImageAnnotation, 6), "[0[1[2[3[1[2]][4]]]]]"); Assert.assertEquals(followLongAnnotations(duplicateImageAnnotation, 6), "[0[1[2[3[1[2]][4]]]]]"); } /** * Test duplication of annotated images that have separate and shared annotations. * @throws Exception unexpected */ @Test public void testDuplicateImagesWithSeparateAndSharedAnnotations() throws Exception { newUserAndGroup("rwra--"); /* create two annotated images with three annotations, the last annotation shared among both images */ final List<Long> originalImageIds = new ArrayList<Long>(); for (int ii = 0; ii < 2; ii++) { originalImageIds.add(iUpdate.saveAndReturnObject(mmFactory.simpleImage()).getId().getValue()); } testImages.addAll(originalImageIds); final List<Long> originalAnnotationIds = new ArrayList<Long>(); final List<String> originalAnnotationText = new ArrayList<String>(); for (int ai = 0; ai < 3; ai++) { final String textValue = getClass().getSimpleName() + " annotation #" + ai; final TextAnnotation originalAnnotation = new XmlAnnotationI(); originalAnnotation.setTextValue(omero.rtypes.rstring(textValue)); originalAnnotationIds.add(iUpdate.saveAndReturnObject(originalAnnotation).getId().getValue()); originalAnnotationText.add(textValue); } final SetMultimap<Integer, Integer> imageAnnotationLinks = ImmutableSetMultimap.of(0, 0, 1, 1, 0, 2, 1, 2); final List<Long> originalLinkIds = new ArrayList<Long>(); for (Map.Entry<Integer, Integer> toLink : imageAnnotationLinks.entries()) { final Image image = new ImageI(originalImageIds.get(toLink.getKey()), false); final TextAnnotation annotation = new XmlAnnotationI(originalAnnotationIds.get(toLink.getValue()), false); final ImageAnnotationLink link = new ImageAnnotationLinkI(); link.setParent(image); link.setChild(annotation); originalLinkIds.add(iUpdate.saveAndReturnObject(link).getId().getValue()); } /* duplicate the images */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", (List<Long>) new ArrayList<Long>(originalImageIds)); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of the images, links, and annotations */ final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); final Set<Long> reportedAnnotationIds = new HashSet<Long>(response.duplicates.get("ome.model.annotations.XmlAnnotation")); final Set<Long> reportedLinkIds = new HashSet<Long>(response.duplicates.get("ome.model.annotations.ImageAnnotationLink")); testImages.addAll(reportedImageIds); Assert.assertEquals(reportedImageIds.size(), originalImageIds.size()); Assert.assertEquals(reportedAnnotationIds.size(), originalAnnotationIds.size()); Assert.assertEquals(reportedLinkIds.size(), originalLinkIds.size()); /* check that the reported images, links, and annotations all have a new ID */ Assert.assertTrue(Sets.intersection(ImmutableSet.of(originalImageIds), reportedImageIds).isEmpty()); Assert.assertTrue(Sets.intersection(ImmutableSet.of(originalAnnotationIds), reportedAnnotationIds).isEmpty()); Assert.assertTrue(Sets.intersection(ImmutableSet.of(originalLinkIds), reportedLinkIds).isEmpty()); /* check that the annotations on the images are exactly as expected */ for (final Map.Entry<Integer, Collection<Integer>> linksForOneImage : imageAnnotationLinks.asMap().entrySet()) { final int ii = linksForOneImage.getKey(); final Set<Long> expectedAnnotationIds = new HashSet<Long>(); for (final int ai : linksForOneImage.getValue()) { expectedAnnotationIds.add(originalAnnotationIds.get(ai)); } Assert.assertEquals(getImageAnnotations(originalImageIds.get(ii)), expectedAnnotationIds); } final Iterator<Long> reportedImageIdsIterator = reportedImageIds.iterator(); final Set<Long> reportedImage1Annotations = getImageAnnotations(reportedImageIdsIterator.next()); final Set<Long> reportedImage2Annotations = getImageAnnotations(reportedImageIdsIterator.next()); Assert.assertEquals(reportedImage1Annotations.size(), 2); Assert.assertEquals(reportedImage2Annotations.size(), 2); Assert.assertEquals(Sets.union(reportedImage1Annotations, reportedImage2Annotations), reportedAnnotationIds); /* check that the annotations are indeed duplicates of the original */ final Set<Long> sharedAnnotationIds = Sets.intersection(reportedImage1Annotations, reportedImage2Annotations); final Set<Long> separateAnnotationIds = Sets.symmetricDifference(reportedImage1Annotations, reportedImage2Annotations); final String hql = "SELECT textValue FROM TextAnnotation WHERE id IN (:ids)"; final Set<String> reportedSharedAnnotationText = new HashSet<String>(); final Set<String> reportedSeparateAnnotationText = new HashSet<String>(); for (final List<RType> result : iQuery.projection(hql, new ParametersI().addIds(sharedAnnotationIds))) { reportedSharedAnnotationText.add(((RString) result.get(0)).getValue()); } for (final List<RType> result : iQuery.projection(hql, new ParametersI().addIds(separateAnnotationIds))) { reportedSeparateAnnotationText.add(((RString) result.get(0)).getValue()); } Assert.assertEquals(reportedSharedAnnotationText.size(), 1); Assert.assertEquals(reportedSeparateAnnotationText.size(), 2); Assert.assertEquals(reportedSharedAnnotationText, ImmutableSet.of(originalAnnotationText.get(2))); Assert.assertEquals(reportedSeparateAnnotationText, ImmutableSet.copyOf(originalAnnotationText.subList(0, 2))); } /** * Test preservation of shapes and their properties when duplicating an image with an ROI. * @throws Exception unexpected */ @Test public void testDuplicateShapeProperties() throws Exception { newUserAndGroup("rwra--"); /* create an image with ROIs */ Image originalImage = mmFactory.simpleImage(); Roi originalRoi = new RoiI(); Rectangle originalRectangle = new RectangleI(); originalRoi.addShape(originalRectangle); Ellipse originalEllipse = new EllipseI(); originalRoi.addShape(originalEllipse); Line originalLine = new LineI(); originalRoi.addShape(originalLine); Point originalPoint = new PointI(); originalRoi.addShape(originalPoint); int propertyValue = 1; originalRectangle.setTheZ(omero.rtypes.rint(propertyValue++)); originalRectangle.setTheT(omero.rtypes.rint(propertyValue++)); originalRectangle.setTheC(omero.rtypes.rint(propertyValue++)); originalRectangle.setX(omero.rtypes.rdouble(propertyValue++)); originalRectangle.setY(omero.rtypes.rdouble(propertyValue++)); originalRectangle.setWidth(omero.rtypes.rdouble(propertyValue++)); originalRectangle.setHeight(omero.rtypes.rdouble(propertyValue++)); originalEllipse.setTheZ(omero.rtypes.rint(propertyValue++)); originalEllipse.setTheT(omero.rtypes.rint(propertyValue++)); originalEllipse.setTheC(omero.rtypes.rint(propertyValue++)); originalEllipse.setCx(omero.rtypes.rdouble(propertyValue++)); originalEllipse.setCy(omero.rtypes.rdouble(propertyValue++)); originalEllipse.setRx(omero.rtypes.rdouble(propertyValue++)); originalEllipse.setRy(omero.rtypes.rdouble(propertyValue++)); originalLine.setTheZ(omero.rtypes.rint(propertyValue++)); originalLine.setTheT(omero.rtypes.rint(propertyValue++)); originalLine.setTheC(omero.rtypes.rint(propertyValue++)); originalLine.setX1(omero.rtypes.rdouble(propertyValue++)); originalLine.setY1(omero.rtypes.rdouble(propertyValue++)); originalLine.setX2(omero.rtypes.rdouble(propertyValue++)); originalLine.setY2(omero.rtypes.rdouble(propertyValue++)); originalPoint.setTheZ(omero.rtypes.rint(propertyValue++)); originalPoint.setTheT(omero.rtypes.rint(propertyValue++)); originalPoint.setTheC(omero.rtypes.rint(propertyValue++)); originalPoint.setCx(omero.rtypes.rdouble(propertyValue++)); originalPoint.setCy(omero.rtypes.rdouble(propertyValue++)); originalRoi = (Roi) iUpdate.saveAndReturnObject(originalRoi); final Iterator<Shape> originalShapes = originalRoi.copyShapes().iterator(); originalRectangle = (Rectangle) originalShapes.next(); originalEllipse = (Ellipse) originalShapes.next(); originalLine = (Line) originalShapes.next(); originalPoint = (Point) originalShapes.next(); Assert.assertFalse(originalShapes.hasNext()); originalImage.addRoi(originalRoi); originalImage = (Image) iUpdate.saveAndReturnObject(originalImage); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalImage.getId().getValue(); final long originalRoiId = originalRoi.getId().getValue(); final long originalRectangleId = originalRectangle.getId().getValue(); final long originalEllipseId = originalEllipse.getId().getValue(); final long originalLineId = originalLine.getId().getValue(); final long originalPointId = originalPoint.getId().getValue(); testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image, link, and annotation */ final Set<Long> reportedImageIds = new HashSet<Long>(response.duplicates.get("ome.model.core.Image")); final Set<Long> reportedRoiIds = new HashSet<Long>(response.duplicates.get("ome.model.roi.Roi")); final Set<Long> reportedRectangleIds = new HashSet<Long>(response.duplicates.get("ome.model.roi.Rectangle")); final Set<Long> reportedEllipseIds = new HashSet<Long>(response.duplicates.get("ome.model.roi.Ellipse")); final Set<Long> reportedLineIds = new HashSet<Long>(response.duplicates.get("ome.model.roi.Line")); final Set<Long> reportedPointIds = new HashSet<Long>(response.duplicates.get("ome.model.roi.Point")); Assert.assertEquals(reportedImageIds.size(), 1); Assert.assertEquals(reportedRoiIds.size(), 1); Assert.assertEquals(reportedRectangleIds.size(), 1); Assert.assertEquals(reportedEllipseIds.size(), 1); Assert.assertEquals(reportedLineIds.size(), 1); Assert.assertEquals(reportedPointIds.size(), 1); /* check that the reported image, ROI and shapes each have a new ID */ final long reportedImageId = reportedImageIds.iterator().next(); final long reportedRoiId = reportedRoiIds.iterator().next(); final long reportedRectangleId = reportedRectangleIds.iterator().next(); final long reportedEllipseId = reportedEllipseIds.iterator().next(); final long reportedLineId = reportedLineIds.iterator().next(); final long reportedPointId = reportedPointIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); Assert.assertNotEquals(originalRoiId, reportedRoiId); Assert.assertNotEquals(originalRectangleId, reportedRectangleId); Assert.assertNotEquals(originalEllipseId, reportedEllipseId); Assert.assertNotEquals(originalLineId, reportedLineId); Assert.assertNotEquals(originalPointId, reportedPointId); /* check that the ROI on the images is exactly as expected */ final Parameters parameters = new ParametersI().addId(reportedImageId); final Image duplicateImage = (Image) iQuery.findByQuery( "SELECT i FROM Image i " + "JOIN FETCH i.rois AS r " + "JOIN FETCH r.shapes " + "WHERE i.id = :id", parameters); final Iterator<Shape> duplicateShapes = duplicateImage.copyRois().get(0).copyShapes().iterator(); final Rectangle duplicateRectangle = (Rectangle) duplicateShapes.next(); final Ellipse duplicateEllipse = (Ellipse) duplicateShapes.next(); final Line duplicateLine = (Line) duplicateShapes.next(); final Point duplicatePoint = (Point) duplicateShapes.next(); Assert.assertFalse(duplicateShapes.hasNext()); Assert.assertEquals(duplicateRectangle.getId().getValue(), reportedRectangleId); Assert.assertEquals(duplicateEllipse.getId().getValue(), reportedEllipseId); Assert.assertEquals(duplicateLine.getId().getValue(), reportedLineId); Assert.assertEquals(duplicatePoint.getId().getValue(), reportedPointId); assertSameProperties(originalRectangle, duplicateRectangle); assertSameProperties(originalEllipse, duplicateEllipse); assertSameProperties(originalLine, duplicateLine); assertSameProperties(originalPoint, duplicatePoint); } /** * Test duplication of an annotated image with various annotation types treated differently. * @throws Exception unexpected */ @Test public void testDuplicateImageWithTypeOptions() throws Exception { newUserAndGroup("rwra--"); /* create an annotated image */ Image originalImage = mmFactory.simpleImage(); originalImage = (Image) iUpdate.saveAndReturnObject(originalImage).proxy(); List<IObject> originalLinks = new ArrayList<IObject>(); for (final Class<? extends Annotation> annotationClass : new Class[]{ DoubleAnnotationI.class, LongAnnotationI.class, MapAnnotationI.class, TagAnnotationI.class, XmlAnnotationI.class}) { final ImageAnnotationLink originalLink = new ImageAnnotationLinkI(); originalLink.setParent(originalImage); originalLink.setChild(annotationClass.newInstance()); originalLinks.add(originalLink); } originalLinks = iUpdate.saveAndReturnArray(originalLinks); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalImage.getId().getValue(); final Map<String, Long> originalAnnotationIds = new HashMap<String, Long>(); final Set<Long> originalLinkIds = new HashSet<Long>(); for (final IObject originalLink : originalLinks) { final Annotation annotation = ((ImageAnnotationLink) originalLink).getChild(); originalAnnotationIds.put(annotation.getClass().getSimpleName(), annotation.getId().getValue()); originalLinkIds.add(originalLink.getId().getValue()); } testImages.add(originalImageId); /* duplicate the image */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); dup.typesToDuplicate = ImmutableList.of("BasicAnnotation", "XmlAnnotation"); dup.typesToReference = ImmutableList.of("DoubleAnnotation", "TextAnnotation"); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of an image, annotations and their links */ final Set<Long> reportedImageIds = new HashSet<Long>( response.duplicates.get("ome.model.core.Image")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.DoubleAnnotation")); final Set<Long> reportedLongAnnotationIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.LongAnnotation")); final Set<Long> reportedMapAnnotationIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.MapAnnotation")); Assert.assertFalse(response.duplicates.containsKey("ome.model.annotations.TagAnnotation")); final Set<Long> reportedXmlAnnotationIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.XmlAnnotation")); final Set<Long> reportedLinkIds = new HashSet<Long>( response.duplicates.get("ome.model.annotations.ImageAnnotationLink")); Assert.assertEquals(reportedImageIds.size(), 1); Assert.assertEquals(reportedLongAnnotationIds.size(), 1); Assert.assertEquals(reportedMapAnnotationIds.size(), 1); Assert.assertEquals(reportedXmlAnnotationIds.size(), 1); Assert.assertEquals(reportedLinkIds.size(), originalLinkIds.size()); /* check that the reported image, links, and annotations each have a new ID where expected */ final long reportedImageId = reportedImageIds.iterator().next(); final long reportedLongAnnotationId = reportedLongAnnotationIds.iterator().next(); final long reportedMapAnnotationId = reportedMapAnnotationIds.iterator().next(); final long reportedXmlAnnotationId = reportedXmlAnnotationIds.iterator().next(); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); Assert.assertNotEquals(originalAnnotationIds.get("LongAnnotationI"), reportedLongAnnotationId); Assert.assertNotEquals(originalAnnotationIds.get("MapAnnotationI"), reportedMapAnnotationId); Assert.assertNotEquals(originalAnnotationIds.get("XmlAnnotationI"), reportedXmlAnnotationId); Assert.assertTrue(Sets.intersection(originalLinkIds, reportedLinkIds).isEmpty()); /* check that the annotations on the images are exactly as expected */ final Set<Long> expectedAnnotationIds = ImmutableSet.of( /* reference includes DoubleAnnotation */ originalAnnotationIds.get("DoubleAnnotationI"), /* duplicate includes BasicAnnotation */ reportedLongAnnotationId, /* default behavior */ reportedMapAnnotationId, /* reference includes TextAnnotation */ originalAnnotationIds.get("TagAnnotationI"), /* duplicate includes XmlAnnotation */ reportedXmlAnnotationId); Assert.assertEquals(getImageAnnotations(originalImageId), new HashSet<Long>(originalAnnotationIds.values())); Assert.assertEquals(getImageAnnotations(reportedImageId), expectedAnnotationIds); } /** * Test duplication of an annotated image with contradictory treatments for the same annotation typs. * @throws Exception unexpected */ @Test public void testDuplicateImageWithOpposingTypeOptions() throws Exception { newUserAndGroup("rwra--"); /* create an image */ Image originalImage = mmFactory.simpleImage(); originalImage = (Image) iUpdate.saveAndReturnObject(originalImage); /* note the objects (and their IDs) that were thus created and saved */ final long originalImageId = originalImage.getId().getValue(); testImages.add(originalImageId); /* duplicate the image with contradictory instructions */ final Duplicate dup = new Duplicate(); dup.targetObjects = ImmutableMap.of("Image", Arrays.asList(originalImageId)); for (int i = 0; i < 4; i++) { dup.typesToDuplicate = i == 0 ? null : ImmutableList.of("IAnnotationLink"); dup.typesToReference = i == 1 ? null : ImmutableList.of("IAnnotationLink"); dup.typesToIgnore = i == 2 ? null : ImmutableList.of("IAnnotationLink"); final ERR response = (ERR) doChange(client, factory, dup, false); Assert.assertEquals(response.name, "bad-class"); } } /** * Test duplication of a dataset's image. {@link SkipHead} is used to identify the image via its dataset. * @throws Exception unexpected */ @Test(groups = "ticket:13197") public void testDuplicateImageViaSkipHead() throws Exception { newUserAndGroup("rwr---"); /* create a dataset with an image */ final Dataset originalDataset = mmFactory.simpleDataset(); final Image originalImage = mmFactory.simpleImage(); DatasetImageLink originalLink = new DatasetImageLinkI(); originalLink.setParent(originalDataset); originalLink.setChild(originalImage); originalLink = (DatasetImageLink) iUpdate.saveAndReturnObject(originalLink); /* note the objects (and their IDs) that were thus created and saved */ final long originalDatasetId = originalLink.getParent().getId().getValue(); final long originalImageId = originalLink.getChild().getId().getValue(); final long originalLinkId = originalLink.getId().getValue(); testImages.add(originalImageId); /* duplicate the image via SkipHead */ final SkipHead dup = Requests.skipHead().target("Dataset").id(originalDatasetId).startFrom("Image").request(Duplicate.class).build(); final DuplicateResponse response = (DuplicateResponse) doChange(dup); /* check that the response includes duplication of only the image */ final List<Long> reportedDatasetIds = response.duplicates.get("ome.model.containers.Dataset"); final List<Long> reportedImageIds = response.duplicates.get("ome.model.core.Image"); final List<Long> reportedLinkIds = response.duplicates.get("ome.model.annotations.ImageAnnotationLink"); Assert.assertNull(reportedDatasetIds); Assert.assertEquals(reportedImageIds.size(), 1); Assert.assertNull(reportedLinkIds); /* check that the reported image has a new ID */ final long reportedImageId = reportedImageIds.get(0); testImages.add(reportedImageId); Assert.assertNotEquals(originalImageId, reportedImageId); } }