package org.gbif.checklistbank.neo.traverse; import org.gbif.api.model.checklistbank.NameUsage; import org.gbif.api.vocabulary.Origin; import org.gbif.api.vocabulary.Rank; import org.gbif.api.vocabulary.TaxonomicStatus; import org.gbif.checklistbank.iterable.Ints; import org.gbif.checklistbank.neo.Labels; import org.gbif.checklistbank.neo.RelType; import org.gbif.checklistbank.neo.UsageDao; import org.gbif.utils.text.StringUtils; import java.io.IOException; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; import org.neo4j.helpers.collection.Iterators; import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.assertTrue; /** * */ public class ChunkingEvaluatorTest { private UsageDao dao; private int idx; private Node root; @Before public void init() throws IOException { dao = UsageDao.temporaryDao(256); try (Transaction tx = dao.beginTx()) { root = dao.createTaxon(); root.addLabel(Labels.ROOT); usage(root, "Animalia", Rank.KINGDOM, TaxonomicStatus.ACCEPTED); tx.success(); } } @After public void cleanup() { dao.closeAndDelete(); } @Test public void testChunkingFlat() { try (Transaction tx = dao.beginTx()) { Node p1 = dao.createTaxon(); root.createRelationshipTo(p1, RelType.PARENT_OF); family(p1); Node p2 = dao.createTaxon(); p1.createRelationshipTo(p2, RelType.PARENT_OF); family(p2); for (int idx = 1; idx < 100; idx++) { Node n = dao.createTaxon(); p2.createRelationshipTo(n, RelType.PARENT_OF); family(n); } tx.success(); } // test chunking assertChunking(5, 10, 2, 1); } @Test public void testChunkingDeep() { System.out.println("Preparing test graph ..."); try (Transaction tx = dao.beginTx()) { for (int i : Ints.until(3)) { Node p = dao.createTaxon(); root.createRelationshipTo(p, RelType.PARENT_OF); usage(p, "Phylum"+i, Rank.PHYLUM, TaxonomicStatus.ACCEPTED); for (int i2 : Ints.until(4)) { Node o = dao.createTaxon(); p.createRelationshipTo(o, RelType.PARENT_OF); usage(o, "Order"+i2, Rank.ORDER, TaxonomicStatus.ACCEPTED); for (int i3 : Ints.until(6)) { Node f = dao.createTaxon(); o.createRelationshipTo(f, RelType.PARENT_OF); family(f); for (int i4 : Ints.until(10)) { Node g = dao.createTaxon(); f.createRelationshipTo(g, RelType.PARENT_OF); genus(g); for (int i5 : Ints.until(25)) { Node sp = dao.createTaxon(); g.createRelationshipTo(sp, RelType.PARENT_OF); accepted(sp, Rank.SPECIES); if (i5 % 4 == 0){ for (int i6 : Ints.until(3)) { Node syn = dao.createTaxon(); syn.addLabel(Labels.SYNONYM); syn.createRelationshipTo(sp, RelType.SYNONYM_OF); synonym(syn, Rank.SPECIES); } } } } } } } tx.success(); } System.out.println("Setup completed."); // test chunking assertChunking(50, 500, 16, 72); } private void assertChunking(final int chunkMinSize, final int chunkSize, final int expectedUnchunkedNodes, final int expectedChunks) { TreeWalker.walkAcceptedTree(dao.getNeo(), new UsageMetricsHandler(dao)); int chunks = 0; int unchunkedNodes = 0; ChunkingEvaluator chunkingEvaluator = new ChunkingEvaluator(dao, chunkMinSize, chunkSize); try (Transaction tx = dao.beginTx()) { for (Node n : MultiRootNodeIterator.create(root, Traversals.TREE_WITHOUT_PRO_PARTE.evaluator(chunkingEvaluator))) { if (chunkingEvaluator.isChunk(n.getId())) { chunks++; long cnt = 1 + Iterators.count(Traversals.DESCENDANTS.traverse(n).iterator()); //System.out.println(n.getId() + ": " + cnt); assertTrue(cnt > chunkMinSize); // we cant assert a maximum chunk size //assertTrue(cnt <= chunkSize*2); }else{ unchunkedNodes++; //System.out.println(n.getId()); } } } assertEquals(expectedChunks, chunks); assertEquals(expectedUnchunkedNodes, unchunkedNodes); } private void family(Node n) { usage(n, StringUtils.randomFamily(), Rank.FAMILY, TaxonomicStatus.ACCEPTED); } private void genus(Node n) { usage(n, StringUtils.randomGenus(), Rank.GENUS, TaxonomicStatus.ACCEPTED); } private void accepted(Node n, Rank rank) { usage(n, StringUtils.randomSpecies(), rank, TaxonomicStatus.ACCEPTED); } private void synonym(Node n, Rank rank) { usage(n, StringUtils.randomSpecies(), rank, TaxonomicStatus.SYNONYM); } private void usage(Node n, String name, Rank rank, TaxonomicStatus status) { NameUsage u = new NameUsage(); u.setScientificName(name); u.setRank(rank); u.setTaxonomicStatus(status); u.setOrigin(Origin.SOURCE); dao.store(n.getId(), u, true); } }