/**
   * @param linkages
   * @param atomLinkages
   * @return true if atomLinkages satisfy the condition; false, otherwise.
   */
  private boolean matchLinkages(List<ModificationLinkage> linkages, List<Atom[]> atomLinkages) {
    int nLink = linkages.size();
    if (nLink != atomLinkages.size()) {
      return false;
    }
    for (int i = 0; i < nLink - 1; i++) {
      ModificationLinkage link1 = linkages.get(i);
      Atom[] atoms1 = atomLinkages.get(i);
      for (int j = i + 1; j < nLink; j++) {
        ModificationLinkage link2 = linkages.get(j);
        Atom[] atoms2 = atomLinkages.get(j);

        // check components
        if (((link1.getIndexOfComponent1() == link2.getIndexOfComponent1())
                != (atoms1[0].getGroup().equals(atoms2[0].getGroup())))
            || ((link1.getIndexOfComponent1() == link2.getIndexOfComponent2())
                != (atoms1[0].getGroup().equals(atoms2[1].getGroup())))
            || ((link1.getIndexOfComponent2() == link2.getIndexOfComponent1())
                != (atoms1[1].getGroup().equals(atoms2[0].getGroup())))
            || ((link1.getIndexOfComponent2() == link2.getIndexOfComponent2())
                != (atoms1[1].getGroup().equals(atoms2[1].getGroup())))) {
          return false;
        }

        // check atoms
        String label11 = link1.getLabelOfAtomOnComponent1();
        String label12 = link1.getLabelOfAtomOnComponent2();
        String label21 = link2.getLabelOfAtomOnComponent1();
        String label22 = link2.getLabelOfAtomOnComponent2();
        if ((label11 != null && label21 != null && label11.equals(label21))
                != (atoms1[0].equals(atoms2[0]))
            || (label11 != null && label22 != null && label11.equals(label22))
                != (atoms1[0].equals(atoms2[1]))
            || (label12 != null && label21 != null && label12.equals(label21))
                != (atoms1[1].equals(atoms2[0]))
            || (label12 != null && label22 != null && label12.equals(label22))
                != (atoms1[1].equals(atoms2[1]))) {
          return false;
        }
      }
    }

    return true;
  }
  /** Get matched atoms for all linkages. */
  private List<List<Atom[]>> getMatchedAtomsOfLinkages(
      ModificationCondition condition, Map<Component, Set<Group>> mapCompGroups) {
    List<ModificationLinkage> linkages = condition.getLinkages();
    int nLink = linkages.size();

    List<List<Atom[]>> matchedAtomsOfLinkages = new ArrayList<List<Atom[]>>(nLink);

    for (int iLink = 0; iLink < nLink; iLink++) {
      ModificationLinkage linkage = linkages.get(iLink);
      Component comp1 = linkage.getComponent1();
      Component comp2 = linkage.getComponent2();

      //			boolean isAA1 = comp1.;
      //			boolean isAA2 = comp2.getType()==true;

      Set<Group> groups1 = mapCompGroups.get(comp1);
      Set<Group> groups2 = mapCompGroups.get(comp2);

      List<Atom[]> list = new ArrayList<Atom[]>();

      List<String> potentialNamesOfAtomOnGroup1 = linkage.getPDBNameOfPotentialAtomsOnComponent1();
      for (String name : potentialNamesOfAtomOnGroup1) {
        if (name.equals("*")) {
          // wildcard
          potentialNamesOfAtomOnGroup1 = null; // search all atoms
          break;
        }
      }

      List<String> potentialNamesOfAtomOnGroup2 = linkage.getPDBNameOfPotentialAtomsOnComponent2();
      for (String name : potentialNamesOfAtomOnGroup2) {
        if (name.equals("*")) {
          // wildcard
          potentialNamesOfAtomOnGroup2 = null; // search all atoms
          break;
        }
      }

      for (Group g1 : groups1) {
        for (Group g2 : groups2) {
          if (g1.equals(g2)) {
            continue;
          }

          // only for wildcard match of two residues
          boolean ignoreNCLinkage =
              potentialNamesOfAtomOnGroup1 == null
                  && potentialNamesOfAtomOnGroup2 == null
                  && residues.contains(g1)
                  && residues.contains(g2);

          Atom[] atoms =
              StructureUtil.findNearestAtomLinkage(
                  g1,
                  g2,
                  potentialNamesOfAtomOnGroup1,
                  potentialNamesOfAtomOnGroup2,
                  ignoreNCLinkage,
                  bondLengthTolerance);
          if (atoms != null) {
            list.add(atoms);
          }
        }
      }

      if (list.isEmpty()) {
        // broken linkage
        break;
      }

      matchedAtomsOfLinkages.add(list);
    }

    return matchedAtomsOfLinkages;
  }