/* $RCSfile$
* $Author$
* $Date$
* $Revision$
*
* Copyright (C) 2001-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.IBond;
import org.openscience.cdk.interfaces.ILonePair;
import org.openscience.cdk.interfaces.IMonomer;
import org.openscience.cdk.interfaces.IPolymer;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;
/**
* Subclass of Molecule to store Polymer specific attributes that a Polymer has.
*
* @cdk.module data
* @cdk.githash
*
* @author Edgar Luttmann <edgar@uni-paderborn.de>
* @author Martin Eklund <martin.eklund@farmbio.uu.se>
* @cdk.created 2001-08-06
* @cdk.keyword polymer
*/
public class Polymer extends Molecule implements java.io.Serializable, IPolymer
{
/**
* 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 = -2596790658835319339L;
private Map<String, IMonomer> monomers; // the list of all the contained Monomers.
/**
* Constructs a new Polymer to store the Monomers.
*/
public Polymer() {
super();
monomers = new Hashtable<String, IMonomer>();
}
/**
* Adds the atom oAtom to a specified Monomer.
*
* @param oAtom The atom to add
* @param oMonomer The monomer the atom belongs to
*/
public void addAtom(IAtom oAtom, IMonomer oMonomer) {
if(!contains(oAtom)) {
super.addAtom(oAtom);
if(oMonomer != null) { // Not sure what's better here...throw nullpointer exception?
oMonomer.addAtom(oAtom);
if (! monomers.containsKey(oMonomer.getMonomerName())) {
monomers.put(oMonomer.getMonomerName(), oMonomer);
}
}
}
/* notifyChanged() is called by addAtom in
AtomContainer */
}
/**
* Returns the number of monomers present in the Polymer.
*
* @return number of monomers
*/
public int getMonomerCount() {
return monomers.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 IMonomer getMonomer(String cName) {
return monomers.get(cName);
}
/**
* Returns a collection of the names of all <code>Monomer</code>s in this
* polymer.
*
* @return a <code>Collection</code> of all the monomer names.
*/
public Collection<String> getMonomerNames() {
return monomers.keySet();
}
/**
* Removes a particular monomer, specified by its name.
*
* @param name The name of the monomer to remove
*/
public void removeMonomer(String name) {
if (monomers.containsKey(name)) {
Monomer monomer = (Monomer)monomers.get(name);
this.remove(monomer);
monomers.remove(name);
}
}
public String toString() {
StringBuffer stringContent = new StringBuffer();
stringContent.append("Polymer(");
stringContent.append(this.hashCode()).append(", ");
stringContent.append(super.toString());
stringContent.append(')');
return stringContent.toString();
}
/*
TODO it's not clear why we need to remove all elements after the clone
Looks like we should only clone the monomer related stuff
*/
public Object clone() throws CloneNotSupportedException {
Polymer clone = (Polymer)super.clone();
clone.removeAllElements();
clone.monomers = new Hashtable<String, IMonomer>();
for (String monomerName : getMonomerNames()) {
Monomer monomerClone = (Monomer) getMonomer(monomerName).clone();
for (IAtom atomInMonomer : monomerClone.atoms()) {
clone.addAtom(atomInMonomer, monomerClone);
}
}
// now consider atoms that are not associated with any monomer
for (IAtom atom : atoms()) {
if (!atomIsInMonomer(atom))
clone.addAtom((IAtom) atom.clone());
}
// since we already removed bonds we'll have to add them back
IBond newBond;
for (IBond bond : bonds()) {
newBond = (IBond)bond.clone();
IAtom[] newAtoms = new IAtom[bond.getAtomCount()];
for (int j = 0; j < bond.getAtomCount(); ++j) {
newAtoms[j] = clone.getAtom(getAtomNumber(bond.getAtom(j)));
}
newBond.setAtoms(newAtoms);
clone.addBond(newBond);
}
// put back lone pairs
ILonePair lp;
ILonePair newLp;
for (int i = 0; i < getLonePairCount(); ++i) {
lp = getLonePair(i);
newLp = (ILonePair) lp.clone();
newLp.setAtom(clone.getAtom(getAtomNumber(lp.getAtom())));
clone.addLonePair(newLp);
}
return clone;
}
private boolean atomIsInMonomer(IAtom atom) {
for (String monomerName : getMonomerNames()) {
IMonomer monomer = getMonomer(monomerName);
if (monomer.contains(atom)) return true;
}
return false;
}
}