/**
   * Record unidentifiable atom linkages in a chain. Only linkages between two residues or one
   * residue and one ligand will be recorded.
   */
  private void recordUnidentifiableAtomLinkages(
      List<ModifiedCompound> modComps, List<Group> ligands) {

    // first put identified linkages in a map for fast query
    Set<StructureAtomLinkage> identifiedLinkages = new HashSet<StructureAtomLinkage>();
    for (ModifiedCompound mc : modComps) {
      identifiedLinkages.addAll(mc.getAtomLinkages());
    }

    // record
    // cross link
    int nRes = residues.size();
    for (int i = 0; i < nRes - 1; i++) {
      Group group1 = residues.get(i);
      for (int j = i + 1; j < nRes; j++) {
        Group group2 = residues.get(j);
        List<Atom[]> linkages =
            StructureUtil.findAtomLinkages(group1, group2, true, bondLengthTolerance);
        for (Atom[] atoms : linkages) {
          StructureAtomLinkage link =
              StructureUtil.getStructureAtomLinkage(atoms[0], true, atoms[1], true);
          unidentifiableAtomLinkages.add(link);
        }
      }
    }

    // attachment
    int nLig = ligands.size();
    for (int i = 0; i < nRes; i++) {
      Group group1 = residues.get(i);
      for (int j = 0; j < nLig; j++) {
        Group group2 = ligands.get(j);
        if (group1.equals(group2)) { // overlap between residues and ligands
          continue;
        }
        List<Atom[]> linkages =
            StructureUtil.findAtomLinkages(group1, group2, false, bondLengthTolerance);
        for (Atom[] atoms : linkages) {
          StructureAtomLinkage link =
              StructureUtil.getStructureAtomLinkage(atoms[0], true, atoms[1], false);
          unidentifiableAtomLinkages.add(link);
        }
      }
    }
  }
  /** 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;
  }