IDCreator.java :  » Science » Chemistry-Development-Kit-1.3.5 » org » openscience » cdk » tools » Java Open Source

Java Open Source » Science » Chemistry Development Kit 1.3.5 
Chemistry Development Kit 1.3.5 » org » openscience » cdk » tools » IDCreator.java
/* $Revision$ $Author$ $Date$
 *
 * Copyright (C) 2003-2007  Egon Willighagen <egonw@users.sf.net>
 *                    2008  Aleksey Tarkhov <bayern7105@yahoo.de>
 *
 * Contact: cdk-devel@lists.sourceforge.net
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 * All we ask is that proper credit is given for our work, which includes
 * - but is not limited to - adding the above copyright notice to the beginning
 * of your source code files, and to any copyright notice that you may distribute
 * with programs based on this work.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.openscience.cdk.tools;

import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.tools.manipulator.*;

import java.util.Iterator;
import java.util.List;

/**
 * Class that provides methods to give unique IDs to ChemObjects.
 * Methods are implemented for Atom, Bond, AtomContainer, AtomContainerSet
 * and Reaction. It will only create missing IDs. If you want to create new
 * IDs for all ChemObjects, you need to delete them first.
 *
 * @cdk.module standard
 * @cdk.githash
 *
 * @author   Egon Willighagen
 * @cdk.created  2003-04-01
 *
 * @cdk.keyword  id, creation
 */
@TestClass("org.openscience.cdk.tools.IDCreatorTest")
public abstract class IDCreator {

  // counters for generated in current session IDs
  private static int REACTION_COUNT = 0;
  private static int ATOM_COUNT = 0;
  private static int BOND_COUNT = 0;
  private static int ATOMCONTAINER_COUNT = 0;
  private static int ATOMCONTAINERSET_COUNT = 0;
  private static int REACTIONSET_COUNT = 0;
  private static int CHEMMODEL_COUNT = 0;
  private static int CHEMSEQUENCE_COUNT = 0;
  private static int CHEMFILE_COUNT = 0;

  // prefix to prepend every individual IDs
  private final static String REACTION_PREFIX = "r";
  private final static String ATOM_PREFIX = "a";
  private final static String BOND_PREFIX = "b";
  private final static String ATOMCONTAINER_PREFIX = "m";
  private final static String ATOMCONTAINERSET_PREFIX = "molSet";
  private final static String REACTIONSET_PREFIX = "rset";
  private final static String CHEMMODEL_PREFIX = "model";
  private final static String CHEMSEQUENCE_PREFIX = "seq";
  private final static String CHEMFILE_PREFIX = "file";
  
  /**
   * Old ID generation policy - to generate IDs unique over the entire set 
   */
  public static final int SET_UNIQUE_POLICY = 0;

  /**
   * New ID generation policy - to generate IDs unique only in a molecule
   */
  public static final int OBJECT_UNIQUE_POLICY = 1;

  /**
   * Internal flag identifying the IDs generation policy. The old policy
   * is to generate IDs so that in a sequence of several molecules all the 
   * atoms and bonds will receive the unique IDs even across molecules, i.e.
   * in a set of 2 molecules the first atom of the first molecule will be "a1"
   * while the first atom of the second molecule will be "aX" where X equals 
   * to the number of atoms in the first molecule plus 1. 
   * <br/>
   * The new policy is to keep the singularity of IDs only within a single
   * molecule, i.e. in a set of two molecules first atoms of each will be "a1".
   */ 
  private static int policy = SET_UNIQUE_POLICY;
  
  /**
   * Alters the policy of ID generation. The IDCreator should in any case 
   * preserve the already existing IDs therefore if one of objects already 
   * has an ID set, this ID will be skipped in all the cases when attempting to
   * generate a new ID value
   * @param policy new policy to be used
   * @see #OBJECT_UNIQUE_POLICY
   * @see #SET_UNIQUE_POLICY
   */
  public static void setIDPolicy(int policy) {
    IDCreator.policy = policy;
  }
  
