Logo Search packages:      
Sourcecode: cdk version File versions  Download package

MolecularFormula.java
/*  $RCSfile$
 *  $Author$
 *  $Date$
 *  $Revision$
 *
 *  Copyright (C) 2007  Miguel Rojasch <miguelrojasch@users.sf.net>
 *
 *  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.
 *
 *  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.formula;

import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.DefaultChemObjectBuilder;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.interfaces.IIsotope;
import org.openscience.cdk.interfaces.IMolecularFormula;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
/**
 * Class defining a molecular formula object. It maintains
 * a list of list {@link IIsotope}.
 *   
 * <p>Examples:
 * <ul>
 *   <li><code>[C<sub>5</sub>H<sub>5</sub>]-</code></li>
 *   <li><code>C<sub>6</sub>H<sub>6</sub></code></li>
 *   <li><code><sup>12</sup>C<sub>5</sub><sup>13</sup>CH<sub>6</sub></code></li>
 * </ul>
 * 
 * @cdk.module  data
 * @author      miguelrojasch
 * @cdk.created 2007-11-20
 * @cdk.keyword molecular formula
 */
@TestClass("org.openscience.cdk.formula.MolecularFormulaTest")
00055 public class MolecularFormula implements IMolecularFormula, Cloneable {

      /**
     * Determines if a de-serialized object is compatible with this class.
     *
     * This value must only be changed if and only if the new version
     * of this class is imcompatible with the old version. See Sun docs
     * for <a href=http://java.sun.com/products/jdk/1.1/docs/guide
     * /serialization/spec/version.doc.html>details</a>.
       */
00065       private static final long serialVersionUID = -2011407700837295287L;
      
      private Map<IIsotope, Integer> isotopes;
      /**
     *  The partial charge of the molecularFormula. The default value is Double.NaN.
     */
00071       private Integer charge = (Integer) CDKConstants.UNSET;

      /**
       *  A hashtable for the storage of any kind of properties of this IChemObject.
       */
00076       private Map<Object, Object> properties;
      
      /**
       *  Constructs an empty MolecularFormula.
       */
00081       public MolecularFormula() {
            isotopes = new HashMap<IIsotope,Integer>();
      }
      
      /**
       * Adds an molecularFormula to this MolecularFormula.
       *
       * @param  formula  The molecularFormula to be added to this chemObject
       * @return          The IMolecularFormula
       */
    @TestMethod("testAdd_IMolecularFormula")
00092       public IMolecularFormula add(IMolecularFormula formula) {
            for (IIsotope newIsotope : formula.isotopes()) {
                  addIsotope(newIsotope,formula.getIsotopeCount(newIsotope));
            }
            if(formula.getCharge() != null)charge += formula.getCharge();
            return this;
      }

      
      /**
       *  Adds an Isotope to this MolecularFormula one time.
       *
       * @param  isotope  The isotope to be added to this MolecularFormula
       * @see             #addIsotope(IIsotope, int)
       */
    @TestMethod("addIsotope_IIsotope")
00108       public IMolecularFormula addIsotope(IIsotope isotope) {
            return this.addIsotope(isotope, 1);
      }

      /**
       *  Adds an Isotope to this MolecularFormula in a number of occurrences.
       *
       * @param  isotope  The isotope to be added to this MolecularFormula
       * @param  count    The number of occurrences to add
       * @see             #addIsotope(IIsotope)
       */
    @TestMethod("testAddIsotope_IIsotope_int")
00120       public IMolecularFormula addIsotope(IIsotope isotope, int count) {
            boolean flag = false;
            for (IIsotope thisIsotope : isotopes()) {
                  if(isTheSame(thisIsotope, isotope)){
                        isotopes.put(thisIsotope, isotopes.get(thisIsotope) + count);
                        flag = true;
                        break;
                  }
            }
            if(!flag){
                  isotopes.put(isotope, count);
            }
            
            return this;
      }

      /**
       *  True, if the MolecularFormula contains the given IIsotope object and not
       *  the instance. The method looks for other isotopes which has the same
       *  symbol, natural abundance and exact mass.
       *
       * @param  isotope  The IIsotope this MolecularFormula is searched for
       * @return          True, if the MolecularFormula contains the given isotope object
       */
    @TestMethod("testContains_IIsotope")
00145       public boolean contains(IIsotope isotope) {
            for (IIsotope thisIsotope : isotopes()) {
                  if(isTheSame(thisIsotope, isotope)){
                        return true;
                  }
            }
            return false;
      }

      /**
     *  Returns the partial charge of this IMolecularFormula. If the charge 
     *  has not been set the return value is Double.NaN.
     *
     * @return the charge of this IMolecularFormula
     *
     * @see    #setCharge
     */
    @TestMethod("testGetCharge")
00163       public Integer getCharge() {
            return charge;
      }

      /**
       *  Checks a set of Nodes for the occurrence of the isotope in the 
       *  IMolecularFormula from a particular isotope. It returns 0 if the does not exist.
       *
       * @param   isotope          The IIsotope to look for
       * @return                   The occurrence of this isotope in this IMolecularFormula
       * @see                      #getIsotopeCount()
       */
    @TestMethod("testGetIsotopeCount_IIsotope")
00176       public int getIsotopeCount(IIsotope isotope) {
            return !contains(isotope) ? 0 : isotopes.get(getIsotope(isotope));
      }

      /**
       *  Checks a set of Nodes for the number of different isotopes in the 
       *  IMolecularFormula.
       *
       * @return        The the number of different isotopes in this IMolecularFormula
       * @see           #getIsotopeCount(IIsotope)
       */
    @TestMethod("testGetIsotopeCount")
00188       public int getIsotopeCount() {
            return isotopes.size();
      }
      
      /**
       *  Get the isotope instance given an IIsotope. The instance is those
       *  that has the isotope with the same symbol, natural abundance and
       *  exact mass.
       *
       * @param  isotope The IIsotope for looking for
       * @return         The IIsotope instance
   * @see            #isotopes
       */
00201       private IIsotope getIsotope(IIsotope isotope){
            for (IIsotope thisIsotope : isotopes()) {
                  if(isTheSame(isotope,thisIsotope))
                        return thisIsotope;
            }
            return null;
      }
      /**
       *  Returns an Iterator for looping over all isotopes in this IMolecularFormula.
       *
       * @return    An Iterator with the isotopes in this IMolecularFormula
       */
    @TestMethod("testIsotopes")
00214       public Iterable<IIsotope> isotopes() {
            return isotopes.keySet();
      }

      /**
     *  Sets the partial charge of this IMolecularFormula.
     *
     * @param  charge  The partial charge
     *
     * @see    #getCharge
     */
    @TestMethod("testSetCharge_Integer")
00226       public void setCharge(Integer charge) {
            this.charge = charge;
      }

      /**
       * Removes all isotopes of this molecular formula.
       */
    @TestMethod("testRemoveAllIsotopes")
00234     public void removeAllIsotopes() {
          isotopes.clear();
    }

    /**
       *  Removes the given isotope from the MolecularFormula.
       *
       * @param isotope  The IIsotope to be removed
       */
    @TestMethod("testRemoveIsotope_IIsotope")
00244     public void removeIsotope(IIsotope isotope) {
          isotopes.remove(getIsotope(isotope));
    }

    /**
       * Clones this MolecularFormula object and its content. I should
       * integrate into ChemObject.
       *
       * @return    The cloned object
       */
    @TestMethod("testClone")
00255       public Object clone() throws CloneNotSupportedException {
            
//          /* it is not a super class of chemObject */
//          MolecularFormula clone = (MolecularFormula) super.clone();
//        // start from scratch
//          clone.removeAllIsotopes();
//        // clone all isotopes
//          Iterator<IIsotope> iterIso = this.isotopes();
//          while(iterIso.hasNext()){
//                IIsotope isotope = iterIso.next();
//                clone.addIsotope((IIsotope) isotope.clone(),getIsotopeCount(isotope));
//          }
            
            MolecularFormula clone = new MolecularFormula();
            for (IIsotope isotope : isotopes()) {
                  clone.addIsotope((IIsotope) isotope.clone(),getIsotopeCount(isotope));
            }
            clone.setCharge(getCharge());
            return clone;
      }
      /**
       * Lazy creation of properties hash. I should
       * integrate into ChemObject.
       *
       * @return    Returns in instance of the properties
       */
00281       private Map<Object, Object> lazyProperties(){
            if (properties == null)
            {
                  properties = new Hashtable<Object, Object>();
            }
            return properties;
      }


      /**
       *  Sets a property for a IChemObject. I should
       * integrate into ChemObject.
       *
       *@param  description  An object description of the property (most likely a
       *      unique string)
       *@param  property     An object with the property itself
       *@see                 #getProperty
       *@see                 #removeProperty
       */
    @TestMethod("testSetProperty_Object_Object")
00301       public void setProperty(Object description, Object property){
            lazyProperties().put(description, property);
      }


      /**
       *  Removes a property for a IChemObject. I should
       * integrate into ChemObject.
       *
       *@param  description  The object description of the property (most likely a
       *      unique string)
       *@see                 #setProperty
       *@see                 #getProperty
       */
    @TestMethod("testRemoveProperty_Object")
00316       public void removeProperty(Object description){
            if (properties == null) {
            return;
        }
        lazyProperties().remove(description);
      }


      /**
       *  Returns a property for the IChemObject. I should
       * integrate into ChemObject.
       *
       *@param  description  An object description of the property (most likely a
       *      unique string)
       *@return              The object containing the property. Returns null if
       *      propert is not set.
       *@see                 #setProperty
       *@see                 #removeProperty
       */
    @TestMethod("testGetProperty_Object")
00336       public Object getProperty(Object description){
        if (properties != null) {
            return lazyProperties().get(description);
        }
        return null;
      }


      /**
       *  Returns a Map with the IChemObject's properties.I should
       * integrate into ChemObject.
       *
       *@return    The object's properties as an Hashtable
       *@see       #setProperties
       */
    @TestMethod("testGetProperties")
00352       public Map<Object, Object> getProperties(){
            return lazyProperties();
      }
      /**
       *  Sets the properties of this object.
       *
       *@param  properties  a Hashtable specifying the property values
       *@see                #getProperties
       */
    @TestMethod("testSetProperties_Hashtable")
00362       public void setProperties(Map<Object, Object> properties){
            
            Iterator<Object> keys = properties.keySet().iterator();
            while (keys.hasNext()) {
                  Object key = keys.next();
                  lazyProperties().put(key, properties.get(key));
            }
      }
      /**
       * Compare to IIsotope. The method doesn't compare instance but if they
       * have the same symbol, natural abundance and exact mass.
       * 
       * @param isotopeOne   The first Isotope to compare
       * @param isotopeTwo   The second Isotope to compare
       * @return             True, if both isotope are the same
       */
    @TestMethod("testIsTheSame")
00379       protected boolean isTheSame(IIsotope isotopeOne, IIsotope isotopeTwo) {

        Double natAbund1 = isotopeOne.getNaturalAbundance();
        Double natAbund2 = isotopeTwo.getNaturalAbundance();

        Double exactMass1 = isotopeOne.getExactMass();
        Double exactMass2 = isotopeTwo.getExactMass();

        if (natAbund1 == null) natAbund1 = -1.0;
        if (natAbund2 == null) natAbund2 = -1.0;
        if (exactMass1 == null) exactMass1 = -1.0;
        if (exactMass2 == null) exactMass2 = -1.0;

            if(!isotopeOne.getSymbol().equals(isotopeTwo.getSymbol() ))
                  return false;
            if(natAbund1.doubleValue() != natAbund2)
                  return false;
            return exactMass1.doubleValue() == exactMass2;
      }

00399       public IChemObjectBuilder getBuilder() {
          return DefaultChemObjectBuilder.getInstance();
    }

}

Generated by  Doxygen 1.6.0   Back to index