Skip to content

Commit

Permalink
Test for tree structure. Refs #4314
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekucera committed Sep 10, 2018
1 parent fcfc34d commit 80b664e
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 27 deletions.
Expand Up @@ -19,11 +19,15 @@

public class AnnotationTree {

private DingAnnotation annotation;
// The root of the tree will be null, all other nodes must not be null
private Annotation annotation;

private List<AnnotationTree> children = new ArrayList<>();
private AnnotationTree parent;

private Map<Annotation,AnnotationTree> quickLookup;

private AnnotationTree(DingAnnotation annotation) {
private AnnotationTree(Annotation annotation) {
this.annotation = Objects.requireNonNull(annotation);
}

Expand All @@ -32,6 +36,7 @@ private AnnotationTree() {


public void add(AnnotationTree child) {
child.parent = this;
children.add(child);
}

Expand All @@ -47,23 +52,46 @@ public List<AnnotationTree> getChildren() {
return Collections.unmodifiableList(children);
}

public DingAnnotation getAnnotation() {
public Annotation getAnnotation() {
return annotation;
}

public int indexOf(AnnotationTree child) {
return children.indexOf(child);
}

public AnnotationTree parent() {
return parent;
}


public List<DingAnnotation> depthFirstOrder() {
List<DingAnnotation> annotations = new ArrayList<>();
public AnnotationTree get(Annotation a) {
if(annotation == null)
return quickLookup.get(a);

if(annotation.equals(a))
return this;

for(AnnotationTree child : children) {
AnnotationTree result = child.get(a);
if(result != null) {
return result;
}
}
return null;
}


public List<Annotation> depthFirstOrder() {
List<Annotation> annotations = new ArrayList<>();
depthFirstOrder(annotations);
return annotations;
}

private void depthFirstOrder(List<DingAnnotation> annotations) {
annotations.add(annotation);
private void depthFirstOrder(List<Annotation> annotations) {
if(annotation != null)
annotations.add(annotation);

for(AnnotationTree child : children) {
child.depthFirstOrder(annotations);
}
Expand All @@ -75,27 +103,28 @@ private void depthFirstOrder(List<DingAnnotation> annotations) {
* its possible the old session files might have annotations that contain cycles. So when loading we
* need to silently convert into a tree.
*/
public static AnnotationTree buildTree(Set<DingAnnotation> annotations) {
public static AnnotationTree buildTree(Collection<? extends Annotation> annotations) {
// We sort the annotations so that if an app created a "wrong" z-order we can make a best
// attempt at ordering the annotations in a way that is similar to the original.
List<DingAnnotation> sortedAnnotations = new ArrayList<>(annotations);
List<Annotation> sortedAnnotations = new ArrayList<>(annotations);
sortAnnotations(sortedAnnotations);

// Build the annotation tree bottom-up, cycles and duplicate membership is ignored.
AnnotationTree root = new AnnotationTree();
Map<DingAnnotation,AnnotationTree> all = new HashMap<>();
for(DingAnnotation a : annotations) {
Map<Annotation,AnnotationTree> all = new HashMap<>();
for(Annotation a : sortedAnnotations) {
addNode(a, root, all);
}
root.quickLookup = all;
return root;
}


private static void addNode(DingAnnotation a, AnnotationTree root, Map<DingAnnotation,AnnotationTree> all) {
private static void addNode(Annotation a, AnnotationTree root, Map<Annotation,AnnotationTree> all) {
AnnotationTree n = all.computeIfAbsent(a, AnnotationTree::new);

if(a.getGroupParent() != null) {
DingAnnotation ga = (DingAnnotation)a.getGroupParent();
if(a instanceof DingAnnotation && ((DingAnnotation)a).getGroupParent() != null) {
DingAnnotation ga = (DingAnnotation)((DingAnnotation)a).getGroupParent();
AnnotationTree pn = all.get(ga);
if(pn == null) {
// Now we can create the Nodes for each GroupAnnotation we find,
Expand Down Expand Up @@ -163,19 +192,23 @@ public static List<DingAnnotation> getRootSet(Set<DingAnnotation> allAnnotations
}


private static void sortAnnotations(List<DingAnnotation> annotations) {
private static void sortAnnotations(List<Annotation> annotations) {
// Sort the annotations by existing z-order.
// This will give us a decent heuristic for how to order the annotations if their z-order is screwed up.
// Once the z-order is "fixed" this will maintain the established order.
Comparator<DingAnnotation> comparator = (a1, a2) -> {
Comparator<Annotation> comparator = (a1, a2) -> {
if (a1 instanceof DingAnnotation && a2 instanceof DingAnnotation) {
DingAnnotation da1 = (DingAnnotation) a1;
DingAnnotation da2 = (DingAnnotation) a2;
JComponent canvas1 = da1.getCanvas();
JComponent canvas2 = da2.getCanvas();
int z1 = canvas1.getComponentZOrder(da1.getComponent());
int z2 = canvas2.getComponentZOrder(da2.getComponent());
return Integer.compare(z1, z2);
if(z1 >= 0 && z2 >= 0) {
return Integer.compare(z1, z2);
} else {
return a1.getName().compareToIgnoreCase(a2.getName());
}
}
return 0;
};
Expand Down
Expand Up @@ -183,6 +183,10 @@ public void dispose() {
backGroundCanvas.dispose();
}

public AnnotationTree getAnnotationTree() {
return AnnotationTree.buildTree(annotationSet);
}

public void loadAnnotations() {
CyNetwork network = view.getModel();
// Now, see if this network has any existing annotations
Expand Down
Expand Up @@ -115,14 +115,14 @@ public void addMember(Annotation member) {

// We muck with the ZOrder directly, so we need to make sure we're on the EDT
ViewUtil.invokeOnEDTAndWait(() -> {
// First, we need to make sure that this annotation is already registered and added to the canvas
if (dMember.getCanvas() != null) {
dMember.addComponent(dMember.getCanvas());
} else {
dMember.addComponent(cyAnnotator.getForeGroundCanvas());
}

dMember.update();
// // First, we need to make sure that this annotation is already registered and added to the canvas
// if (dMember.getCanvas() != null) {
// dMember.addComponent(dMember.getCanvas());
// } else {
// dMember.addComponent(cyAnnotator.getForeGroundCanvas());
// }
//
// dMember.update();

if (!annotations.contains(dMember))
annotations.add(dMember);
Expand Down
Expand Up @@ -4,12 +4,16 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.HashMap;
import java.util.Map;

import org.cytoscape.ding.NetworkViewTestSupport;
import org.cytoscape.ding.impl.DGraphView;
import org.cytoscape.ding.impl.cyannotator.create.GroupAnnotationFactory;
import org.cytoscape.ding.impl.cyannotator.create.ShapeAnnotationFactory;
import org.cytoscape.event.CyEventHelper;
import org.cytoscape.service.util.CyServiceRegistrar;
import org.cytoscape.view.presentation.annotations.Annotation;
import org.cytoscape.view.presentation.annotations.AnnotationManager;
import org.cytoscape.view.presentation.annotations.GroupAnnotation;
import org.cytoscape.view.presentation.annotations.ShapeAnnotation;
Expand Down Expand Up @@ -37,11 +41,29 @@ public void before() {
groupFactory = new GroupAnnotationFactory(registrar);
}



protected ShapeAnnotation createShapeAnnotation() {
return shapeFactory.createAnnotation(ShapeAnnotation.class, graphView, emptyMap());
}

protected ShapeAnnotation createShapeAnnotation(String name, int zorder) {
return shapeFactory.createAnnotation(ShapeAnnotation.class, graphView, toArgs(name, zorder));
}

protected GroupAnnotation createGroupAnnotation() {
return groupFactory.createAnnotation(GroupAnnotation.class, graphView, emptyMap());
}

protected GroupAnnotation createGroupAnnotation(String name, int zorder) {
return groupFactory.createAnnotation(GroupAnnotation.class, graphView, toArgs(name, zorder));
}


private static Map<String, String> toArgs(String name, int zorder) {
Map<String,String> args = new HashMap<>();
args.put(Annotation.NAME, name);
args.put(Annotation.Z, String.valueOf(zorder));
return args;
}
}
@@ -1,8 +1,11 @@
package org.cytoscape.ding.impl.cyannotator;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.cytoscape.ding.impl.cyannotator.annotations.DingAnnotation;
Expand Down Expand Up @@ -165,15 +168,59 @@ public void testDetectNoCycleBig() {
}


@Test
public void testConvertToTree() {
GroupAnnotation group2 = createGroupAnnotation("group2", 0);
GroupAnnotation group1 = createGroupAnnotation("group1", 1);
ShapeAnnotation shape1 = createShapeAnnotation("shape1", 2);
ShapeAnnotation shape2 = createShapeAnnotation("shape2", 3);
ShapeAnnotation shape3 = createShapeAnnotation("shape3", 4);
group1.addMember(shape1);
group1.addMember(shape2);
group2.addMember(group1);
group2.addMember(shape3);

Set<DingAnnotation> annotations = asSet(shape1, shape2, shape3, group1, group2);
AnnotationTree root = AnnotationTree.buildTree(annotations);

// the root of the tree does not contain an annotation
assertNull(root.getAnnotation());
assertEquals(1, root.childCount());

AnnotationTree ng2 = root.getChildren().get(0);
assertEquals("group2", ng2.getAnnotation().getName());
assertEquals(2, ng2.childCount());
assertEquals("shape3", ng2.getChildren().get(1).getAnnotation().getName());
AnnotationTree ng1 = ng2.getChildren().get(0);
assertEquals("group1", ng1.getAnnotation().getName());
assertEquals(2, ng1.childCount());
assertEquals("shape1", ng1.getChildren().get(0).getAnnotation().getName());
assertEquals("shape2", ng1.getChildren().get(1).getAnnotation().getName());

List<Annotation> depthFirst = root.depthFirstOrder();
assertEquals(5, depthFirst.size());
assertEquals("group2", depthFirst.get(0).getName());
assertEquals("group1", depthFirst.get(1).getName());
assertEquals("shape1", depthFirst.get(2).getName());
assertEquals("shape2", depthFirst.get(3).getName());
assertEquals("shape3", depthFirst.get(4).getName());

assertEquals(ng2, root.get(group2));
assertEquals(ng1, root.get(group1));
assertEquals(ng1.getChildren().get(0), ng1.get(shape1));
}


@Test
public void testDetectDuplicateMembership() {

GroupAnnotation group1 = createGroupAnnotation();
GroupAnnotation group2 = createGroupAnnotation();
ShapeAnnotation shape1 = createShapeAnnotation();
group1.addMember(shape1);
try {
group2.addMember(shape1);
fail();
} catch(IllegalAnnotationStructureException e) {}
}


Expand Down
Expand Up @@ -12,7 +12,7 @@
import org.junit.Ignore;
import org.junit.Test;

public class AnnotationStructureTest extends AnnotationTest {
public class AnnotatorStructureTest extends AnnotationTest {


@Test
Expand Down

0 comments on commit 80b664e

Please sign in to comment.