/**
   * Shift application conditions (NAC / PAC) of the kernel rule along embedding morphism of the
   * given multi rule (left embedding: kernel.LHS -> multi.LHS, right embedding: kernel.RHS ->
   * multi.RHS). Shifted application condition is added to the list of the own application
   * conditions of the multi rule.
   */
  private boolean shiftApplCondsOfKernelToMultiRule(final MultiRule multiRule) {
    // shift PACS
    List<OrdinaryMorphism> kernConds = this.kernelRule.getPACsList();
    for (int i = 0; i < kernConds.size(); i++) {
      OrdinaryMorphism kernCond = kernConds.get(i);
      if (kernCond.isEnabled()) {
        OrdinaryMorphism shiftCond =
            this.shiftApplCondAlongMorph(kernCond, multiRule.getEmbeddingLeft());
        if (shiftCond != null) {
          shiftCond.setName(kernCond.getName().concat("(shifted)"));
          shiftCond.setEnabled(kernCond.isEnabled());

          multiRule.addShiftedKernelApplCond(shiftCond, true);
          this.shiftDone = true;
        }
      }
    }
    // shift NACs
    kernConds = this.kernelRule.getNACsList();
    for (int i = 0; i < kernConds.size(); i++) {
      OrdinaryMorphism kernCond = kernConds.get(i);
      if (kernCond.isEnabled()) {
        OrdinaryMorphism shiftCond =
            this.shiftApplCondAlongMorph(kernCond, multiRule.getEmbeddingLeft());
        if (shiftCond != null) {
          shiftCond.setName(kernCond.getName().concat("(shifted)"));
          shiftCond.setEnabled(kernCond.isEnabled());

          multiRule.addShiftedKernelApplCond(shiftCond, false);
          this.shiftDone = true;
        }
      }
    }

    // shift NestedACs
    kernConds = this.kernelRule.getNestedACsList();
    for (int i = 0; i < kernConds.size(); i++) {
      if (kernConds.get(i) instanceof NestedApplCond) {
        NestedApplCond kernCond = (NestedApplCond) kernConds.get(i);
        if (kernCond.isEnabled()) {
          NestedApplCond shiftCond =
              this.shiftNestedApplCondAlongEmbMorphism(
                  kernCond,
                  multiRule.getEmbeddingLeft(),
                  this.kernelRule.getRight().getAttrContext());
          if (shiftCond != null) {
            shiftCond.setName(kernCond.getName().concat("(shifted)"));
            shiftCond.setEnabled(kernCond.isEnabled());

            multiRule.addShiftedKernelNestedApplCond(shiftCond);
            this.shiftDone = true;
          }
        }
      } else break;
    }

    addAttrCondsOfKernelToMultiRule(multiRule);

    return true;
  }
  private NestedApplCond shiftNestedApplCondAlongEmbMorphism(
      final NestedApplCond cond, final OrdinaryMorphism embedding, final AttrContext ac) {

    if (cond.getSource() == embedding.getSource()) {
      final OrdinaryMorphism condIso = cond.getTarget().isomorphicCopy();
      if (condIso == null) return null;

      final NestedApplCond shiftCond =
          new NestedApplCond(embedding.getTarget(), condIso.getTarget(), ac);
      if (this.propagateMapping(cond, shiftCond, embedding, condIso)) {

        for (int i = 0; i < cond.getNestedACs().size(); i++) {
          NestedApplCond nc = cond.getNestedACAt(i);
          final NestedApplCond shiftnc =
              shiftNestedApplCondAlongEmbMorphism(nc, condIso, cond.getAttrContext());
          if (shiftnc != null) {
            shiftnc.setName(nc.getName());
            shiftnc.setEnabled(nc.isEnabled());
            shiftCond.addNestedAC(shiftnc);
          } else return null;
        }

        return shiftCond;
      }

      shiftCond.dispose();
      condIso.dispose();
    }
    return null;
  }