private LeftJoinNode liftCondition(LeftJoinNode leftJoinNode, QueryNode leftChild, DataNode rightChild,
ImmutableSet<Variable> requiredVariablesAboveLJ, QueryTreeComponent treeComponent,
Optional<ImmutableSubstitution<ImmutableTerm>> remainingRightSubstitution,
VariableGenerator variableGenerator, IntermediateQuery query) {
ImmutableExpression ljCondition = leftJoinNode.getOptionalFilterCondition()
.orElseThrow(() -> new IllegalArgumentException("The LJ is expected to have a joining condition"));
ImmutableSet<Variable> leftVariables = query.getVariables(leftChild);
ImmutableSet<Variable> requiredRightVariables = requiredVariablesAboveLJ.stream()
.filter(v -> !leftVariables.contains(v))
.collect(ImmutableCollectors.toSet());
ImmutableSet<Variable> rightVariablesToUpdate = Optional.of(ljCondition)
.filter(c -> c.getFunctionSymbol().equals(IS_NOT_NULL))
.map(c -> c.getArguments().get(0))
.filter(t -> t instanceof Variable)
.map(v -> (Variable) v)
.map(specialVariable -> requiredRightVariables.stream()
.filter(v -> !v.equals(specialVariable))
.collect(ImmutableCollectors.toSet()))
.orElse(requiredRightVariables);
LeftJoinNode newLeftJoinNode = leftJoinNode.changeOptionalFilterCondition(Optional.empty());
treeComponent.replaceNode(leftJoinNode, newLeftJoinNode);
return (rightVariablesToUpdate.isEmpty() && (!remainingRightSubstitution.isPresent()))
? newLeftJoinNode
: updateConditionalVariables(rightVariablesToUpdate, rightChild, newLeftJoinNode, ljCondition,
query, treeComponent, remainingRightSubstitution, variableGenerator);
}