/**
   * Computes if the first rule exclude the second rule. The result is added to the container.
   *
   * @param r1 The first rule.
   * @param r2 The second rule.
   */
  protected synchronized void computeCritical(Rule r1, Rule r2) {
    Report.trace("LayeredDependencyPairContainer: starte computeCritical", 2);
    // System.out.println("LayeredDependencyPairContainer.computeCritical(r1,
    // r2): "+r1.getName()+" "+r2.getName()+" "+this.getEntry(r1,
    // r2).state);
    // mark Entry
    if (!r1.isEnabled() || !r2.isEnabled()) { // test disabled rule
      this.getEntry(r1, r2).state = Entry.DISABLED;
      addEntry(r1, r2, false, null);
      addQuadruple(this.excludeContainer, r1, r2, false, null);
      addQuadruple(this.conflictFreeContainer, r1, r2, false, null);
      firePairEvent(
          new CriticalPairEvent(
              this,
              r1,
              r2,
              "<" + r1.getName() + ">  and  <" + r2.getName() + ">  should not be computed."));
      return;
    }

    if (r1.getLayer() != r2.getLayer()) { // test rule layer
      this.getEntry(r1, r2).state = Entry.NOT_RELATED;
      addEntry(r1, r2, false, null);
      addQuadruple(this.excludeContainer, r1, r2, false, null);
      addQuadruple(this.conflictFreeContainer, r1, r2, false, null);
      firePairEvent(new CriticalPairEvent(this, r1, r2, ""));
      return;
    }

    if ((this.layer > -1) && (r1.getLayer() != this.layer)) {
      return;
    }

    if ((this.getEntry(r1, r2).state == Entry.SCHEDULED_FOR_COMPUTING)
        || (this.getEntry(r1, r2).state == Entry.NOT_SET)) {
      getEntry(r1, r2).setState(Entry.COMPUTING_IS_RUNNING);

      firePairEvent(
          new CriticalPairEvent(
              this,
              r1,
              r2,
              "Computing critical rule pair  [  " + r1.getName() + "  ,  " + r2.getName() + "  ]"));

      if (!this.complete) {
        this.layeredPair = null;

        this.layeredSimplePair = new LayeredSimpleDependencyPair();
        this.excludePair = this.layeredSimplePair;
      } else {
        this.layeredSimplePair = null;

        this.layeredPair = new LayeredDependencyPair();
        this.excludePair = this.layeredPair;
      }

      setOptionsOfExcludePair();

      Vector<
              Pair<
                  Pair<OrdinaryMorphism, OrdinaryMorphism>,
                  Pair<OrdinaryMorphism, OrdinaryMorphism>>>
          overlapping = null;

      try {
        if (this.layeredPair != null) {
          overlapping = this.layeredPair.isCritical(CriticalPair.EXCLUDE, r1, r2);
        } else if (this.layeredSimplePair != null) {
          overlapping = this.layeredSimplePair.isCritical(CriticalPair.EXCLUDE, r1, r2);
        }
      } catch (InvalidAlgorithmException iae) {
        System.out.println(iae.getLocalizedMessage());
      }

      if (this.excludePair != null) this.excludePair.dispose();
      this.excludePair = null;
      this.layeredPair = null;
      this.layeredSimplePair = null;
      //			System.gc();

      boolean critic = (overlapping != null);

      // new container
      addEntry(r1, r2, critic, overlapping);

      /*
       * Wenn overlapping Elemente enthaelt sind r1/r2 kritisch critic
       * wird daher true. Alle wichtigen Informationen werden eingetragen.
       * Enthaelt r1/r2 keine Elementen, so wird critic auf false gesetzt.
       * Wenn excludeContainer nach r1/r2 gefragt wird, liefert die
       * Antwort auch false. overlapping kann daher null sein.
       */

      /*
       * Achtung, wenn r1 r2 nicht kritisch ist gibt es keine
       * Ueberlappungen
       */
      addQuadruple(this.excludeContainer, r1, r2, critic, overlapping);

      /*
       * conflictfree braucht keine ueberlappungsgraphen daher ist das
       * letzte Argument null
       */
      addQuadruple(this.conflictFreeContainer, r1, r2, !critic, null);

      if (overlapping != null)
        firePairEvent(
            new CriticalPairEvent(
                this,
                r1,
                r2,
                "<" + r1.getName() + ">  and  <" + r2.getName() + ">  have critical pairs"));
      else
        firePairEvent(
            new CriticalPairEvent(
                this,
                r1,
                r2,
                "<" + r1.getName() + ">  and  <" + r2.getName() + ">  have no critical pairs"));
    }
    Report.trace("LayeredDependencyPairContainer: beende computeCritical", -2);
  }
  /**
   * Reads the contents of a xml file to restore this object.
   *
   * @param h A helper object for loading.
   */
  public void XreadObject(XMLHelper h) {
    if (h.isTag("CriticalPairs", this)) {
      // System.out.println("LayerExcludePairContainer.XreadObject ...");
      Rule r1 = null;
      Rule r2 = null;
      boolean b = false;
      Vector<
              Pair<
                  Pair<OrdinaryMorphism, OrdinaryMorphism>,
                  Pair<OrdinaryMorphism, OrdinaryMorphism>>>
          allOverlappings = null;
      Vector<String> tagnames = new Vector<String>(1);
      Vector<String> tagnames2 = new Vector<String>(1);

      this.grammar = BaseFactory.theFactory().createGraGra();
      h.getObject("", this.grammar, true);

      tagnames.add("conflictContainer");
      tagnames.add("conflictsContainer");
      tagnames.add("excludeContainer");

      tagnames2.add("dependencyContainer");
      tagnames2.add("dependenciesContainer");

      this.switchDependency = false;

      if (h.readSubTag(tagnames2)) {
        this.conflictKind = CriticalPair.TRIGGER_DEPENDENCY;
        if (h.readAttr("kind").equals("trigger_switch_dependency")) {
          this.switchDependency = true;
          this.conflictKind = CriticalPair.TRIGGER_SWITCH_DEPENDENCY;
        }
      } else if (h.readSubTag(tagnames)) {
        this.conflictKind = CriticalPair.CONFLICT;
      }

      if (this.conflictKind == CriticalPair.TRIGGER_DEPENDENCY
          || this.conflictKind == CriticalPair.TRIGGER_SWITCH_DEPENDENCY
          || this.conflictKind == CriticalPair.CONFLICT) {
        Enumeration<?> r1s = h.getEnumeration("", null, true, "Rule");
        if (!r1s.hasMoreElements()) r1s = h.getEnumeration("", null, true, "Regel");
        while (r1s.hasMoreElements()) {
          h.peekElement(r1s.nextElement());
          /*
           * da ein referenziertes object geholt werden soll. muss nur
           * angegeben werden wie der Membername heisst.
           */
          r1 = (Rule) h.getObject("R1", null, false);
          Enumeration<?> r2s = h.getEnumeration("", null, true, "Rule");
          if (!r2s.hasMoreElements()) r2s = h.getEnumeration("", null, true, "Regel");
          while (r2s.hasMoreElements()) {
            h.peekElement(r2s.nextElement());
            r2 = (Rule) h.getObject("R2", null, false);
            String bool = h.readAttr("bool");
            allOverlappings = null;
            b = false;
            if (bool.equals("true")) {
              b = true;
              allOverlappings =
                  new Vector<
                      Pair<
                          Pair<OrdinaryMorphism, OrdinaryMorphism>,
                          Pair<OrdinaryMorphism, OrdinaryMorphism>>>();
              Enumeration<?> overlappings = h.getEnumeration("", null, true, "Overlapping_Pair");
              while (overlappings.hasMoreElements()) {
                h.peekElement(overlappings.nextElement());
                Graph g = (Graph) h.getObject("", new Graph(), true);

                while (h.readSubTag("Critical")) {
                  GraphObject o = (GraphObject) h.getObject("object", null, false);
                  if (o != null) o.setCritical(true);
                  h.close();
                }
                /*
                 * OrdinaryMorphism first =
                 * BaseFactory.theFactory().createMorphism(r1.getRight(),g);
                 * first.readMorphism(h); OrdinaryMorphism
                 * second =
                 * BaseFactory.theFactory().createMorphism(r2.getLeft(),g);
                 * second.readMorphism(h);
                 * allOverlappings.addElement(new
                 * Pair(first,second));
                 */

                Pair<
                        Pair<OrdinaryMorphism, OrdinaryMorphism>,
                        Pair<OrdinaryMorphism, OrdinaryMorphism>>
                    p = readOverlappingMorphisms(h, r1, r2, g);
                allOverlappings.addElement(p);

                h.close();
              }
            }
            addQuadruple(this.excludeContainer, r1, r2, b, allOverlappings);
            h.close();
          }
          h.close();
        }
        h.close();
        // System.out.println("excludeContainer
        // "+excludeContainer+"\n");
      } /* Ende readSubTag("excludeContainer") */
      if (h.readSubTag("conflictFreeContainer")) {
        Enumeration<?> r1s = h.getEnumeration("", null, true, "Rule");
        if (!r1s.hasMoreElements()) r1s = h.getEnumeration("", null, true, "Regel");
        while (r1s.hasMoreElements()) {
          h.peekElement(r1s.nextElement());
          /*
           * da ein referenziertes object geholt werden soll. muss nur
           * angegeben werden wie der Membername heisst.
           */
          r1 = (Rule) h.getObject("R1", null, false);
          Enumeration<?> r2s = h.getEnumeration("", null, true, "Rule");
          if (!r2s.hasMoreElements()) r2s = h.getEnumeration("", null, true, "Regel");
          while (r2s.hasMoreElements()) {
            h.peekElement(r2s.nextElement());
            r2 = (Rule) h.getObject("R2", null, false);
            String bool = h.readAttr("bool");
            b = false;
            if (bool.equals("true")) b = true;
            addQuadruple(this.conflictFreeContainer, r1, r2, b, null);

            if (!r1.isEnabled()) // test disabled rule
            this.getEntry(r1, r2).state = Entry.DISABLED;
            else if (r1.getLayer() != r2.getLayer()) // test rule
              // layer
              this.getEntry(r1, r2).state = Entry.NOT_RELATED;

            h.close();
          }
          h.close();
        }
        h.close();
        // System.out.println("conflictFreeContainer
        // "+conflictFreeContainer+"\n");
      }
    }
    // isComputed = true;
    h.close();
  }