  /**
   * Labels the Atom's and Bond's in the AtomContainer using the a1, a2, b1, b2
     * scheme often used in CML. Supports IAtomContainer, IAtomContainerSet,
     * IChemFile, IChemModel, IChemSequence, IReaction, IReactionSet,
     * and derived interfaces.
     * 
   * @param  chemObject IChemObject to create IDs for.
   */
    @TestMethod("testCreateIDs_IChemObject,testKeepingIDs,testNoDuplicateCreation,testCallingTwice")
    public static void createIDs(IChemObject chemObject) {
    if (chemObject == null) return;
    
    resetCounters();
    
    if (chemObject instanceof IAtomContainer) {
      createIDsForAtomContainer((IAtomContainer)chemObject, null);
    } else if (chemObject instanceof IAtomContainerSet) {
      createIDsForAtomContainerSet((IAtomContainerSet)chemObject, null);
    } else if (chemObject instanceof IReaction) {
      createIDsForReaction((IReaction)chemObject, null);
    } else if (chemObject instanceof IReactionSet) {
      createIDsForReactionSet((IReactionSet)chemObject, null);
    } else if (chemObject instanceof IChemFile) {
      createIDsForChemFile((IChemFile)chemObject, null);
    } else if (chemObject instanceof IChemSequence) {
      createIDsForChemSequence((IChemSequence)chemObject, null);
    } else if (chemObject instanceof IChemModel) {
      createIDsForChemModel((IChemModel)chemObject, null);
    }
  }

  /**
   * Reset the counters so that we keep generating simple IDs within 
   * single chem object or a set of them
   */
  private static void resetCounters() {
    ATOM_COUNT = 0;
    BOND_COUNT = 0;
    ATOMCONTAINER_COUNT = 0;
    ATOMCONTAINERSET_COUNT = 0;
    REACTION_COUNT = 0;
    REACTIONSET_COUNT = 0;
    CHEMMODEL_COUNT = 0;
    CHEMSEQUENCE_COUNT = 0;
    CHEMFILE_COUNT = 0;
  }
  
  /**
   * Sets the ID on the object and adds it to the tabu list.
   * 
   * @param object   IChemObject to set the ID for
   * @param tabuList Tabu list to add the ID to
   */
  private static int setID(String prefix, int identifier, IChemObject object, List<String> tabuList) {
    identifier += 1;
    while (tabuList.contains(prefix + identifier)) {
      identifier += 1;
    }
    object.setID(prefix + identifier);
    tabuList.add(prefix + identifier);
    return identifier;
  }

    /**
     * Labels the Atom's and Bond's in the AtomContainer using the a1, a2, b1, b2
     * scheme often used in CML.
     *
     * @see #createIDs(org.openscience.cdk.interfaces.IChemObject)
     */
    private static void createIDsForAtomContainer(IAtomContainer container, List<String> tabuList) {
      if (tabuList == null) tabuList = AtomContainerManipulator.getAllIDs(container);
      
    if (null == container.getID()) {
      // generate new ID and remember it
      ATOMCONTAINER_COUNT = setID(ATOMCONTAINER_PREFIX, ATOMCONTAINER_COUNT, container, tabuList);
    }
      
    // the tabu list for the container should force singularity
    // within a container only!
    List internalTabuList = AtomContainerManipulator.getAllIDs(container);
    if (policy == OBJECT_UNIQUE_POLICY) {
        // start atom and bond indices within a container set always from 1
        ATOM_COUNT = 0;
        BOND_COUNT = 0;
      } else {
        internalTabuList = tabuList;
        }
        
        Iterator atoms = container.atoms().iterator();
        while(atoms.hasNext()) {
          IAtom atom = (IAtom)atoms.next();
      if (null == atom.getID()) {
        ATOM_COUNT = setID(ATOM_PREFIX, ATOM_COUNT, atom, internalTabuList);
            }
        }

        Iterator bonds = container.bonds().iterator();
        while (bonds.hasNext()) {
            IBond bond = (IBond) bonds.next();
      if (null == bond.getID()) {
        BOND_COUNT = setID(BOND_PREFIX, BOND_COUNT, bond, internalTabuList);
            }
        }
    }

  /**
     * Labels the Atom's and Bond's in each AtomContainer using the a1, a2, b1, b2
     * scheme often used in CML. It will also set id's for all AtomContainers, naming
     * them m1, m2, etc.
     * It will not the AtomContainerSet itself.
     */
    private static void createIDsForAtomContainerSet(IAtomContainerSet containerSet, List<String> tabuList) {
        if (tabuList == null) tabuList = AtomContainerSetManipulator.getAllIDs(containerSet);

    if (null == containerSet.getID()) {
      ATOMCONTAINERSET_COUNT = setID(ATOMCONTAINERSET_PREFIX, ATOMCONTAINERSET_COUNT, containerSet, tabuList);
    }
        
    if (policy == OBJECT_UNIQUE_POLICY) {
    // start atom and bond indices within a container set always from 1
      ATOM_COUNT = 0;
      BOND_COUNT = 0;
        }

        Iterator<IAtomContainer> acs = containerSet.atomContainers().iterator();
        while (acs.hasNext()) {
      createIDsForAtomContainer((IAtomContainer)acs.next(), tabuList);
        }
    }
    
