JAL-2405 check for circular reference in SequenceGroup.context
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 9 Feb 2017 08:49:38 +0000 (08:49 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 9 Feb 2017 08:49:38 +0000 (08:49 +0000)
src/jalview/datamodel/SequenceGroup.java
test/jalview/datamodel/SequenceGroupTest.java

index a1579c5..4f9d530 100755 (executable)
@@ -1347,13 +1347,25 @@ public class SequenceGroup implements AnnotatedCollectionI
   private AnnotatedCollectionI context;
 
   /**
-   * set the alignment or group context for this group
+   * Sets the alignment or group context for this group
    * 
-   * @param context
+   * @param ctx
+   * @throws IllegalArgumentException
+   *           if setting the context would result in a circular reference chain
    */
-  public void setContext(AnnotatedCollectionI context)
+  public void setContext(AnnotatedCollectionI ctx)
   {
-    this.context = context;
+    AnnotatedCollectionI ref = ctx;
+    while (ref != null)
+    {
+      if (ref == this)
+      {
+        throw new IllegalArgumentException(
+                "Circular reference in SequenceGroup.context");
+      }
+      ref = ref.getContext();
+    }
+    this.context = ctx;
   }
 
   /*
index 53ac181..243bd53 100644 (file)
@@ -6,6 +6,7 @@ import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import jalview.schemes.NucleotideColourScheme;
 
@@ -79,4 +80,36 @@ public class SequenceGroupTest
     sg.setColourScheme(scheme);
     assertSame(scheme, sg.getColourScheme());
   }
+
+  @Test
+  public void testSetContext()
+  {
+    SequenceGroup sg1 = new SequenceGroup();
+    SequenceGroup sg2 = new SequenceGroup();
+    SequenceGroup sg3 = new SequenceGroup();
+    assertNull(sg1.getContext());
+    sg1.setContext(null);
+    assertNull(sg1.getContext());
+    try
+    {
+      sg1.setContext(sg1); // self-reference :-O
+      fail("Expected exception");
+    } catch (IllegalArgumentException e)
+    {
+      // expected
+      assertNull(sg1.getContext());
+    }
+    sg1.setContext(sg2);
+    assertSame(sg2, sg1.getContext());
+    sg2.setContext(sg3);
+    try
+    {
+      sg3.setContext(sg1); // circular reference :-O
+      fail("Expected exception");
+    } catch (IllegalArgumentException e)
+    {
+      // expected
+      assertNull(sg3.getContext());
+    }
+  }
 }