final Map<String, BasicOperator> mso,
final BasicOperator rootOperator) {
final Collection<BasicOperator> deleted = new LinkedList<BasicOperator>();
final Collection<BasicOperator> added = new LinkedList<BasicOperator>();
final Union union = (Union) mso.get("union");
final Join join = (Join) mso.get("join");
final int id = union.getOperatorIDTuple(join).getId();
final List<BasicOperator> unionOperands = union.getPrecedingOperators();
union.setPrecedingOperator(join);
union.setSucceedingOperators(join.getSucceedingOperators());
for (final OperatorIDTuple oid : join.getSucceedingOperators()) {
oid.getOperator().removePrecedingOperator(join);
oid.getOperator().addPrecedingOperator(union);
}
final List<OperatorIDTuple> precedingOperatorsJoin = new LinkedList<OperatorIDTuple>();
for (final BasicOperator bo : join.getPrecedingOperators()) {
if (!(bo.equals(union))) {
precedingOperatorsJoin.add(new OperatorIDTuple(bo, bo
.getOperatorIDTuple(join).getId()));
}
}
boolean firstTime = true;
for (final BasicOperator toMove : unionOperands) {
Join joinNew;
if (firstTime) {
// use existing join operator
joinNew = join;
joinNew.removePrecedingOperator(union);
firstTime = false;
} else {
// clone join operator plus its other operands
joinNew = new Join();
added.add(joinNew);
union.addPrecedingOperator(joinNew);
for (final OperatorIDTuple oid : precedingOperatorsJoin) {
final BasicOperator toClone = oid.getOperator();
final BasicOperator clone = toClone.clone();
added.add(clone);
clone.setSucceedingOperator(new OperatorIDTuple(joinNew,
oid.getId()));
joinNew.addPrecedingOperator(clone);
cloneFurther(clone, toClone, added);
}
}
joinNew.setSucceedingOperator(new OperatorIDTuple(union, union
.getPrecedingOperators().size() - 1));
joinNew.addPrecedingOperator(toMove);
final LinkedList<Variable> intersectionVariables = new LinkedList<Variable>();
final LinkedList<Variable> unionVariables = new LinkedList<Variable>();
intersectionVariables.addAll(joinNew.getPrecedingOperators().get(0)
.getUnionVariables());
for (final BasicOperator bo : joinNew.getPrecedingOperators()) {
unionVariables.addAll(bo.getUnionVariables());
intersectionVariables.retainAll(bo.getUnionVariables());
}
joinNew.setIntersectionVariables(intersectionVariables);
joinNew.setUnionVariables(unionVariables);
toMove.setSucceedingOperator(new OperatorIDTuple(joinNew, id));
}
if (deleted.size() > 0 || added.size() > 0)
return new Tuple<Collection<BasicOperator>, Collection<BasicOperator>>(