/* $RCSfile$
* $Author$
* $Date$
* $Revision$
*
* Copyright (C) 1997-2007 Edgar Luttmann <edgar@uni-paderborn.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;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IBioPolymer;
import org.openscience.cdk.interfaces.IMonomer;
import org.openscience.cdk.interfaces.IStrand;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
/**
* A BioPolymer is a subclass of a Polymer which is supposed to store
* additional informations about the Polymer which are connected to BioPolymers.
*
* @cdk.module data
* @cdk.githash
*
* @author Edgar Luttmann <edgar@uni-paderborn.de>
* @author Martin Eklund
* @cdk.created 2001-08-06
*
* @cdk.keyword polymer
* @cdk.keyword biopolymer
*/
public class BioPolymer extends Polymer implements java.io.Serializable, IBioPolymer
{
/**
* 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 incompatible 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>.
*/
private static final long serialVersionUID = -5001873073769634393L;
private Map<String, IStrand> strands; // the list of all the contained Strands.
/**
* Constructs a new Polymer to store the Strands.
*/
public BioPolymer() {
super();
// Strand stuff
strands = new Hashtable<String, IStrand>();
}
/**
* Adds the atom oAtom to a specified Strand, whereas the Monomer is unspecified. Hence
* the atom will be added to a Monomer of type UNKNOWN in the specified Strand.
*
* @param oAtom The atom to add
* @param oStrand The strand the atom belongs to
*/
public void addAtom(IAtom oAtom, IStrand oStrand) {
int atomCount = super.getAtomCount();
// Add atom to AtomContainer
super.addAtom(oAtom);
if (atomCount != super.getAtomCount() &&
oStrand != null) { // Maybe better to throw null pointer exception here, so user realises that
// Strand == null and Atom only gets added to this BioPolymer, but not to a Strand.
oStrand.addAtom(oAtom);
if (!strands.containsKey(oStrand.getStrandName())) {
strands.put(oStrand.getStrandName(), oStrand);
}
}
/* notifyChanged() is called by addAtom in
AtomContainer */
}
/**
* Adds the atom to a specified Strand and a specified Monomer.
*
* @param oAtom
* @param oMonomer
* @param oStrand
*/
public void addAtom(IAtom oAtom, IMonomer oMonomer, IStrand oStrand) {
int atomCount = super.getAtomCount();
// Add atom to AtomContainer
super.addAtom(oAtom);
if(atomCount != super.getAtomCount() && // OK, super did not yet contain the atom
// Add atom to Strand (also adds the atom to the monomer).
oStrand != null) {
oStrand.addAtom(oAtom, oMonomer); // Same problem as above: better to throw nullpointer exception?
if (!strands.containsKey(oStrand.getStrandName())) {
strands.put(oStrand.getStrandName(), oStrand);
}
}
/* The reasoning above is:
* All Monomers have to belong to a Strand and all atoms belonging to strands have to belong to a Monomer =>
* ? oMonomer != null and oStrand != null, oAtom is added to BioPolymer and to oMonomer in oStrand
* ? oMonomer == null and oStrand != null, oAtom is added to BioPolymer and default Monomer in oStrand
* ? oMonomer != null and oStrand == null, oAtom is added to BioPolymer, but not to a Monomer or Strand (especially good to maybe throw exception in this case)
* ? oMonomer == null and oStrand == null, oAtom is added to BioPolymer, but not to a Monomer or Strand
* */
}
/**
* Returns the number of monomers present in BioPolymer.
*
* @return number of monomers
*/
public int getMonomerCount() {
Iterator<String> keys = strands.keySet().iterator();
int number = 0;
while(keys.hasNext()) {
Strand tmp = (Strand)strands.get(keys.next()); // Cast exception?!
number += (tmp.getMonomers()).size() - 1;
}
return number;
}
/**
* Retrieves a Monomer object by specifying its name. [You have to specify the strand to enable
* monomers with the same name in different strands. There is at least one such case: every
* strand contains a monomer called "".]
*
* @param monName The name of the monomer to look for
* @return The Monomer object which was asked for
*
*/
public IMonomer getMonomer(String monName, String strandName) {
Strand strand = (Strand)strands.get(strandName);
if(strand != null) {
return (Monomer)strand.getMonomer(monName);
}
else {
return null;
}
}
/* Could look like this if you ensured individual name giving for ALL monomers:
*
public Monomer getMonomer(String cName) {
Enumeration keys = strands.keys();
Monomer oMonomer = null;
while(keys.hasMoreElements()) {
if(((Strand)strands.get(keys.nextElement())).getMonomers().containsKey(cName)) {
Strand oStrand = (Strand)strands.get(keys.nextElement());
oMonomer = oStrand.getMonomer(cName);
break;
}
}
return oMonomer;
}
*/
/**
* Returns a collection of the names of all <code>Monomer</code>s in this
* BioPolymer.
*
* @return a <code>Collection</code> of all the monomer names.
*/
public Collection<String> getMonomerNames() {
Iterator<String> keys = strands.keySet().iterator();
Map<String, IMonomer> monomers = new Hashtable<String, IMonomer>();
while(keys.hasNext()) {
Strand oStrand = (Strand)strands.get(keys.next());
monomers.putAll(oStrand.getMonomers());
}
return monomers.keySet();
}
/**
*
* Returns the number of strands present in the BioPolymer.
*
* @return number of strands
*
*/
public int getStrandCount() {
return strands.size();
}
/**
*
* Retrieves a Monomer object by specifying its name.
*
* @param cName The name of the monomer to look for
* @return The Monomer object which was asked for
*
*/
public IStrand getStrand(String cName) {
return (Strand)strands.get(cName);
}
/**
* Returns a collection of the names of all <code>Strand</code>s in this
* BioPolymer.
*
* @return a <code>Collection</code> of all the strand names.
*/
public Collection<String> getStrandNames() {
return strands.keySet();
}
/**
* Removes a particular strand, specified by its name.
*
* @param name name of the strand to remove
*/
public void removeStrand(String name) {
if (strands.containsKey(name)) {
Strand strand = (Strand)strands.get(name);
this.remove(strand);
strands.remove(name);
}
}
/**
* @return hashtable containing the monomers in the strand.
*/
public Map<String, IStrand> getStrands() {
return strands;
}
public String toString() {
StringBuffer stringContent = new StringBuffer();
stringContent.append("BioPolymer(");
stringContent.append(this.hashCode()).append(", ");
stringContent.append(super.toString());
stringContent.append(')');
return stringContent.toString();
}
public Object clone() throws CloneNotSupportedException {
BioPolymer clone = (BioPolymer)super.clone();
clone.strands.clear();
for (Iterator<String> strands = clone.getStrandNames().iterator(); strands.hasNext();) {
Strand strand = (Strand)clone.getStrand(strands.next().toString()).clone();
for (Iterator<String> iter = strand.getMonomerNames().iterator(); iter.hasNext();) {
IMonomer monomer = strand.getMonomer(iter.next().toString());
Iterator<IAtom> atoms = monomer.atoms().iterator();
while (atoms.hasNext()) {
clone.addAtom((IAtom)atoms.next(), monomer, strand);
}
}
}
return clone;
}
}