protected void replace(HashMap<Class<?>, HashSet<BasicOperator>> _startNodes) {
    // remove obsolete connections...
    for (lupos.engine.operators.BasicOperator _parent : this.o1) {
      _parent.removeSucceedingOperator(this.f);
      this.f.removePrecedingOperator(_parent);
    }

    for (lupos.engine.operators.BasicOperator _child : this.o2) {
      this.f.removeSucceedingOperator(_child);
      _child.removePrecedingOperator(this.f);
    }

    // add new operators...
    lupos.rif.operator.RuleFilter rf = null;
    rf = new lupos.rif.operator.RuleFilter();

    // add new connections...
    for (lupos.engine.operators.BasicOperator _parent : this.o1) {
      _parent.addSucceedingOperator(rf);
      rf.addPrecedingOperator(_parent);
    }

    for (lupos.engine.operators.BasicOperator _child : this.o2) {
      rf.addSucceedingOperator(_child);
      _child.addPrecedingOperator(rf);
    }

    // delete unreachable operators...
    this.deleteOperatorWithoutParentsRecursive(this.f, _startNodes);

    // additional replace method code...
    lupos.optimizations.sparql2core_sparql.SPARQLParserVisitorImplementationDumper filterDumper =
        new lupos.optimizations.sparql2core_sparql.SPARQLParserVisitorImplementationDumper();

    String equalsString =
        (String)
            filterDumper.visit(
                (lupos.sparql1_1.ASTEqualsNode) this.f.getNodePointer().jjtGetChild(0));

    lupos.rif.model.Equality equality = null;

    try {
      lupos.rif.generated.syntaxtree.RIFAtomic atomic =
          new lupos.rif.generated.parser.RIFParser(
                  new java.io.StringReader(equalsString.substring(1, equalsString.length() - 1)))
              .RIFAtomic();
      lupos.rif.visitor.ParseSyntaxTreeVisitor rifParser =
          new lupos.rif.visitor.ParseSyntaxTreeVisitor();
      equality = (lupos.rif.model.Equality) atomic.accept(rifParser, null);
    } catch (lupos.rif.generated.parser.ParseException e) {
      e.printStackTrace();
      return;
    }

    rf.setExpression(equality);
    rf.setUnionVariables(this.f.getUnionVariables());
    rf.setIntersectionVariables(this.f.getIntersectionVariables());
  }
 public void deleteAllBelow(
     final BasicOperator parent,
     final BasicOperator child,
     final Collection<BasicOperator> deleted) {
   if (child.getPrecedingOperators().size() > 1) {
     parent.removeSucceedingOperator(child);
     child.removePrecedingOperator(parent);
   } else {
     deleted.add(parent);
     final OperatorIDTuple[] opIDTuples =
         child.getSucceedingOperators().toArray(new OperatorIDTuple[0]);
     for (final OperatorIDTuple opIDTuple : opIDTuples) {
       deleteAllBelow(child, opIDTuple.getOperator(), deleted);
     }
   }
 }
  /** {@inheritDoc} */
  @Override
  public Tuple<Collection<BasicOperator>, Collection<BasicOperator>> transformOperatorGraph(
      final Map<String, BasicOperator> mso, final BasicOperator rootOperator) {
    final Collection<BasicOperator> deleted = new LinkedList<BasicOperator>();
    final Collection<BasicOperator> added = new LinkedList<BasicOperator>();
    final ReplaceVar replaceVar = (ReplaceVar) mso.get("replaceVar");

    final LinkedList<BasicOperator> pres =
        (LinkedList<BasicOperator>) replaceVar.getPrecedingOperators();
    final LinkedList<OperatorIDTuple> succs =
        (LinkedList<OperatorIDTuple>) replaceVar.getSucceedingOperators();

    BasicOperator pre;
    OperatorIDTuple idTuple;
    // Connect all precessors to all successors
    for (int i = 0; i < pres.size(); i++) {
      for (int a = 0; a < succs.size(); a++) {
        idTuple = succs.get(a);
        pre = pres.get(i);
        pre.addSucceedingOperator(new OperatorIDTuple(idTuple.getOperator(), idTuple.getId()));
        pre.removeSucceedingOperator(replaceVar);
      }
    }

    BasicOperator succ;
    // And all successors to all precessors
    for (int i = 0; i < succs.size(); i++) {
      for (int a = 0; a < pres.size(); a++) {
        succ = succs.get(i).getOperator();
        succ.addPrecedingOperator(pres.get(a));
        succ.removePrecedingOperator(replaceVar);
      }
    }

    rootOperator.deleteParents();
    rootOperator.setParents();
    rootOperator.detectCycles();
    // should have been done manually: rootOperator.sendMessage(new
    // BoundVariablesMessage());
    deleted.add(replaceVar);
    if (deleted.size() > 0 || added.size() > 0)
      return new Tuple<Collection<BasicOperator>, Collection<BasicOperator>>(added, deleted);
    else return null;
  }
  @Override
  public Tuple<Collection<BasicOperator>, Collection<BasicOperator>> transformOperatorGraph(
      final Map<String, BasicOperator> mso, final BasicOperator rootOperator) {
    final GenerateAddEnv genAdd = (GenerateAddEnv) mso.get("genAdd");
    final Optional optional = (Optional) mso.get("optional");

    final LinkedList<BasicOperator> pres =
        (LinkedList<BasicOperator>) genAdd.getPrecedingOperators();
    final LinkedList<OperatorIDTuple> succs =
        (LinkedList<OperatorIDTuple>) optional.getSucceedingOperators();

    BasicOperator pre;
    for (int i = 0; i < pres.size(); i++) {
      pre = pres.get(i);
      pre.addSucceedingOperator(new OperatorIDTuple(optional, 0));
      pre.removeSucceedingOperator(genAdd);
      optional.addPrecedingOperator(pre);
    }

    optional.removePrecedingOperator(genAdd);
    optional.setSucceedingOperator(new OperatorIDTuple(genAdd, 0));

    genAdd.setPrecedingOperator(optional);
    genAdd.setSucceedingOperators(succs);

    BasicOperator succ;
    for (int i = 0; i < succs.size(); i++) {
      succ = succs.get(i).getOperator();
      succ.addPrecedingOperator(genAdd);
      succ.removePrecedingOperator(optional);
    }

    rootOperator.deleteParents();
    rootOperator.setParents();
    rootOperator.detectCycles();
    rootOperator.sendMessage(new BoundVariablesMessage());
    return null;
  }