PackageGraph implements ProgressCheck { public boolean isLeftDescendantOfRight(final @NotNull PackageId left, final @NotNull PackageId right) { if (left.equals(right)) { return true; } return Optional.ofNullable(getOrCreateNode(left).getParent()) .map(parent -> isLeftDescendantOfRight(parent.getId(), right)) .orElse(false); }  @Override Collection<Violation> getReportedViolations(); @Override void startedScan(); @Override void identifyPackage(final PackageId packageId, final File file); @Override void identifySubpackage(final PackageId packageId, final PackageId parentId); @Override void identifyEmbeddedPackage(final PackageId packageId, final PackageId parentId,
                                        final EmbeddedPackageInstallable slingInstallable); boolean isIdentified(final @NotNull PackageId packageId); @Nullable PackageId getLastIdentified(); boolean isRoot(final @NotNull PackageId packageId); boolean isLeftDescendantOfRight(final @NotNull PackageId left, final @NotNull PackageId right); Collection<PackageId> getSelfAndAncestors(final @NotNull PackageId self); Collection<PackageId> getSelfAndDescendants(final @NotNull PackageId self);  }
@Test public void testIsLeftDescendantOfRight() { assertTrue("expect yes: cont1 -> cont1", graph.isLeftDescendantOfRight(container1, container1)); assertTrue("expect yes: cont2 -> cont2", graph.isLeftDescendantOfRight(container2, container2)); assertFalse("expect not: cont1 -> cont2", graph.isLeftDescendantOfRight(container1, container2)); assertFalse("expect not: cont2 -> cont1", graph.isLeftDescendantOfRight(container2, container1)); assertTrue("expect yes: cont1sub1 -> cont1", graph.isLeftDescendantOfRight(cont1sub1, container1)); assertFalse("expect not: cont1 -> cont1sub1 ", graph.isLeftDescendantOfRight(container1, cont1sub1)); assertTrue("expect yes: cont1emb1 -> cont1", graph.isLeftDescendantOfRight(cont1emb1, container1)); assertFalse("expect not: cont1 -> cont1emb1 ", graph.isLeftDescendantOfRight(container1, cont1emb1)); assertFalse("expect not: cont1sub1 -> cont1emb1 ", graph.isLeftDescendantOfRight(cont1sub1, cont1emb1)); assertFalse("expect not: cont1emb1 -> cont1sub1 ", graph.isLeftDescendantOfRight(cont1emb1, cont1sub1)); assertTrue("expect yes: cont2sub1 -> cont2", graph.isLeftDescendantOfRight(cont2sub1, container2)); assertFalse("expect not: cont2 -> cont2sub1 ", graph.isLeftDescendantOfRight(container2, cont2sub1)); assertTrue("expect yes: cont2emb1 -> cont2", graph.isLeftDescendantOfRight(cont2emb1, container2)); assertFalse("expect not: cont2 -> cont2emb1 ", graph.isLeftDescendantOfRight(container2, cont2emb1)); assertFalse("expect not: cont2sub1 -> cont2emb1 ", graph.isLeftDescendantOfRight(cont2sub1, cont2emb1)); assertFalse("expect not: cont2emb1 -> cont2sub1 ", graph.isLeftDescendantOfRight(cont2emb1, cont2sub1)); graph.identifyPackage(cont1sub1, null); assertFalse("expect not after new event: cont1sub1 -> cont1", graph.isLeftDescendantOfRight(cont1sub1, container1)); graph.identifySubpackage(container2, cont1emb1); assertTrue("expect yes after new event: cont2 -> cont1emb1", graph.isLeftDescendantOfRight(container2, cont1emb1)); assertTrue("expect yes after new event: cont2 -> cont1", graph.isLeftDescendantOfRight(container2, container1)); graph.identifyEmbeddedPackage(container1, cont2sub1, null); assertTrue("expect yes after cycle: cont2 -> cont1emb1", graph.isLeftDescendantOfRight(container2, cont1emb1)); assertFalse("expect not after cycle: cont2 -> cont1", graph.isLeftDescendantOfRight(container2, container1)); assertFalse("expect not after cycle: cont1emb1 -> cont1", graph.isLeftDescendantOfRight(cont1emb1, container1)); assertTrue("expect cont1emb1 is root after cycle", graph.isRoot(cont1emb1)); }