content: /*
   * Project: DD_core
   * @(#)ReactionIndexer.java
   *
   * Copyright (c) 1997- 2014
   * Actelion Pharmaceuticals Ltd.
   * Gewerbestrasse 16
   * CH-4123 Allschwil, Switzerland
   *
   * All Rights Reserved.
   *
   * This software is the proprietary information of Actelion Pharmaceuticals, Ltd.
   * Use is subject to license terms.
   *
   * Author: Christian Rufener
   */
  
  package com.actelion.research.chem.reaction;
  
  import com.actelion.research.chem.ExtendedMolecule;
  import com.actelion.research.chem.Molecule;
  import com.actelion.research.chem.StereoMolecule;
  import com.actelion.research.chem.io.RXNFileParser;
  
  public class ReactionIndexer
  {
      private static boolean debug = false;
  /*
      public static final int BOND_BREAK_1 = 0x0001;
      public static final int BOND_BREAK_2 = 0x0002;
      public static final int BOND_BREAK_3 = 0x0004;
      public static final int BOND_BREAK_M = 0x0008;
  
      public static final int BOND_CREATE_1 = 0x0010;
      public static final int BOND_CREATE_2 = 0x0020;
      public static final int BOND_CREATE_3 = 0x0040;
      public static final int BOND_CHANGE_13 = 0x0080;
  
      public static final int BOND_CHANGE_12 = 0x0100;
      public static final int BOND_CHANGE_21 = 0x0200;
      public static final int BOND_CHANGE_23 = 0x0400;
      public static final int BOND_CHANGE_32 = 0x0800;
      public static final int BOND_CHANGE_31 = 0x1000;
      public static final int BOND_CHANGE_A2 = 0x2000;
      public static final int BOND_CHANGE_A1 = 0x4000;
      public static final int BOND_CHANGE_O = 0x8000;
  
      public static final int ATOM_C_C = 0x00010000;
      public static final int ATOM_C_O = 0x00020000;
      public static final int ATOM_C_N = 0x00040000;
      public static final int ATOM_C_X = 0x00080000;
      public static final int ATOM_C_M = 0x00100000;
  */
  
      private static final byte CR_ONLY = 0;
      // Carbon Create Keys
      private static final byte CR_CC1 = 1;
      private static final byte CR_CC2 = 2;
      private static final byte CR_CC3 = 3;
      private static final byte CR_CCA = 4;
      private static final byte CR_CN1 = 5;
      private static final byte CR_CN2 = 6;
      private static final byte CR_CN3 = 7;
      private static final byte CR_CO1 = 8;
      private static final byte CR_CO2 = 9;
      private static final byte CR_CCl = 10;
      private static final byte CR_CX = 11;
  
      // Nitrogen Create Keys
      private static final byte CR_NN1 = 12;
      private static final byte CR_NN2 = 13;
      private static final byte CR_NO1 = 14;
      private static final byte CR_NO2 = 15;
  
      // Change Carbon Keys
      private static final byte CH_CCSD = 16;
      private static final byte CH_CCDS = 17;
      private static final byte CH_CCST = 18;
      private static final byte CH_CCTS = 19;
      private static final byte CH_CCDT = 20;
      private static final byte CH_CCTD = 21;
      private static final byte CH_CCSA = 22;
      private static final byte CH_CCAS = 23;
      private static final byte CH_CCDA = 24;
      private static final byte CH_CCAD = 25;
      private static final byte CH_CCTA = 26;
      private static final byte CH_CCAT = 27;
  
      private static final byte CH_CNSD = 28;
      private static final byte CH_CNDS = 29;
      private static final byte CH_CNST = 30;
      private static final byte CH_CNTS = 31;
      private static final byte CH_CNDT = 32;
      private static final byte CH_CNTD = 33;
      private static final byte CH_CNSA = 34;
      private static final byte CH_CNAS = 35;
      private static final byte CH_CNDA = 36;
      private static final byte CH_CNAD = 37;
  
      private static final byte CH_COSD = 38;
      private static final byte CH_CODS = 39;
  
  
      private static final byte DEL_ONLY = 40;
      private static final byte DEL_CCS = 41;
      private static final byte DEL_CCD = 42;
      private static final byte DEL_CCT = 43;
      private static final byte DEL_CCA = 44;
      private static final byte DEL_CNS = 45;
      private static final byte DEL_CND = 46;
      private static final byte DEL_CNT = 47;
      private static final byte DEL_COS = 48;
      private static final byte DEL_COT = 49;
      private static final byte DEL_CF = 50;
      private static final byte DEL_CCl = 51;
      private static final byte DEL_CBR = 52;
      private static final byte DEL_CX = 53;
  
      // Nitrogen Create Keys
      private static final byte DEL_NN1 = 54;
      private static final byte DEL_NN2 = 55;
      private static final byte DEL_NO1 = 56;
      private static final byte DEL_NO2 = 57;
  
      private static final byte CH_ONLY = 58;
  
      public static final byte NUMKEYS = 1 + CH_ONLY;
  
      public static final int NITROGEN = 7;
      public static final int OXYGEN = 8;
      public static final int FLUORINE = 9;
      public static final int CHLORINE = 17;
      public static final int BROMINE = 35;
      public static final int IODINE = 53;
      public static final int ASTATINE = 85;
  
      private static final int CARBON = 6;
  
      private static final String[] KEY_STRING = {
          "CR_ONLY",
          "CR_CC1",
          "CR_CC2",
          "CR_CC3",
          "CR_CCA",
          "CR_CN1",
          "CR_CN2",
          "CR_CN3",
          "CR_CO1",
          "CR_CO2",
          "CR_CCl",
          "CR_CX",
          "CR_NN1",
          "CR_NN2",
          "CR_NO1",
          "CR_NO2",
          "CH_CCSD",
          "CH_CCDS",
          "CH_CCST",
          "CH_CCTS",
          "CH_CCDT",
          "CH_CCTD",
          "CH_CCSA",
          "CH_CCAS",
          "CH_CCDA",
          "CH_CCAD",
          "CH_CCTA",
          "CH_CCAT",
          "CH_CNSD",
          "CH_CNDS",
          "CH_CNST",
          "CH_CNTS",
          "CH_CNDT",
          "CH_CNTD",
          "CH_CNSA",
          "CH_CNAS",
          "CH_CNDA",
          "CH_CNAD",
          "CH_COSD",
          "CH_CODS",
          "DEL_ONLY",
          "DEL_CC1",
          "DEL_CC2",
          "DEL_CC3",
          "DEL_CCA",
          "DEL_CN1",
          "DEL_CN2",
          "DEL_CN3",
          "DEL_CO1",
          "DEL_CO2",
          "DEL_CF ",
          "DEL_CCl",
          "DEL_CBR",
          "DEL_CX ",
          "DEL_NN1",
          "DEL_NN2",
          "DEL_NO1",
          "DEL_NO2",
          "CH_ONLY",
      };
  
      private byte[] rxnKeys = null;
  
      public ReactionIndexer(boolean debug)
      {
          this.debug = debug;
          init();
      }
  
      public ReactionIndexer()
      {
          this(false);
      }
  
      private void init()
      {
          rxnKeys = new byte[NUMKEYS];
      }
  
      public String getKeysString(Reaction rxn)
      {
          init();
          generateKeys(rxn);
          return getKeysString();
  
      }
  
      public static String getKeyName(int key)
      {
          return KEY_STRING[key];
      }
      public byte[] getKeys(Reaction rxn)
      {
          init();
          generateKeys(rxn);
          byte[] ret = new byte[rxnKeys.length];
          System.arraycopy(rxnKeys, 0, ret, 0, rxnKeys.length);
          return ret;
      }
  
      public boolean hasKeys()
      {
          for (int k : rxnKeys) {
              if (k != 0) {
                  return true;
              }
          }
          return false;
      }
  
      private void addKey(int index)
      {
          if (index >= 0 && rxnKeys[index] < Byte.MAX_VALUE) {
              rxnKeys[index]++;
          }
      }
  
      private void initKeys()
      {
          init();
      }
  
  
      public String getFoundKeys()
      {
          StringBuilder sb = new StringBuilder();
          for (int i = 0; i < NUMKEYS; i++) {
              if (rxnKeys[i] > 0) {
                  sb.append(String.format("%s (%d)\n",KEY_STRING[i],(int)rxnKeys[i]));
              }
          }
          return sb.toString();
  
      }
      public static byte[] getKeysFromString(String s)
      {
          byte[] ret = new byte[NUMKEYS];
          if (s != null) {
              if (s.length() != NUMKEYS)
                  throw new RuntimeException("Invalid KeyString Length");
              for (int i = 0; i < NUMKEYS; i++) {
                  ret[i] = (byte)(s.charAt(i)-'0');
              }
          }
  
          return ret;
      }
  
  
      public static String getKeysString(byte[] keys)
      {
          StringBuilder sb = new StringBuilder();
          for (int i = 0; i < NUMKEYS; i++) {
              sb.append(String.format("%1d", (int) keys[i]));
          }
          return sb.toString();
      }
  
      private String getKeysString()
      {
          return getKeysString(rxnKeys);
      }
  
      private int addCreateKey(int bondtype, int atomSymbol1, int atomSymbol2)
      {
          int key = CR_ONLY;
          int a1 = atomSymbol1;
          int a2 = atomSymbol2;
          if (atomSymbol2 < atomSymbol1) {
              a1 = atomSymbol2;
              a2 = atomSymbol1;
          }
          switch (a1) {
              case CARBON:
                  key = getCarbonCreateKey(bondtype, a2);
                  break;
              case NITROGEN:
                  key = getNitroCreateKey(bondtype, a2);
                  break;
  
          }
          return key;
      }
  
      private int getCarbonCreateKey(int bondtype, int atomNo)
      {
          int key = CR_ONLY;
          switch (atomNo) {
              case CARBON:
                  key = getCreateCarbonCarbonKey(bondtype);
                  break;
  
              case NITROGEN:
                  key = getCreateCarbonNitroKey(bondtype);
                  break;
  
              case OXYGEN:
                  key = getCreateCarbonOxygenKey(bondtype);
                  break;
  
              case CHLORINE:
                  key = CR_CCl;
                  break;
  
              case FLUORINE:
              case BROMINE:
              case IODINE:
              case ASTATINE:
                  key = CR_CX;
                  break;
  
          }
          return key;
      }
  
      private int getNitroCreateKey(int bondtype, int atomNo)
      {
          int key = CR_ONLY;
          switch (atomNo) {
              case NITROGEN:
                  if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                      key = CR_NN1;
                  } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                      key = CR_NN2;
                  }
                  break;
  
              case OXYGEN:
                  if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                      key = CR_NO1;
                  } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                      key = CR_NO2;
                  }
                  break;
          }
          return key;
      }
  
      private int getCreateCarbonCarbonKey(int bondtype)
      {
          if (bondtype == Molecule.cBondTypeDelocalized) {
              return CR_CCA;
          } else if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              return CR_CC1;
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              return CR_CC2;
          } else if ((bondtype & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              return CR_CC3;
          }
          return CR_ONLY;
      }
  
      private int getCreateCarbonNitroKey(int bondtype)
      {
  
          if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              return CR_CN1;
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              return CR_CN2;
          } else if ((bondtype & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              return CR_CN3;
          }
          return CR_ONLY;
      }
  
      private int getCreateCarbonOxygenKey(int bondtype)
      {
          if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              return CR_CO1;
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              return CR_CO2;
          }
          return CR_ONLY;
      }
  
      ///////// Change////////
      private void addChangeKey(int atomNo1, int atomNo2, int bt1, int bt2)
      {
          addKey(CH_ONLY);
          int a1 = atomNo1;
          int a2 = atomNo2;
          if (atomNo2 < atomNo1) {
              a1 = atomNo2;
              a2 = atomNo1;
          }
          switch (a1) {
              case CARBON:
                  addCarbonChangeKey(a2, bt1, bt2);
                  break;
          }
          //return key;
      }
  
      private void addCarbonChangeKey(int atomNo, int bt1, int bt2)
      {
          int key = CH_ONLY;
          switch (atomNo) {
              case CARBON:
                  addChangeCarbonCarbonKey(bt1, bt2);
                  break;
  
              case NITROGEN:
                  addChangeCarbonNitroKey(bt1, bt2);
                  break;
  
              case OXYGEN:
                  addChangeCarbonOxygenKey(bt1, bt2);
                  break;
  
          }
  //        return key;
      }
  
  
      private void addChangeCarbonCarbonKey(int bt1, int bt2)
      {
  //        int key = CH_ONLY;
          if (bt1 == Molecule.cBondTypeDelocalized) {
              if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CCAS);
              } else if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_CCAD);
              } else if ((bt2 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
                  addKey(CH_CCAT);
              }
          } else if ((bt1 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              if (bt2 == Molecule.cBondTypeDelocalized) {
                  addKey(CH_CCSA);
              } else if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_CCSD);
              } else if ((bt2 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
                  addKey(CH_CCST);
              }
          } else if ((bt1 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              if (bt2 == Molecule.cBondTypeDelocalized) {
                  addKey(CH_CCDA);
              } else if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CCDS);
              } else if ((bt2 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
                  addKey(CH_CCDT);
              }
          } else if ((bt1 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              if (bt2 == Molecule.cBondTypeDelocalized) {
                  addKey(CH_CCTA);
              } else if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CCTS);
              } else if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_CCTD);
              }
          }
  
  //        return key;
      }
  
      private void addChangeCarbonNitroKey(int bt1, int bt2)
      {
  //        int addKey(CH_ONLY;
          if (bt1 == Molecule.cBondTypeDelocalized) {
              if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CNAS);
              } else if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_CNAD);
              }
          } else if ((bt1 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              if (bt2 == Molecule.cBondTypeDelocalized) {
                  addKey(CH_CNSA);
              } else if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_CNSD);
              } else if ((bt2 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
                  addKey(CH_CNST);
              }
          } else if ((bt1 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              if (bt2 == Molecule.cBondTypeDelocalized) {
                  addKey(CH_CNDA);
              } else if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CNDS);
              } else if ((bt2 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
                  addKey(CH_CNDT);
              }
          } else if ((bt1 & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CNTS);
              } else if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_CNTD);
              }
          }
  
  //        return key;
      }
  
      private void addChangeCarbonOxygenKey(int bt1, int bt2)
      {
  //        int addKey(CH_ONLY;
          if ((bt1 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              if ((bt2 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                  addKey(CH_COSD);
              }
          } else if ((bt1 & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              if ((bt2 & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                  addKey(CH_CODS);
              }
          }
          //return key;
      }
  
  
      /*
          private int getChangeKey(int bt1, int bt2)
          {
              int addKey(-1;
              if (bt1 == Molecule.cBondTypeDelocalized) {
                  if ((bt2 & Molecule.cBondTypeSingle) ==Molecule.cBondTypeSingle) {
                      addKey(CH_AS;
                  }else if ((bt2 & Molecule.cBondTypeDouble) ==Molecule.cBondTypeDouble) {
                      addKey(CH_AD;
                  }else if ((bt2 & Molecule.cBondTypeTriple) ==Molecule.cBondTypeTriple) {
                      addKey(CH_AT;
                  }
              } else if ((bt1 & Molecule.cBondTypeSingle) ==Molecule.cBondTypeSingle) {
                  if (bt2 == Molecule.cBondTypeDelocalized) {
                      addKey(CH_SA;
                  } else if ((bt2 & Molecule.cBondTypeDouble) ==Molecule.cBondTypeDouble) {
                      addKey(CH_SD;
                  }else if ((bt2 & Molecule.cBondTypeTriple) ==Molecule.cBondTypeTriple) {
                      addKey(CH_ST;
                  }
              } else if ((bt1 & Molecule.cBondTypeDouble) ==Molecule.cBondTypeDouble) {
                  if (bt2 == Molecule.cBondTypeDelocalized) {
                      addKey(CH_DA;
                  } else if ((bt2 & Molecule.cBondTypeSingle) ==Molecule.cBondTypeSingle) {
                      addKey(CH_DS;
                  }else if ((bt2 & Molecule.cBondTypeTriple) ==Molecule.cBondTypeTriple) {
                      addKey(CH_DT;
                  }
              } else if ((bt1 & Molecule.cBondTypeTriple) ==Molecule.cBondTypeTriple) {
                  if (bt2 == Molecule.cBondTypeDelocalized) {
                      addKey(CH_TA;
                  } else if ((bt2 & Molecule.cBondTypeSingle) ==Molecule.cBondTypeSingle) {
                      addKey(CH_TS;
                  }else if ((bt2 & Molecule.cBondTypeDouble) ==Molecule.cBondTypeDouble) {
                      addKey(CH_TD;
                  }
              }
  
              return key;
          }
      */
      private void addDeleteKey(int bondtype, int atomNo1, int atomNo2)
      {
          addKey(DEL_ONLY);
          int a1 = atomNo1;
          int a2 = atomNo2;
          if (atomNo2 < atomNo1) {
              a1 = atomNo2;
              a2 = atomNo1;
          }
          switch (a1) {
              case CARBON:
                  addCarbonDeleteKey(bondtype, a2);
                  break;
              case NITROGEN:
                  addNitroDeleteKey(bondtype, a2);
                  break;
  
          }
      }
  
      private void addCarbonDeleteKey(int bondtype, int atomNo)
      {
  //          int addKey(DEL_ONLY;
          switch (atomNo) {
              case CARBON:
                  addDeleteCarbonCarbonKey(bondtype);
                  break;
  
              case NITROGEN:
                  addDeleteCarbonNitroKey(bondtype);
                  break;
  
              case OXYGEN:
                  addDeleteCarbonOxygenKey(bondtype);
                  break;
              case FLUORINE:
              case CHLORINE:
              case 35:
              case IODINE:
                  addHalogenDeleteKey(atomNo);
                  break;
  
          }
  //        addKey();
      }
  
      private void addDeleteCarbonCarbonKey(int bondtype)
      {
          if (bondtype == Molecule.cBondTypeDelocalized) {
              addKey(DEL_CCA);
          } else if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              addKey(DEL_CCS);
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              addKey(DEL_CCD);
          } else if ((bondtype & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              addKey(DEL_CCT);
          }
          //addKey(DEL_ONLY;
      }
  
      private void addDeleteCarbonNitroKey(int bondtype)
      {
  
          if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              addKey(DEL_CNS);
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              addKey(DEL_CND);
          } else if ((bondtype & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              addKey(DEL_CNT);
          }
          //return DEL_ONLY;
      }
  
      private void addDeleteCarbonOxygenKey(int bondtype)
      {
          if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              addKey(DEL_COS);
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              addKey(DEL_COT);
          }
          //return DEL_ONLY;
      }
  
      private void addNitroDeleteKey(int bondtype, int atomNo)
      {
  //        int addKey(DEL_ONLY;
          switch (atomNo) {
              case NITROGEN:
                  if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                      addKey(DEL_NN1);
                  } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                      addKey(DEL_NN2);
                  }
                  break;
  
              case 8:
                  if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
                      addKey(DEL_NO1);
                  } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
                      addKey(DEL_NO2);
                  }
                  break;
          }
  //        return key;
      }
  
      private void addHalogenDeleteKey(int atomNo)
      {
          addKey(DEL_CX);
          switch (atomNo) {
              case FLUORINE:
                  addKey(DEL_CF);
                  break;
              case CHLORINE:
                  addKey(DEL_CCl);
                  break;
              case BROMINE:
                  addKey(DEL_CBR);
                  break;
              case IODINE:
                  break;
          }
          //return key;
      }
  
  
  /*
      C1             C5                                  C1        C5
        \           /                                      \      /
         C2-Cl    N4                 -->                    C2 - N4
        /           \                                      /      \
       C3            C6                                   C3       C6
  
      C1                                                 C1
        \                                                  \
         C2 = O3                     -->                   C2 - 03
        /                                                  /
       C3                                                 C3
  
      C1         C5                                       C1            C5
        \       /                                           \          /
         C2 - N4                     -->                    C2       N4
        /      \                                           /           \
       C3       C6                                        C3           C6
  
  
      C1         C         C5                            C1         C5
        \       /        /                                 \       /
         C2 - N        N4            -->                    C2 - N4
        /      \         \                                 /       \
       C3       C         C6                             C3         C6
  
  
  */
  //  C1 -> Map No = 1, pAtomNo = x, cConntectedAtoms = 1, pNumConnectedAtoms=1
  //       cBondAtom = (C2), bondType = 1, cOtherMapNo = 2, pBondType=1 = > NO CHANGE
  //  C2 -> Map No = 2, pAtomNo = x, cConntextedAtoms = 3, pNumConnectedAtoms = 3
  //        C1 == OK
  //        C3 == OK
  //       cBondAtom (Cl),cBondType=1,cOtherMapNo=0
  //
  
      /*
                              // For all atoms connected to Component Atoms (cAtomNo)
                              for (int cbi = 0; cbi < cNumConnectedAtoms; cbi++) {
                                  // get the other atom at this bond
                                  int cBondAtom = source.getConnAtom(cAtomNo, cbi);
                                  // Get the bond index from these two atoms
                                  int sourceBondIndex = source.getConnBond(cAtomNo, cbi);
                                  if (cVisitedBonds[sourceBondIndex])
                                      continue;
                                  // Find the mapping number of the bond's other end
                                  int cOtherMapNo = source.getAtomMapNo(cBondAtom);
                                  // get the bond type of this atom
                                  int cBondType = getBondType(source, sourceBondIndex);
                                  ////sb.append(String.format("Source Bond From %d(%d) - %d(%d) \n",cAtomNo,cMapNo,cBondAtom,cOtherMapNo));
  
                                  cVisitedBonds[sourceBondIndex] = true;
                                  // the other end is mapped
                                  if (cOtherMapNo != 0) {
                                      // find the cont type of the two mapped atoms on the preoduct
                                      int pBondType = getMappedBondType(target, cMapNo, cOtherMapNo);
                                      //sb.append(String.format("Proiduct Bond Type (%d) - (%d) = %d \n",cMapNo,cOtherMapNo,pBondType));
                                      // If there's no bond, then the bond has been brokwn
                                      if (pBondType == -1) {
                                          if (!reverse) {
                                              System.out.println(String.format("###BOND_BREAK(1) at %d-%d \n", cOtherMapNo, cMapNo));
                                              int key = addDeleteKey(cBondType, source.getAtomicNo(cAtomNo), source.getAtomicNo(cBondAtom));
                                              if (debug)
                                                  System.out.println("Delete Key is " + key);
                                              addKey(key);
                                              addKey(DEL_ONLY);
                                          } else {
                                              System.out.println(String.format("###BOND_CREATE(1) at %d-%d \n", cOtherMapNo, cMapNo));
                                              int key = addCreateKey(cBondType, source.getAtomicNo(cAtomNo), source.getAtomicNo(cBondAtom));
                                              addKey(key);
                                              addKey(CR_ONLY);
                                          }
                                          if (debug)
                                              sb.append(String.format("Bond %d %s-%s\n", sourceBondIndex, source.getAtomLabel(cAtomNo), source.getAtomLabel(cBondAtom)));
                                          // BOND_BREAK;
                                          // If the bond type is the same, nothing happend
                                      } else if (cBondType == pBondType) {
                                          ;
                                          // the bond type is different, so it's a change
                                      } else {
                                          if (!reverse) {
                                              System.out.println(String.format("###BOND_CHANGE(1) Type=%d Map %d-%d \n", pBondType, cOtherMapNo, cMapNo));
                                              int key = getChangeKey(source.getAtomicNo(cAtomNo), source.getAtomicNo(cBondAtom), cBondType, pBondType);
                                              addKey(key);
                                              addKey(CH_ONLY);
                                          }
                                          // BOND_CHANGE
                                      }
  
                                  } else {
                                      System.out.println(String.format("not found other map no %d %d", listIndex, cMapNo));
                                      //if (!cVisitedBonds[sourceBondIndex]) {
                                      //    System.out.println(String.format("## UNDEFINED",listIndex,cMapNo));
                                      //}
                                      // Does this bond break
                                  }
                              }
                              if (!reverse) {
                                  if (cNumConnectedAtoms < pNumConnectedAtoms) {
                                      System.out.println(String.format("searching backward? %d/%d (%d)", cNumConnectedAtoms, pNumConnectedAtoms, cMapNo));
                                      int bondIndex = findDeletedBond(target, pAtomNo, source, cAtomNo);
                                      if (bondIndex != -1 && !cVisitedBonds[bondIndex]) {
                                          int ba = target.getConnAtom(pAtomNo, bondIndex);
                                          int type = target.getAtomicNo(ba);
                                          int bt = getBondType(target, bondIndex);
                                          System.out.println(String.format("### BOND_CREATE(2) at Target Atom %d(%d)[%d] from Source Atom %d(%d)", pAtomNo, cMapNo, type, cAtomNo, cMapNo));
                                          // BOND_CREATE
                                          int key = addCreateKey(bt, target.getAtomicNo(pAtomNo), target.getAtomicNo(ba));
                                          addKey(key);
                                          addKey(CR_ONLY);
                                      }
                                  } else if (cNumConnectedAtoms > pNumConnectedAtoms) {
                                      System.out.println(String.format("searching forward? %d/%d (%d)", cNumConnectedAtoms, pNumConnectedAtoms, cMapNo));
                                      int bondIndex = findDeletedBond(source, cAtomNo, target, pAtomNo);
                                      if (bondIndex != -1 && !cVisitedBonds[bondIndex]) {
                                          int ba = source.getConnAtom(cAtomNo, bondIndex);
                                          int type = source.getAtomicNo(ba);
                                          int bt = getBondType(target, bondIndex);
                                          System.out.println(String.format("### BOND_DELETE(2) at Target Atom %d(%d)[%d] from Source Atom %d(%d)", pAtomNo, cMapNo, type, cAtomNo, cMapNo));
                                          // BOND_CREATE
                                          int key = addDeleteKey(bt, source.getAtomicNo(cAtomNo), source.getAtomicNo(ba));
                                          addKey(key);
                                          addKey(DEL_ONLY);
                                      }
                                  }
                              }
                          } else {
                          }
                      }
                  }
              } else {
  
              }
              sb.append(getKeysString());
              return sb.toString();
          }
      */
      private int findDeletedBond(ExtendedMolecule source, int sourceAtom, ExtendedMolecule target, int targetAtom)
      {
          int sourceNumConnectedAtoms = source.getConnAtoms(sourceAtom);
          int originAtomType = source.getAtomicNo(sourceAtom);
          int targetNumConnectedAtoms = target.getConnAtoms(targetAtom);
          boolean visitedSourceBonds[] = new boolean[sourceNumConnectedAtoms];
          if (sourceNumConnectedAtoms > targetNumConnectedAtoms) {
              if (debug) {
                  System.out.println(String.format("findDeletedBond() walk source atom %d", sourceAtom));
              }
  // Walk all bonds at this atom
              boolean visitedTargetBonds[] = new boolean[targetNumConnectedAtoms];
              for (int i = 0; i < sourceNumConnectedAtoms; i++) {
                  if (!visitedSourceBonds[i]) {
                      // This is the atom of the bond
                      int sourceBondAtom = source.getConnAtom(sourceAtom, i);
  // And this is the bond
                      int sourceBond = source.getConnBond(sourceAtom, i);
  // The bond type
                      int sourceBondType = getBondType(source, sourceBond);
  // The atom type
                      int sourceAtomType = source.getAtomicNo(sourceBondAtom);
                      if (debug) {
                          System.out.println(String.format("findDeletedBond() walk source bond atom %d bond %d type %d atomtype %d", sourceBondAtom, i, sourceBondType, sourceAtomType));
                      }
                      for (int j = 0; j < targetNumConnectedAtoms; j++) {
                          if (!visitedTargetBonds[j]) {
                              int bondAtom = target.getConnAtom(targetAtom, j);
                              int bond = target.getConnBond(targetAtom, j);
                              int targetBondType = getBondType(target, bond);
                              int targetAtomType = target.getAtomicNo(bondAtom);
                              if (debug) {
                                  System.out.println(String.format("findDeletedBond() walk checking bond %d->%d (%d/%d) %d/%d", sourceAtomType, targetAtomType, i, j, sourceBondType, targetBondType));
                              }
                              if (sourceAtomType == targetAtomType && sourceBondType == targetBondType) {
                                  visitedSourceBonds[i] = true;
                                  visitedTargetBonds[j] = true;
                                  System.out.println("Found Bond");
                                  break;
                              }
                          }
                      }
                      if (!visitedSourceBonds[i]) {
                          if (debug) {
                              System.out.println(String.format("findDeletedBond() walk source bond not found atom %d bond %d type %d atomtype %d->%d",
  
                                  sourceBondAtom, i, sourceBondType, originAtomType, sourceAtomType));
                          }
                      }
                  }
              }
              for (int i = 0; i < sourceNumConnectedAtoms; i++) {
                  if (!visitedSourceBonds[i]) {
                      if (debug) {
                          System.out.println(String.format("Did not find bond: %d(%d)", sourceAtom, i));
                      }
  // this bond has not been seen, so it's breacking
                      return i;
                  }
              }
          }
          return -1;
      }
  
      private boolean findBond(ExtendedMolecule mol, int atomIndex, int atomType, int bondType)
      {
          int pNumConnectedAtoms = mol.getConnAtoms(atomIndex);
          return false;
      }
  
      /*
          ExtendedMolecule findMappedAtomMol(int mapno)
          {
              ExtendedMolecule ret = null;
              int prod = rxn.getProducts();
              for (int i = 0; i < prod; i++) {
                  ExtendedMolecule m = rxn.getMolecule(i);
                  for (int a = 0; a < m.getAllAtoms(); a++) {
                      if (m.getAtomMapNo(a) == mapno) {
                          ret = m;
                          break;
                      }
                  }
              }
              return ret;
          }
      */
      int getMappedAtom(ExtendedMolecule m, int map1)
      {
          int a1 = -1;
          for (int a = 0; a < m.getAllAtoms(); a++) {
              if (m.getAtomMapNo(a) == map1) {
                  a1 = a;
                  break;
              }
          }
          return a1;
      }
  
      int getMappedBondType(ExtendedMolecule m, int map1, int map2)
      {
          int ret = -1; // Bond Type
          int bond = getMappedBond(m, map1, map2);
          if (bond != -1) {
              return getBondType(m, bond);
          }
          return ret;
      }
  
      private int getBondType(ExtendedMolecule m, int bond)
      {
          int ret = m.getBondType(bond);
          if (m.isAromaticBond(bond) || m.isDelocalizedBond(bond)) {
              ret = Molecule.cBondTypeDelocalized;
          }
          return getSimpleBondType(ret);
      }
  
      private int getSimpleBondType(int bondtype)
      {
          if (bondtype == Molecule.cBondTypeDelocalized) {
              return Molecule.cBondTypeDelocalized;
          } else if ((bondtype & Molecule.cBondTypeSingle) == Molecule.cBondTypeSingle) {
              return Molecule.cBondTypeSingle;
          } else if ((bondtype & Molecule.cBondTypeDouble) == Molecule.cBondTypeDouble) {
              return Molecule.cBondTypeDouble;
          } else if ((bondtype & Molecule.cBondTypeTriple) == Molecule.cBondTypeTriple) {
              return bondtype & Molecule.cBondTypeTriple;
          }
          return bondtype;
      }
  
      int getMappedBond(ExtendedMolecule m, int map1, int map2)
      {
          int ret = -1; // Bond
          int a1 = getMappedAtom(m, map1);
          if (a1 != -1) {
              int bcnt = m.getConnAtoms(a1);
              for (int b = 0; b < bcnt; b++) {
                  int a2 = m.getConnAtom(a1, b);
  //                int a2 = m.getBondAtom(a1,b);
                  int mt = m.getAtomMapNo(a2);
                  if (debug) {
                      System.out.println(String.format("Checking Product bond %d-%d : Product Atom %d has map no %d", a1, a2, a2, mt));
                  }
                  if (mt == map2) {
                      ret = m.getConnBond(a1, b);
                      break;
                  }
              }
          }
          return ret;
      }
  
  //    public int getKey(ExtendedMolecule s, int a1, int a2, int bond)
  //    {
  //        return 0;
  //    }
  
  
      private int getSameBond(ExtendedMolecule source, int cBondAtom, int cBondIndex, ExtendedMolecule target, int targetAtom)
      {
          int cAtomSymbol = source.getAtomicNo(cBondAtom);
          int map = source.getAtomMapNo(cBondAtom);
  //        int cBondAtom = source.getConnAtom(sourceAtom,cbi);
  //		int cBondIndex = source.getConnBond(sourceAtom,cbi);
          int cBondType = getBondType(source, cBondIndex);
          int targetBondCount = target.getConnAtoms(targetAtom);
          for (int tbi = 0; tbi < targetBondCount; tbi++) {
              int tBondAtom = target.getConnAtom(targetAtom, tbi);
              int tBondIndex = target.getConnBond(targetAtom, tbi);
              int tBondType = getBondType(target, tBondIndex);
              int tAtomSymbol = target.getAtomicNo(tBondAtom);
              int tmap = target.getAtomMapNo(tBondAtom);
              if (cAtomSymbol == tAtomSymbol && cBondType == tBondType && map == tmap) {
                  return tBondIndex;
              }
          }
          return -1;
      }
  
      private int getBond(ExtendedMolecule mol, int atom1, int atom2)
      {
          int ret = -1;
          int bondCount = mol.getConnAtoms(atom1);
          for (int tbi = 0; tbi < bondCount; tbi++) {
              int tBondAtom = mol.getConnAtom(atom1, tbi);
              if (tBondAtom == atom2) {
                  ret = mol.getConnBond(atom1, tbi);
                  break;
              }
          }
          return ret;
      }
  
      private int findMapAt(ExtendedMolecule mol, int atom, int map)
      {
          int ret = -1;
          int bondCount = mol.getConnAtoms(atom);
          int m = mol.getAtomMapNo(atom);
          if (m == map) {
              ret = atom;
          }
          if (ret == -1) {
              for (int tbi = 0; tbi < bondCount; tbi++) {
                  int tBondAtom = mol.getConnAtom(atom, tbi);
                  m = mol.getAtomMapNo(tBondAtom);
                  if (m == map) {
                      ret = tBondAtom;
                      break;
                  }
              }
          }
          return ret;
      }
  
      private void generateKeys(Reaction rxn)
      {
  
          // (1)
          // FIND ATOM WITH MAP NO IN TARGET
          // FOR ALL ATOMS ON TARGET
          // IF MAP(ATOM)== MAP
          // TATOM = ATOM
          // END FOR
  
          //(2)
          // for all bonds at targetatom
          // if map(atom)== map
          // return atom
          // end for
  
          StringBuilder sb = new StringBuilder();
          ExtendedMolecule m = new ExtendedMolecule();
          initKeys();
          if (debug) {
              System.out.println(" " + m.toString());
          }
          int comp = rxn.getReactants();
          int prod = rxn.getProducts();
          int flags = Molecule.cHelperBitNeighbours | Molecule.cHelperBitRings;
  
          if (comp != 0 && prod != 0) {
              if (debug) {
                  System.out.println("RXNSearcher.search()");
              }
              ExtendedMolecule component = new StereoMolecule(rxn.getMolecule(0));
              for (int c = 1; c < comp; c++) {
                  ExtendedMolecule mol = rxn.getMolecule(c);
                  component.addMolecule(mol);
              }
              component.ensureHelperArrays(flags);
              //sb.append(String.format("Component has %d atoms\n",component.getAllAtoms()));
  
              ExtendedMolecule product = new StereoMolecule(rxn.getProduct(0));
              for (int c = 1; c < prod; c++) {
                  product.addMolecule(rxn.getProduct(c));
              }
              product.ensureHelperArrays(flags);
  
              ExtendedMolecule source = component;
              ExtendedMolecule target = product;
  
              // All Mapped atom indizes
              int mappedSourceAtoms[] = new int[source.getAllAtoms()];
              int mappedTargetAtoms[] = new int[target.getAllAtoms()];
              boolean cVisitedBonds[] = new boolean[source.getAllBonds()];
  
              //sb.append(String.format("source has %d atoms\n",source.getAllAtoms()));
              int noMappedSourceAtoms = 0;
              for (int a = 0; a < source.getAllAtoms(); a++) {
                  int map = source.getAtomMapNo(a);
                  if (map > 0) {
                      mappedSourceAtoms[noMappedSourceAtoms++] = a;
                  }
  
              }
  
  
              int noMappedTargetAtoms = 0;
              for (int a = 0; a < target.getAllAtoms(); a++) {
                  int map = target.getAtomMapNo(a);
                  if (map > 0) {
                      mappedTargetAtoms[noMappedTargetAtoms++] = a;
                  }
  
              }
  
              // setup SOURCEBOND and TARGETBOND ARRAY based on MAPPED ATOMS
              boolean sourceBonds[] = new boolean[source.getAllBonds()];
              boolean targetBonds[] = new boolean[target.getAllBonds()];
  
  
  //            for (int k = 0; k < idx; k++) {
  ////                System.out.printf("Map [%d] -> [%d]\n",k,source.getAtomMapNo(k));
  //                int s = source.getConnAtoms(k);
  //                for (int b = 0; b < s; b++) {
  //                    int a2 = source.getConnAtom(k, b);
  //                    System.out.printf("Map #[%d] -> M[%d] = #[%d] -> M[%d]\n",
  //                        k,source.getAtomMapNo(k),a2,
  //                        source.getAtomMapNo(a2));
  //                }
  //            }
  //            if (true)
  //                return "";
  
              // for all mapped atoms
              for (int k = 0; k < noMappedSourceAtoms; k++) {
                  // sourceAtom
                  int sourceAtom = mappedSourceAtoms[k];
                  int sourceMapNo = source.getAtomMapNo(sourceAtom);
                  // targetAtom = find atom with same map no as sourceAtom (1)
                  int targetAtom = getMappedAtom(target, sourceMapNo);
                  debug("Working on atom %d (%d) target atom is %d\n", sourceMapNo, sourceAtom, targetAtom);
  
                  // if not found
                  // break;
                  if (targetAtom == -1) {
                      break;
                  }
  
  //                debug("Map first (%d) (%d-%d)\n",sourceMapNo, sourceAtom,targetAtom);
  
                  // boundCounts at source and target atom
                  int sourceBondCount = source.getConnAtoms(sourceAtom);
                  int targetBondCount = target.getConnAtoms(targetAtom);
                  // for all bonds at source Atom
                  for (int cbi = 0; cbi < sourceBondCount; cbi++) {
                      int sourceBondConnectedAtom = source.getConnAtom(sourceAtom, cbi);
                      int sourceBondIndex = source.getConnBond(sourceAtom, cbi);
                      int sourceBondType = getBondType(source, sourceBondIndex);
                      // if sourceBond is not visited
                      if (!sourceBonds[sourceBondIndex]) {
                          // amap = map(bondAtom)
                          int sourceBondConnectedAtomMap = source.getAtomMapNo(sourceBondConnectedAtom);
                          debug("\tChecking Source Bond on atom %d (%d)\n",
                              sourceBondConnectedAtomMap, sourceBondConnectedAtom);
  
                          // if bondAtom is mapped
                          if (sourceBondConnectedAtomMap != 0) {
                              // find atom with amap as at targetAtom bonds
                              int targetBondAtom = findMapAt(target, targetAtom, sourceBondConnectedAtomMap);
  //                            debug("Mapping source bond %d (%d-%d) (%d-%d)\n",
  //                                cbi,
  //                                sourceMapNo,
  //                                sourceBondConnectedAtomMap,
  //                                sourceAtom,
  //                                sourceBondConnectedAtom
  //                            );
                              // if same map is found
                              if (targetBondAtom != -1) {
                                  int targetBondIndex = getBond(target, targetAtom, targetBondAtom);
                                  // TARGETBOND is visited
                                  targetBonds[targetBondIndex] = true;
                                  // if bondtype differs
                                  int targetBondType = getBondType(target, targetBondIndex);
                                  // The bond types don't match
                                  if (targetBondType != sourceBondType) {
                                      // its a change
                                      // sourceBond[i] is visited
                                      if (debug) {
                                          System.out.println(String.format("Map: %d-%d bond CHANGE %d/%d", sourceMapNo, sourceBondConnectedAtomMap, sourceBondType, targetBondType));
                                      }
                                      sourceBonds[sourceBondIndex] = true;
                                      addChangeKey(source.getAtomicNo(sourceAtom), source.getAtomicNo(sourceBondConnectedAtom), sourceBondType, targetBondType);
                                      //addKey(key);
                                      //addKey(CH_ONLY);
                                      // else
                                  } else {
                                      // sourceBond[i] is visited
                                      sourceBonds[sourceBondIndex] = true;
                                      // no change
                                      // end if
                                  }
                                  // else (map not found)
                              } else {
                                  // its a break;
                                  // sourceBond[i] is visited
                                  if (debug) {
                                      System.out.println(String.format("Map: %d-%d bond BREAK %d", sourceMapNo, sourceBondConnectedAtomMap, sourceBondType));
                                  }
                                  sourceBonds[sourceBondIndex] = true;
                                  addDeleteKey(sourceBondType, source.getAtomicNo(sourceAtom), source.getAtomicNo(sourceBondConnectedAtom));
  //                                addKey(key);
  //                                addKey(DEL_ONLY);
                                  // ??? don't mark bond as visited we want to find the CREATE
                                  // end if
                              }
                          } else {
                              ;
                              // Not a mapped atom, we will deal with this in the next section
                              // System.out.println(String.format("Map: %d Not mapped atom", sourceMapNo));
                              // not mapped atom
                              // ignore
                          }
                      } // end if
                  } // end for
  
                  // Deal with the non-mapped atoms...
                  // for all bonds at source Atom
                  for (int cbi = 0; cbi < sourceBondCount; cbi++) {
                      int cBondAtom = source.getConnAtom(sourceAtom, cbi);
                      int cBondIndex = source.getConnBond(sourceAtom, cbi);
                      int cBondType = getBondType(source, cBondIndex);
  //                    int cAtomSymbol = source.getAtomicNo(cBondAtom);
                      // if sourceBond is not visited
                      // System.out.println(String.format("Map %d running at atom %d map %d",sourceMapNo,cBondAtom,source.getAtomMapNo(cBondAtom)));
                      if (!sourceBonds[cBondIndex]) {
                          int cbMap = source.getAtomMapNo(cBondAtom);
                          // if bondAtom is not  mapped
                          if (cbMap == 0) {
                              int tBondIndex = getSameBond(source, cBondAtom, cBondIndex, target, targetAtom);
                              if (tBondIndex != -1) {
                                  // sourcebond is visited
                                  // TARGETBOND IS VISITED
                                  sourceBonds[cBondIndex] = true;
                                  targetBonds[tBondIndex] = true;
                                  // System.out.println(String.format("No Map/No change -> found bond index %d ", sourceMapNo));
                                  // no change
                                  // else
                              } else {
                                  // BREAK_BOND
                                  // sourcebond is visited
  //                                if (debug)
  //                                    System.out.println(String.format("Map: %d (%d-%d) Atom Type: %d  bond at atom " +
  //                                        "BREAK",
  //                                        sourceMapNo,
  //                                        sourceAtom,cBondAtom,
  //                                        source.getAtomicNo(cBondAtom)));
                                  sourceBonds[cBondIndex] = true;
                                  addDeleteKey(cBondType, source.getAtomicNo(sourceAtom), source.getAtomicNo(cBondAtom));
                                  if (debug) {
                                      System.out.println(String.format("Map: %d (%d-%d) Atom Type: %d  bond at atom " +
                                              "DELETE",
                                          sourceMapNo,
                                          sourceAtom, cBondAtom,
                                          source.getAtomicNo(cBondAtom)));
                                  }
  
  //                                addKey(key);
                                  //addKey(DEL_ONLY);
                                  // end if
                              }
                          } else {
                              // This should not happen, since we dealt with this already before
                              if (debug) {
                                  System.out.println(String.format("Map: %d Found SHOULD NOT", cbMap));
                              }
                          } // end if
                      } else {
                          // The bond has already been
                          // else
                          //???
                      }
                      // end if
                      // end for
                  }
                  // for all target bounds which have not yet been visited
                  // they might be created, however, we'd need to check whether there's a mapping
  //                if (sourceBondCount < targetBondCount) {
                  // for all bonds at target atom
                  for (int tbi = 0; tbi < targetBondCount; tbi++) {
                      int tBondIndex = target.getConnBond(targetAtom, tbi);
                      int tBondType = getBondType(target, tBondIndex);
                      int tAtom = target.getConnAtom(targetAtom, tbi);
                      int tmap = target.getAtomMapNo(tAtom);
                      int an = target.getAtomicNo(tAtom);
                      // if targetbond is not visited
                      if (!targetBonds[tBondIndex]) {
                          //those are CREATE_BONDS
                          if (debug) {
                              System.out.println(String.format("Map: %d-%d (%d) bond at atom CREATE_2", sourceMapNo, tmap, an));
                          }
                          targetBonds[tBondIndex] = true;
                          int key = addCreateKey(tBondType, target.getAtomicNo(targetAtom), target.getAtomicNo(tAtom));
                          addKey(key);
                          addKey(CR_ONLY);
  
                      } //endif
                  } // end for
  //                } //endif
              } //end for all mapped atoms
          }
      }
  
      public void debug(String format, Object... args)
      {
          if (debug)
              System.out.printf(format, args);
  
      }
  
      public static void main(String args[])
      {
          ReactionIndexer rs = new ReactionIndexer();
          try {
  
              for (int i = 1; i <= 11; i++) {
                  RXNFileParser p = new RXNFileParser();
                  Reaction r = new Reaction();
                  p.parse(r, new java.io.File("RXN" + i + ".rxn"));
                  if (debug) {
                      System.out.println("RXN: " + r.getMolecules());
                  }
                  rs.getKeys(r);
              }
          } catch (Throwable e) {
              System.err.println("Error parsing RDFILE " + e);
              e.printStackTrace();
          }
      }
  
  
  }
  
  
  /*
  class RDFileReader
  {
      BufferedReader rd = null;
      StringBuilder rxn = null;
      StringBuilder data = null;
  
      public RDFileReader(InputStream is) throws IOException
      {
          rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
          String line;
          line = rd.readLine();
          if (line == null || !line.startsWith("$RDFILE "))
              throw new IOException("Invalid File Header");
          line = rd.readLine();
          if (line == null)
              throw new IOException("Invalid File Header");
          line = rd.readLine();
          if (line == null || !line.startsWith("$RFMT"))
              throw new IOException("File is empty");
      }
  
      boolean hasNext()
      {
          boolean ret = false;
          StringBuilder r = new StringBuilder();
          StringBuilder d = new StringBuilder();
          // The default buffer is the reaction buffer
          StringBuilder sb = r;
          String line;
          try {
              boolean eof = true;
              while ((line = rd.readLine()) != null) {
                  eof = false;
                  if (line.startsWith("$RFMT")) {
  //                        System.out.println("End of This RXN..." +line);
                      break;
                  }
                  // Switch the buffer to the data buffer
                  if (line.startsWith("$DTYPE")) {
  //                        System.out.println("Switching To Data Buffer " + line);
                      sb = data;
                  }
                  sb.append(line);
                  sb.append("\n");
              }
              if (!eof) {
                  data = d;
                  rxn = r;
                  ret = true;
              }
          } catch (IOException e) {
              ret = false;
          }
          return ret;
      }
  
      public Reaction getReaction()
      {
          Reaction r = new Reaction();
          RXNFileParser p = new RXNFileParser();
          try {
              r = p.getReaction(rxn.toString());
          } catch (Exception e) {
              System.err.println("Error parsing reaction...");
              r = null;
          }
          return r;
      }
  
  }
  */
  