Promise<Content> (@NotNull final Condition<XValueGroup> groupContentResolveCondition, @NotNull final Condition<VariableView> valueSubContentResolveCondition) { assert content == null; content = new Content(); return result.thenAsync(new Function<>() { private void resolveGroups(@NotNull List<XValueGroup> valueGroups, @NotNull List<TestCompositeNode> resultNodes, @NotNull List<Promise<?>> promises) { for (XValueGroup group : valueGroups) { TestCompositeNode node = new TestCompositeNode(group); boolean computeChildren = groupContentResolveCondition.value(group); if (computeChildren) { group.computeChildren(node); } resultNodes.add(node); if (computeChildren) { promises.add(node.loadContent(Conditions.alwaysFalse(), valueSubContentResolveCondition)); } } } @NotNull @Override public Promise<Content> fun(XValueChildrenList list) { List<Promise<?>> promises = new ArrayList<>(); resolveGroups(children.getTopGroups(), content.topGroups, promises); for (int i = 0; i < children.size(); i++) { XValue value = children.getValue(i); TestValueNode node = new TestValueNode(); node.myName = children.getName(i); value.computePresentation(node, XValuePlace.TREE); content.values.add(node); promises.add(node.getResult()); // myHasChildren could be not computed yet if (value instanceof VariableView && ((VariableView)value).getValue() instanceof ObjectValue && valueSubContentResolveCondition.value((VariableView)value)) { promises.add(node.loadChildren(value)); } } resolveGroups(children.getBottomGroups(), content.bottomGroups, promises); return Promises.all(promises, content); } }); }