/* $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 java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.interfaces.IIsotope;
/**
* Class defining a expanded molecular formula object. The Isotopes don't have
* a fix occurrence in the MolecularFormula but they have a range.<p>
* With this class man can define a MolecularFormula which contains certain IIsotope
* with a maximum and minimum occurrence.
*
* Examples:
* <ul>
* <li><code>[C(1-5)H(4-10)]-</code></li>
* </ul>
*
* @cdk.module formula
* @author miguelrojasch
* @cdk.created 2007-11-20
* @cdk.keyword molecular formula
*/
@TestClass("org.openscience.cdk.formula.MolecularFormulaRangeTest")
public class MolecularFormulaRange implements Cloneable {
private Map<IIsotope,Integer> isotopesMax;
private Map<IIsotope,Integer> isotopesMin;
/**
* Constructs an empty MolecularFormulaExpand.
*/
public MolecularFormulaRange() {
isotopesMax = new HashMap<IIsotope,Integer>();
isotopesMin = new HashMap<IIsotope,Integer>();
}
/**
* Adds an Isotope to this MolecularFormulaExpand in a number of
* maximum and minimum occurrences allowed.
*
* @param isotope The isotope to be added to this MolecularFormulaExpand
* @param countMax The maximal number of occurrences to add
* @param countMin The minimal number of occurrences to add
*
*/
@TestMethod("testAddIsotope_IIsotope_int_int")
public void addIsotope(IIsotope isotope, int countMin, int countMax) {
boolean flag = false;
for(Iterator<IIsotope> it = isotopes().iterator(); it.hasNext(); ) {
IIsotope thisIsotope = it.next();
if(isTheSame(thisIsotope, isotope)){
isotopesMax.put(thisIsotope, countMax);
isotopesMin.put(thisIsotope, countMin);
flag = true;
break;
}
}
if(!flag){
isotopesMax.put(isotope, countMax);
isotopesMin.put(isotope, countMin);
}
}
/**
* True, if the MolecularFormulaExpand contains the given IIsotope.
* 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")
public boolean contains(IIsotope isotope) {
for(Iterator<IIsotope> it = isotopes().iterator(); it.hasNext(); ) {
IIsotope thisIsotope = it.next();
if(isTheSame(thisIsotope, isotope)){
return true;
}
}
return false;
}
/**
* Checks a set of Nodes for the maximal occurrence of the isotope in the
* MolecularFormulaExpand from a particular isotope. It returns -1 if the Isotope
* does not exist.
*
* @param isotope The IIsotope to look for
* @return The occurrence of this isotope in this IMolecularFormula
*/
@TestMethod("testGetIsotopeCountMax_IIsotope")
public int getIsotopeCountMax(IIsotope isotope) {
return !contains(isotope) ? -1 : isotopesMax.get(getIsotope(isotope));
}
/**
* Checks a set of Nodes for the minimal occurrence of the isotope in the
* MolecularFormulaExpand from a particular isotope. It returns -1 if the Isotope
* does not exist.
*
* @param isotope The IIsotope to look for
* @return The occurrence of this isotope in this IMolecularFormula
*/
@TestMethod("testGetIsotopeCountMin_IIsotope")
public int getIsotopeCountMin(IIsotope isotope) {
return !contains(isotope) ? -1 : isotopesMin.get(getIsotope(isotope));
}
/**
* Checks a set of Nodes for the number of different isotopes in the
* MolecularFormulaExpand.
*
* @return The the number of different isotopes in this MolecularFormulaExpand
*/
@TestMethod("testGetIsotopeCount")
public int getIsotopeCount() {
return isotopesMax.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
*/
private IIsotope getIsotope(IIsotope isotope){
for(Iterator<IIsotope> it = isotopes().iterator(); it.hasNext(); ) {
IIsotope thisIsotope = it.next();
if(isTheSame(isotope,thisIsotope))
return thisIsotope;
}
return null;
}
/**
* Returns an Iterator for looping over all isotopes in this MolecularFormulaExpand.
*
* @return An Iterator with the isotopes in this MolecularFormulaExpand
*/
@TestMethod("testIsotopes")
public Iterable<IIsotope> isotopes() {
return new Iterable<IIsotope>(){
public Iterator<IIsotope> iterator() {
return isotopesMax.keySet().iterator();
}
};
}
/**
* Removes all isotopes of this molecular formula.
*/
@TestMethod("testRemoveAllIsotopes")
public void removeAllIsotopes() {
isotopesMax.clear();
isotopesMin.clear();
}
/**
* Removes the given isotope from the MolecularFormulaExpand.
*
* @param isotope The IIsotope to be removed
*/
@TestMethod("testRemoveIsotope_IIsotope")
public void removeIsotope(IIsotope isotope) {
isotopesMax.remove(getIsotope(isotope));
isotopesMin.remove(getIsotope(isotope));
}
/**
* Clones this MolecularFormulaExpand object and its content. I should
* integrate into ChemObject.
*
* @return The cloned object
*/
@TestMethod("testClone")
public Object clone() throws CloneNotSupportedException {
MolecularFormulaRange clone = new MolecularFormulaRange();
Iterator<IIsotope> iterIso = this.isotopes().iterator();
while(iterIso.hasNext()){
IIsotope isotope = iterIso.next();
clone.addIsotope((IIsotope) isotope.clone(),getIsotopeCountMin(isotope),getIsotopeCountMax(isotope));
}
return clone;
}
/**
* 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
*/
private boolean isTheSame(IIsotope isotopeOne, IIsotope isotopeTwo) {
if(isotopeOne.getSymbol() != isotopeTwo.getSymbol() )
return false;
if(isotopeOne.getNaturalAbundance() != isotopeTwo.getNaturalAbundance() )
return false;
if(isotopeOne.getExactMass() != isotopeTwo.getExactMass() )
return false;
return true;
}
}