// for each collection in this class (e.g. Gene), test if it's a child feature
  private Set<InterMineObject> getChildFeatures(
      Map<String, SOTerm> soTerms, SOTerm soTerm, InterMineObject o) {

    // e.g. gene
    String parentSOTerm = soTerm.getName();

    // if we have not seen this class before, set relationships
    if (parentToChildren.get(parentSOTerm) == null) {
      populateParentChildMap(soTerms, parentSOTerm);
    }

    Set<InterMineObject> newCollection = new HashSet<InterMineObject>();

    Set<CollectionHolder> childHolders = parentToChildren.get(parentSOTerm);
    if (childHolders == null) {
      return null;
    }
    for (CollectionHolder h : childHolders) {
      String childCollectionName = h.getCollectionName();
      String childClassName = h.getClassName();
      try {
        Set<InterMineObject> childObjects =
            (Set<InterMineObject>) o.getFieldValue(childCollectionName);
        newCollection.addAll(childObjects);
      } catch (IllegalAccessException e) {
        LOG.error("couldn't set relationship between " + parentSOTerm + " and " + childClassName);
        return null;
      }
    }
    return newCollection;
  }
  private void check(
      CollectionHolder holder, CollectionHolder original1, CollectionHolder original2) {
    Assert.isTrue(holder != original1);
    Assert.isTrue(holder != original2);

    if (holder.name().equals("h1")) checkH1(holder);
    else checkH2(holder);
  }
  private void checkH2(CollectionHolder holder) {
    Assert.areEqual("h1", ((CollectionHolder) holder.map().get("key")).name());
    Assert.areEqual("h1", ((CollectionHolder) holder.map().get(holder)).name());

    Assert.areEqual("two", holder.list().get(0));
    Assert.areEqual("h1", ((CollectionHolder) holder.list().get(1)).name());
    Assert.areEqual(holder, holder.list().get(2));

    Assert.isTrue(holder.set().remove("two"));
    Assert.isTrue(holder.set().remove(holder));
    CollectionHolder remaining = nextCollectionHolder(holder.set().iterator());
    Assert.areEqual("h1", remaining.name());
  }
  private void checkH1(CollectionHolder holder) {
    Assert.areEqual("value", holder.map().get("key"));
    Assert.areEqual(holder, holder.map().get("key2"));
    Assert.areEqual("value2", holder.map().get(holder));

    Assert.areEqual("one", holder.list().get(0));
    Assert.areEqual(holder, holder.list().get(1));

    Assert.isTrue(holder.set().contains("one"));
    Assert.isTrue(holder.set().contains(holder));
  }
  protected void actualTest() {
    if (!a().provider().supportsHybridCollection()) return;
    if (!b().provider().supportsHybridCollection()) return;

    CollectionHolder h1 = new CollectionHolder("h1");
    CollectionHolder h2 = new CollectionHolder("h2");

    h1.map().put("key", "value");
    h1.map().put("key2", h1);
    h1.map().put(h1, "value2");

    h2.map().put("key", h1);
    h2.map().put(h2, h1);

    h1.list().add("one");
    h1.list().add(h1);

    h2.list().add("two");
    h2.list().add(h1);
    h2.list().add(h2);

    h1.set().add("one");
    h1.set().add(h1);

    h2.set().add("two");
    h2.set().add(h1);
    h2.set().add(h2);

    b().provider().storeNew(h2);
    b().provider().storeNew(h1);

    final ReplicationSession replication =
        new GenericReplicationSession(a().provider(), b().provider());

    replication.replicate(h2); // Traverses to h1.

    replication.commit();

    Iterator objects = a().provider().getStoredObjects(CollectionHolder.class).iterator();
    check(nextCollectionHolder(objects), h1, h2);
    check(nextCollectionHolder(objects), h1, h2);
  }