    /**
     * Labels the reactants and products in the Reaction m1, m2, etc, and the atoms
     * accordingly, when no ID is given.
     */
    private static void createIDsForReaction(IReaction reaction, List<String> tabuList) {
        if (tabuList == null) tabuList = ReactionManipulator.getAllIDs(reaction);
        
    if (null == reaction.getID()) {
      // generate new ID
      REACTION_COUNT = setID(REACTION_PREFIX, REACTION_COUNT, reaction, tabuList);
    }
        
    if (policy == OBJECT_UNIQUE_POLICY) {
      // start atom and bond indices within a reaction set always from 1
      ATOM_COUNT = 0;
      BOND_COUNT = 0;
        }

        for (IAtomContainer reactant : reaction.getReactants().atomContainers()) {
            createIDsForAtomContainer(reactant, tabuList);
        }
        for (IAtomContainer product : reaction.getReactants().atomContainers()) {
            createIDsForAtomContainer(product, tabuList);
        }
    Iterator<IAtomContainer> agents = reaction.getAgents().atomContainers().iterator();
    while (agents.hasNext()) {
      createIDsForAtomContainer((IAtomContainer)agents.next(), tabuList);
    }
    }
    
    private static void createIDsForReactionSet(IReactionSet reactionSet, List<String> tabuList) {
      if (tabuList == null) tabuList = ReactionSetManipulator.getAllIDs(reactionSet);
        
    if (null == reactionSet.getID()) {
      // generate new ID for the set
      REACTIONSET_COUNT = setID(REACTIONSET_PREFIX, REACTIONSET_COUNT, reactionSet, tabuList);
        }

    for (Iterator reaction = reactionSet.reactions().iterator(); reaction.hasNext();) {
      createIDsForReaction((IReaction)reaction.next(), tabuList);
        }
    }
    
    private static void createIDsForChemFile(IChemFile file, List<String> tabuList) {
      if (tabuList == null) tabuList = ChemFileManipulator.getAllIDs(file);
        
    if (null == file.getID()) {
      CHEMFILE_COUNT = setID(CHEMFILE_PREFIX, CHEMFILE_COUNT, file, tabuList);
    }

    if (policy == OBJECT_UNIQUE_POLICY) {
      // start indices within a chem file always from 1
      CHEMSEQUENCE_COUNT = 0;
        }

        for (IChemSequence chemSequence : file.chemSequences()) {
            createIDsForChemSequence(chemSequence, tabuList);
        }
    }
    
    private static void createIDsForChemSequence(IChemSequence sequence, List<String> tabuList) {
      if (tabuList == null) tabuList = ChemSequenceManipulator.getAllIDs(sequence);
        
    if (null == sequence.getID()) {
      CHEMSEQUENCE_COUNT = setID(CHEMSEQUENCE_PREFIX, CHEMSEQUENCE_COUNT, sequence, tabuList);
    }

    if (policy == OBJECT_UNIQUE_POLICY) {
      // start indices within a chem file always from 1
      CHEMSEQUENCE_COUNT = 0;
        }

        for (IChemModel chemModel : sequence.chemModels()) {
            createIDsForChemModel(chemModel, tabuList);
        }
    }
    
    private static void createIDsForChemModel(IChemModel model, List<String> tabuList) {
      if (tabuList == null) tabuList = ChemModelManipulator.getAllIDs(model);
        
    if (null == model.getID()) {
      CHEMMODEL_COUNT = setID(CHEMMODEL_PREFIX, CHEMMODEL_COUNT, model, tabuList);
        }
      
      ICrystal crystal = model.getCrystal();
    if (crystal != null) {
      if (policy == OBJECT_UNIQUE_POLICY) {
        ATOM_COUNT = 0;
        BOND_COUNT = 0;
      }
      createIDsForAtomContainer(crystal, tabuList);
    }
    
      IMoleculeSet moleculeSet = model.getMoleculeSet();
    if (moleculeSet != null) {
        if (policy == OBJECT_UNIQUE_POLICY) {  
          ATOMCONTAINERSET_COUNT = 0;
          ATOMCONTAINER_COUNT = 0;
        }
      createIDsForAtomContainerSet(moleculeSet, tabuList);
    }
    
      IReactionSet reactionSet = model.getReactionSet();
    if (reactionSet != null) {
      if (policy == OBJECT_UNIQUE_POLICY) {
        REACTIONSET_COUNT = 0;
        REACTION_COUNT = 0;
      }
      createIDsForReactionSet(reactionSet, tabuList);
    }
    }
    
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.