/* $RCSfile$ * $Author$ * $Date$ * $Revision$ * * Copyright (C) 1997-2007 Christoph Steinbeck * * 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; import java.io.Serializable; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IAtomParity; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IChemObjectChangeEvent; import org.openscience.cdk.interfaces.IChemObjectListener; import org.openscience.cdk.interfaces.IElectronContainer; import org.openscience.cdk.interfaces.ILonePair; import org.openscience.cdk.interfaces.ISingleElectron; import org.openscience.cdk.interfaces.IBond.Order; /** * Base class for all chemical objects that maintain a list of Atoms and * ElectronContainers. <p> * * Looping over all Bonds in the AtomContainer is typically done like: <pre> * Iterator iter = atomContainer.bonds(); * while (iter.hasNext()) { * IBond aBond = (IBond) iter.next(); * } * * </pre> * * @cdk.module data * @cdk.githash * * @author steinbeck * @cdk.created 2000-10-02 */ public class AtomContainer extends ChemObject implements IAtomContainer, IChemObjectListener, Serializable, 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 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 = 5678100348445919254L; /** * Number of atoms contained by this object. */ protected int atomCount; /** * Number of bonds contained by this object. */ protected int bondCount; /** * Number of lone pairs contained by this object. */ protected int lonePairCount; /** * Number of single electrons contained by this object. */ protected int singleElectronCount; /** * Amount by which the bond and atom arrays grow when elements are added and * the arrays are not large enough for that. */ protected int growArraySize = 10; /** * Internal array of atoms. */ protected IAtom[] atoms; /** * Internal array of bonds. */ protected IBond[] bonds; /** * Internal array of lone pairs. */ protected ILonePair[] lonePairs; /** * Internal array of single electrons. */ protected ISingleElectron[] singleElectrons; /** * Internal list of atom parities. */ protected Map<IAtom, IAtomParity> atomParities; /** * Constructs an empty AtomContainer. */ public AtomContainer() { this(10, 10, 0, 0); } /** * Constructs an AtomContainer with a copy of the atoms and electronContainers * of another AtomContainer (A shallow copy, i.e., with the same objects as in * the original AtomContainer). * * @param container An AtomContainer to copy the atoms and electronContainers from */ public AtomContainer(IAtomContainer container) { this.atomCount = container.getAtomCount(); this.bondCount = container.getBondCount(); this.lonePairCount = container.getLonePairCount(); this.singleElectronCount = container.getSingleElectronCount(); this.atoms = new IAtom[this.atomCount]; this.bonds = new IBond[this.bondCount]; this.lonePairs = new ILonePair[this.lonePairCount]; this.singleElectrons = new ISingleElectron[this.singleElectronCount]; atomParities = new Hashtable<IAtom, IAtomParity>(atomCount/2); for (int f = 0; f < container.getAtomCount(); f++) { atoms[f] = container.getAtom(f); container.getAtom(f).addListener(this); } for (int f = 0; f < this.bondCount; f++) { bonds[f] = container.getBond(f); container.getBond(f).addListener(this); } for (int f = 0; f < this.lonePairCount; f++) { lonePairs[f] = container.getLonePair(f); container.getLonePair(f).addListener(this); } for (int f = 0; f < this.singleElectronCount; f++) { singleElectrons[f] = container.getSingleElectron(f); container.getSingleElectron(f).addListener(this); } } /** * Constructs an empty AtomContainer that will contain a certain number of * atoms and electronContainers. It will set the starting array lengths to the * defined values, but will not create any Atom or ElectronContainer's. * *@param atomCount Number of atoms to be in this container *@param bondCount Number of bonds to be in this container *@param lpCount Number of lone pairs to be in this container *@param seCount Number of single electrons to be in this container * */ public AtomContainer(int atomCount, int bondCount, int lpCount, int seCount) { this.atomCount = 0; this.bondCount = 0; this.lonePairCount = 0; this.singleElectronCount = 0; atoms = new IAtom[atomCount]; bonds = new IBond[bondCount]; lonePairs = new ILonePair[lpCount]; singleElectrons = new ISingleElectron[seCount]; atomParities = new Hashtable<IAtom, IAtomParity>(atomCount/2); } /** * Adds an AtomParity to this container. If a parity is already given for the * affected Atom, it is overwritten. * * @param parity The new AtomParity for this container * @see #getAtomParity */ public void addAtomParity(IAtomParity parity) { atomParities.put(parity.getAtom(), parity); } /** * Returns the atom parity for the given Atom. If no parity is associated * with the given Atom, it returns null. * * @param atom Atom for which the parity must be returned * @return The AtomParity for the given Atom, or null if that Atom does * not have an associated AtomParity * @see #addAtomParity */ public IAtomParity getAtomParity(IAtom atom) { return atomParities.get(atom); } /** * Sets the array of atoms of this AtomContainer. * *@param atoms The array of atoms to be assigned to this AtomContainer *@see #getAtom */ public void setAtoms(IAtom[] atoms) { this.atoms = atoms; for (IAtom atom : atoms) { atom.addListener(this); } this.atomCount = atoms.length; notifyChanged(); } /** * Sets the array of bonds of this AtomContainer. * * @param bonds The array of bonds to be assigned to * this AtomContainer * @see #getBond */ public void setBonds(IBond[] bonds) { this.bonds = bonds; for (IBond bond : bonds) { bond.addListener(this); } this.bondCount = bonds.length; } /** * Sets the array of electronContainers of this AtomContainer. * *@param electronContainers The array of electronContainers to be assigned to * this AtomContainer *@see #getElectronContainers */ // public void setElectronContainers(IElectronContainer[] electronContainers) // { // this.electronContainers = electronContainers; // for (int f = 0; f < electronContainers.length; f++) // { // electronContainers[f].addListener(this); // } // setElectronContainerCount(electronContainers.length); // notifyChanged(); // } /** * Sets the atom at position <code>number</code> in [0,..]. * *@param number The position of the atom to be set. *@param atom The atom to be stored at position <code>number</code> *@see #getAtom(int) */ public void setAtom(int number, IAtom atom) { atom.addListener(this); atoms[number] = atom; notifyChanged(); } /** * Get the atom at position <code>number</code> in [0,..]. * *@param number The position of the atom to be retrieved. *@return The atomAt value * @see #setAtom(int, org.openscience.cdk.interfaces.IAtom) * @see #setAtoms(org.openscience.cdk.interfaces.IAtom[]) * */ public IAtom getAtom(int number) { return atoms[number]; } /** * Get the bond at position <code>number</code> in [0,..]. * *@param number The position of the bond to be retrieved. *@return The bondAt value */ public IBond getBond(int number) { return bonds[number]; } /** * Get the lone pair at position <code>number</code> in [0,..]. * *@param number The position of the LonePair to be retrieved. *@return The lone pair number */ public ILonePair getLonePair(int number) { return lonePairs[number]; } /** * Get the single electron at position <code>number</code> in [0,..]. * *@param number The position of the SingleElectron to be retrieved. *@return The single electron number */ public ISingleElectron getSingleElectron(int number) { return singleElectrons[number]; } /** * Sets the ElectronContainer at position <code>number</code> in [0,..]. * * @param number The position of the ElectronContainer to be set. * @param electronContainer The ElectronContainer to be stored at position <code>number</code> * @see #getElectronContainer(int) */ // public void setElectronContainer(int number, IElectronContainer electronContainer) // { // electronContainer.addListener(this); // electronContainers[number] = electronContainer; // notifyChanged(); // } /** * Sets the number of electronContainers in this container. * * @param electronContainerCount The number of electronContainers in this * container * @see #getElectronContainerCount */ // public void setElectronContainerCount(int electronContainerCount) // { // this.electronContainerCount = electronContainerCount; // notifyChanged(); // } /** * Sets the number of atoms in this container. * *@param atomCount The number of atoms in this container *@see #getAtomCount */ // public void setAtomCount(int atomCount) // { // this.atomCount = atomCount; // notifyChanged(); // } /** * Returns an Iterable for looping over all atoms in this container. * *@return An Iterable with the atoms in this container */ public Iterable<IAtom> atoms() { return new Iterable<IAtom>() { public Iterator<IAtom> iterator() { return new AtomIterator(); } }; } /** * The inner AtomIterator class. * */ private class AtomIterator implements Iterator<IAtom> { private int pointer = 0; public boolean hasNext() { return pointer < atomCount; } public IAtom next() { return atoms[pointer++]; } public void remove() { removeAtom(--pointer); } } /** * Returns an Iterable for looping over all bonds in this container. * *@return An Iterable with the bonds in this container */ public Iterable<IBond> bonds() { return new Iterable<IBond>() { public Iterator<IBond> iterator() { return new BondIterator(); } }; } /** * The inner BondIterator class. * */ private class BondIterator implements Iterator<IBond> { private int pointer = 0; public boolean hasNext() { return pointer < bondCount; } public IBond next() { return bonds[pointer++]; } public void remove() { removeBond(--pointer); } } /** * Returns an Iterable for looping over all lone pairs in this container. * *@return An Iterable with the lone pairs in this container */ public Iterable<ILonePair> lonePairs() { return new Iterable<ILonePair>() { public Iterator<ILonePair> iterator() { return new LonePairIterator(); } }; } /** * The inner LonePairIterator class. * */ private class LonePairIterator implements Iterator<ILonePair> { private int pointer = 0; public boolean hasNext() { return pointer < lonePairCount; } public ILonePair next() { return lonePairs[pointer++]; } public void remove() { removeLonePair(--pointer); } } /** * Returns an Iterable for looping over all single electrons in this container. * *@return An Iterable with the single electrons in this container */ public Iterable<ISingleElectron> singleElectrons() { return new Iterable<ISingleElectron>() { public Iterator<ISingleElectron> iterator() { return new SingleElectronIterator(); } }; } /** * The inner SingleElectronIterator class. * */ private class SingleElectronIterator implements Iterator<ISingleElectron> { private int pointer = 0; public boolean hasNext() { return pointer < singleElectronCount; } public ISingleElectron next() { return singleElectrons[pointer++]; } public void remove() { removeSingleElectron(--pointer); } } /** * Returns an Iterable for looping over all electron containers in this container. * *@return An Iterable with the electron containers in this container */ public Iterable<IElectronContainer> electronContainers() { return new Iterable<IElectronContainer>() { public Iterator<IElectronContainer> iterator() { return new ElectronContainerIterator(); } }; } /** * The inner ElectronContainerIterator class. * */ private class ElectronContainerIterator implements Iterator<IElectronContainer> { private int pointer = 0; public boolean hasNext() { return pointer < (bondCount + lonePairCount + singleElectronCount); } public IElectronContainer next() { if (pointer < bondCount) return bonds[pointer++]; else if (pointer < bondCount+lonePairCount) return lonePairs[(pointer++)-bondCount]; else if (pointer < bondCount+lonePairCount+singleElectronCount) return singleElectrons[(pointer++)-bondCount-lonePairCount]; return null; } public void remove() { if (pointer <= bondCount) removeBond(--pointer); else if (pointer <= bondCount+lonePairCount) removeLonePair((--pointer)-bondCount); else if (pointer <= bondCount+lonePairCount+singleElectronCount) removeSingleElectron((--pointer)-bondCount-lonePairCount); } } /** * Returns the atom at position 0 in the container. * *@return The atom at position 0 . */ public IAtom getFirstAtom() { return atoms[0]; } /** * Returns the atom at the last position in the container. * *@return The atom at the last position */ public IAtom getLastAtom() { return getAtomCount() > 0 ? (Atom)atoms[getAtomCount() - 1] : null; } /** * Returns the position of a given atom in the atoms array. It returns -1 if * the atom does not exist. * *@param atom The atom to be sought *@return The Position of the atom in the atoms array in [0,..]. */ public int getAtomNumber(IAtom atom) { for (int f = 0; f < atomCount; f++) { if (atoms[f] == atom) return f; } return -1; } /** * Returns the position of the bond between two given atoms in the * electronContainers array. It returns -1 if the bond does not exist. * *@param atom1 The first atom *@param atom2 The second atom *@return The Position of the bond between a1 and a2 in the * electronContainers array. */ public int getBondNumber(IAtom atom1, IAtom atom2) { return (getBondNumber(getBond(atom1, atom2))); } /** * Returns the position of a given bond in the electronContainers array. It * returns -1 if the bond does not exist. * *@param bond The bond to be sought *@return The Position of the bond in the electronContainers array in [0,..]. */ public int getBondNumber(IBond bond) { for (int f = 0; f < bondCount; f++) { if (bonds[f] == bond) return f; } return -1; } /** * Returns the position of a given lone pair in the lone pair array. * It returns -1 if the lone pair does not exist. * *@param lonePair The lone pair to be sought *@return The Position of the lone pair in the array.. */ public int getLonePairNumber(ILonePair lonePair) { for (int f = 0; f < lonePairCount; f++) { if (lonePairs[f] == lonePair) return f; } return -1; } /** * Returns the position of a given single electron in the single electron array. * It returns -1 if the single electron does not exist. * *@param singleElectron The single electron to be sought *@return The Position of the single electron in the array. */ public int getSingleElectronNumber(ISingleElectron singleElectron) { for (int f = 0; f < singleElectronCount; f++) { if (singleElectrons[f] == singleElectron) return f; } return -1; } /** * Returns the ElectronContainer at position <code>number</code> in the * container. * * @param number The position of the ElectronContainer to be returned. * @return The ElectronContainer at position <code>number</code>. */ public IElectronContainer getElectronContainer(int number) { if (number < this.bondCount) return bonds[number]; number -= this.bondCount; if (number < this.lonePairCount) return lonePairs[number]; number -= this.lonePairCount; if (number < this.singleElectronCount) return singleElectrons[number]; return null; } /** * Returns the bond that connects the two given atoms. * * @param atom1 The first atom * @param atom2 The second atom * @return The bond that connects the two atoms */ public IBond getBond(IAtom atom1, IAtom atom2) { for (int i = 0; i < getBondCount(); i++) { if (bonds[i].contains(atom1) && bonds[i].getConnectedAtom(atom1) == atom2) { return bonds[i]; } } return null; } /** * Returns the number of Atoms in this Container. * *@return The number of Atoms in this Container */ public int getAtomCount() { return this.atomCount; } /** * Returns the number of Bonds in this Container. * *@return The number of Bonds in this Container */ public int getBondCount() { return this.bondCount; } /** * Returns the number of LonePairs in this Container. * *@return The number of LonePairs in this Container */ public int getLonePairCount() { return this.lonePairCount; } /** * Returns the number of the single electrons in this container, * *@return The number of SingleElectron objects of this AtomContainer */ public int getSingleElectronCount() { return this.singleElectronCount; } /** * Returns the number of ElectronContainers in this Container. * * @return The number of ElectronContainers in this Container */ public int getElectronContainerCount() { return this.bondCount + this.lonePairCount + this.singleElectronCount; } /** * Returns an ArrayList of all atoms connected to the given atom. * *@param atom The atom the bond partners are searched of. *@return The ArrayList with the connected atoms */ public List<IAtom> getConnectedAtomsList(IAtom atom) { List<IAtom> atomsList = new ArrayList<IAtom>(); for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom)) atomsList.add(bonds[i].getConnectedAtom(atom)); } return atomsList; } /** * Returns an ArrayList of all Bonds connected to the given atom. * *@param atom The atom the connected bonds are searched of *@return The ArrayList with connected atoms */ public List<IBond> getConnectedBondsList(IAtom atom) { List<IBond> bondsList = new ArrayList<IBond>(); for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom)) bondsList.add(bonds[i]); } return bondsList; } /** * Returns the array of lone pairs connected to an atom. * * @param atom The atom for which to get lone pairs * @return The array of LonePairs of this AtomContainer * @see #getElectronContainer * @see #electronContainers() * @see #getBond */ public List<ILonePair> getConnectedLonePairsList(IAtom atom) { List<ILonePair> lps = new ArrayList<ILonePair>(); for (int i = 0; i < lonePairCount; i++) { if (lonePairs[i].contains(atom)) lps.add(lonePairs[i]); } return lps; } /** * Returns an array of all SingleElectron connected to the given atom. * *@param atom The atom on which the single electron is located *@return The array of SingleElectron of this AtomContainer */ public List<ISingleElectron> getConnectedSingleElectronsList(IAtom atom) { List<ISingleElectron> lps = new ArrayList<ISingleElectron>(); for (int i = 0; i < singleElectronCount; i++) { if (singleElectrons[i].contains(atom)) lps.add(singleElectrons[i]); } return lps; } /** * Returns an ArrayList of all electronContainers connected to the given atom. * *@param atom The atom the connected electronContainers are searched of *@return The ArrayList with the connected atoms */ public List<IElectronContainer> getConnectedElectronContainersList(IAtom atom) { List<IElectronContainer> lps = new ArrayList<IElectronContainer>(); for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom)) lps.add(bonds[i]); } for (int i = 0; i < lonePairCount; i++) { if (lonePairs[i].contains(atom)) lps.add(lonePairs[i]); } for (int i = 0; i < singleElectronCount; i++) { if (singleElectrons[i].contains(atom)) lps.add(singleElectrons[i]); } return lps; } /** * Returns the number of atoms connected to the given atom. * *@param atom The atom the number of bond partners are searched of. *@return The the size of connected atoms */ public int getConnectedAtomsCount(IAtom atom) { int count = 0; for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom)) ++count; } return count; } /** * Returns the number of Bonds for a given Atom. * *@param atom The atom *@return The number of Bonds for this atom */ public int getConnectedBondsCount(IAtom atom) { return getConnectedAtomsCount(atom); } /** * Returns the number of connected atoms (degree) to the given atom. * *@param atomNumber The atomnumber the degree is searched for *@return The number of connected atoms (degree) */ public int getConnectedBondsCount(int atomNumber) { return getConnectedAtomsCount(atoms[atomNumber]); } /** * Returns the number of LonePairs for a given Atom. * *@param atom The atom *@return The number of LonePairs for this atom */ public int getConnectedLonePairsCount(IAtom atom) { int count = 0; for (int i = 0; i < lonePairCount; i++) { if (lonePairs[i].contains(atom)) ++count; } return count; } /** * Returns the sum of the SingleElectron for a given Atom. * *@param atom The atom on which the single electron is located *@return The array of SingleElectron of this AtomContainer */ public int getConnectedSingleElectronsCount(IAtom atom) { int count = 0; for (int i = 0; i < singleElectronCount; i++) { if (singleElectrons[i].contains(atom)) ++count; } return count; } /** * Returns the sum of the bond orders for a given Atom. * * @param atom The atom * @return The number of bond orders for this atom * * @deprecated Replaced by <code>AtomContainerManipulator#getBondOrderSum(IAtomContainer, IAtom)</code> */ public double getBondOrderSum(IAtom atom) { double count = 0; for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom)) { if (bonds[i].getOrder() == IBond.Order.SINGLE) { count += 1; } else if (bonds[i].getOrder() == IBond.Order.DOUBLE) { count += 2; } else if (bonds[i].getOrder() == IBond.Order.TRIPLE) { count += 3; } else if (bonds[i].getOrder() == IBond.Order.QUADRUPLE) { count += 4; } } } return count; } /** * Returns the maximum bond order that this atom currently has in the context * of this AtomContainer. * * @param atom The atom * @return The maximum bond order that this atom currently has */ public Order getMaximumBondOrder(IAtom atom) { IBond.Order max = IBond.Order.SINGLE; for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom) && bonds[i].getOrder().ordinal() > max.ordinal()) { max = bonds[i].getOrder(); } } return max; } /** * Returns the minimum bond order that this atom currently has in the context * of this AtomContainer. * *@param atom The atom *@return The minimum bond order that this atom currently has */ public Order getMinimumBondOrder(IAtom atom) { IBond.Order min = IBond.Order.QUADRUPLE; for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom) && bonds[i].getOrder().ordinal() < min.ordinal()) { min = bonds[i].getOrder(); } } return min; } /** * Adds all atoms and electronContainers of a given atomcontainer to this * container. * *@param atomContainer The atomcontainer to be added */ public void add(IAtomContainer atomContainer) { for (int f = 0; f < atomContainer.getAtomCount(); f++) { if (!contains(atomContainer.getAtom(f))) { addAtom(atomContainer.getAtom(f)); } } for (int f = 0; f < atomContainer.getBondCount(); f++) { if (!contains(atomContainer.getBond(f))) { addBond(atomContainer.getBond(f)); } } for (int f = 0; f < atomContainer.getLonePairCount(); f++) { if (!contains(atomContainer.getLonePair(f))) { addLonePair(atomContainer.getLonePair(f)); } } for (int f = 0; f < atomContainer.getSingleElectronCount(); f++) { if (!contains(atomContainer.getSingleElectron(f))) { addSingleElectron(atomContainer.getSingleElectron(f)); } } notifyChanged(); } /** * Adds the <code>ElectronContainer</code>s found in atomContainer to this * container. * *@param atomContainer AtomContainer with the new ElectronContainers */ // public void addElectronContainers(IAtomContainer atomContainer) // { // // notifyChanged(); // } /** * Adds an atom to this container. * *@param atom The atom to be added to this container */ public void addAtom(IAtom atom) { if (contains(atom)) { return; } if (atomCount + 1 >= atoms.length) { growAtomArray(); } atom.addListener(this); atoms[atomCount] = atom; atomCount++; notifyChanged(); } /** * Adds a Bond to this AtomContainer. * *@param bond The bond to added to this container */ public void addBond(IBond bond) { if (bondCount >= bonds.length) growBondArray(); bonds[bondCount] = bond; ++bondCount; notifyChanged(); } /** * Adds a lone pair to this AtomContainer. * *@param lonePair The LonePair to added to this container */ public void addLonePair(ILonePair lonePair) { if (lonePairCount >= lonePairs.length) growLonePairArray(); lonePairs[lonePairCount] = lonePair; ++lonePairCount; notifyChanged(); } /** * Adds a single electron to this AtomContainer. * *@param singleElectron The SingleElectron to added to this container */ public void addSingleElectron(ISingleElectron singleElectron) { if (singleElectronCount >= singleElectrons.length) growSingleElectronArray(); singleElectrons[singleElectronCount] = singleElectron; ++singleElectronCount; notifyChanged(); } /** * Adds a ElectronContainer to this AtomContainer. * *@param electronContainer The ElectronContainer to added to this container */ public void addElectronContainer(IElectronContainer electronContainer) { if (electronContainer instanceof IBond) this.addBond((IBond)electronContainer); if (electronContainer instanceof ILonePair) this.addLonePair((ILonePair)electronContainer); if (electronContainer instanceof ISingleElectron) this.addSingleElectron((ISingleElectron)electronContainer); } /** * Removes all atoms and electronContainers of a given atomcontainer from this * container. * *@param atomContainer The atomcontainer to be removed */ public void remove(IAtomContainer atomContainer) { for (int f = 0; f < atomContainer.getAtomCount(); f++) { removeAtom(atomContainer.getAtom(f)); } for (int f = 0; f < atomContainer.getBondCount(); f++) { removeBond(atomContainer.getBond(f)); } for (int f = 0; f < atomContainer.getLonePairCount(); f++) { removeLonePair(atomContainer.getLonePair(f)); } for (int f = 0; f < atomContainer.getSingleElectronCount(); f++) { removeSingleElectron(atomContainer.getSingleElectron(f)); } } /** * Removes the atom at the given position from the AtomContainer. Note that * the electronContainers are unaffected: you also have to take care of * removing all electronContainers to this atom from the container manually. * *@param position The position of the atom to be removed. */ public void removeAtom(int position) { atoms[position].removeListener(this); for (int i = position; i < atomCount - 1; i++) { atoms[i] = atoms[i + 1]; } atoms[atomCount - 1] = null; atomCount--; notifyChanged(); } /** * Removes the given atom from the AtomContainer. Note that the * electronContainers are unaffected: you also have to take care of removing * all electronContainers to this atom from the container. * *@param atom The atom to be removed */ public void removeAtom(IAtom atom) { int position = getAtomNumber(atom); if (position != -1) { removeAtom(position); } } /** * Removes the bond at the given position from the AtomContainer. * *@param position The position of the bond to be removed. */ public IBond removeBond(int position) { IBond bond = bonds[position]; bond.removeListener(this); for (int i = position; i < bondCount - 1; i++) { bonds[i] = bonds[i + 1]; } bonds[bondCount - 1] = null; bondCount--; notifyChanged(); return bond; } /** * Removes the bond that connects the two given atoms. * * @param atom1 The first atom * @param atom2 The second atom * @return The bond that connects the two atoms */ public IBond removeBond(IAtom atom1, IAtom atom2) { int pos = getBondNumber(atom1, atom2); IBond bond = null; if (pos != -1) { bond = bonds[pos]; removeBond(pos); } return bond; } /** * Removes the bond from this container. * * @param bond The bond to be removed. */ public void removeBond(IBond bond) { int pos = getBondNumber(bond); if (pos != -1) removeBond(pos); } /** * Removes the lone pair at the given position from the AtomContainer. * *@param position The position of the LonePair to be removed. */ public ILonePair removeLonePair(int position) { ILonePair lp = lonePairs[position]; lp.removeListener(this); for (int i = position; i < lonePairCount - 1; i++) { lonePairs[i] = lonePairs[i + 1]; } lonePairs[lonePairCount - 1] = null; lonePairCount--; notifyChanged(); return lp; } /** * Removes the lone pair from the AtomContainer. * *@param lonePair The LonePair to be removed. */ public void removeLonePair(ILonePair lonePair) { int pos = getLonePairNumber(lonePair); if (pos != -1) removeLonePair(pos); } /** * Removes the single electron at the given position from the AtomContainer. * *@param position The position of the SingleElectron to be removed. */ public ISingleElectron removeSingleElectron(int position) { ISingleElectron se = singleElectrons[position]; se.removeListener(this); for (int i = position; i < singleElectronCount - 1; i++) { singleElectrons[i] = singleElectrons[i + 1]; } singleElectrons[singleElectronCount - 1] = null; singleElectronCount--; notifyChanged(); return se; } /** * Removes the single electron from the AtomContainer. * *@param singleElectron The SingleElectron to be removed. */ public void removeSingleElectron(ISingleElectron singleElectron) { int pos = getSingleElectronNumber(singleElectron); if (pos != -1) removeSingleElectron(pos); } /** * Removes the bond at the given position from this container. * * @param number The position of the bond in the electronContainers array * @return Bond that was removed */ public IElectronContainer removeElectronContainer(int number) { if (number < this.bondCount) return removeBond(number); number -= this.bondCount; if (number < this.lonePairCount) return removeLonePair(number); number -= this.lonePairCount; if (number < this.singleElectronCount) return removeSingleElectron(number); return null; } /** * Removes this ElectronContainer from this container. * * @param electronContainer The electronContainer to be removed */ public void removeElectronContainer(IElectronContainer electronContainer) { if (electronContainer instanceof IBond) removeBond((IBond) electronContainer); else if (electronContainer instanceof ILonePair) removeLonePair((ILonePair) electronContainer); else if (electronContainer instanceof ISingleElectron) removeSingleElectron((ISingleElectron) electronContainer); } /** * Removes the given atom and all connected electronContainers from the * AtomContainer. * *@param atom The atom to be removed */ public void removeAtomAndConnectedElectronContainers(IAtom atom) { int position = getAtomNumber(atom); if (position != -1) { for (int i = 0; i < bondCount; i++) { if (bonds[i].contains(atom)) { removeBond(i); --i; } } for (int i = 0; i < lonePairCount; i++) { if (lonePairs[i].contains(atom)) { removeLonePair(i); --i; } } for (int i = 0; i < singleElectronCount; i++) { if (singleElectrons[i].contains(atom)) { removeSingleElectron(i); --i; } } removeAtom(position); } notifyChanged(); } /** * Removes all atoms and bond from this container. */ public void removeAllElements() { removeAllElectronContainers(); for (int f = 0; f < getAtomCount(); f++) { getAtom(f).removeListener(this); } atoms = new IAtom[growArraySize]; atomCount = 0; notifyChanged(); } /** * Removes electronContainers from this container. */ public void removeAllElectronContainers() { removeAllBonds(); for (int f = 0; f < getLonePairCount(); f++) { getLonePair(f).removeListener(this); } for (int f = 0; f < getSingleElectronCount(); f++) { getSingleElectron(f).removeListener(this); } lonePairs = new ILonePair[growArraySize]; singleElectrons = new ISingleElectron[growArraySize]; lonePairCount = 0; singleElectronCount = 0; notifyChanged(); } /** * Removes all Bonds from this container. */ public void removeAllBonds() { for (int f = 0; f < getBondCount(); f++) { getBond(f).removeListener(this); } bonds = new IBond[growArraySize]; bondCount = 0; notifyChanged(); } /** * Adds a bond to this container. * *@param atom1 Id of the first atom of the Bond in [0,..] *@param atom2 Id of the second atom of the Bond in [0,..] *@param order Bondorder *@param stereo Stereochemical orientation */ public void addBond(int atom1, int atom2, IBond.Order order, IBond.Stereo stereo) { IBond bond = getBuilder().newBond(getAtom(atom1), getAtom(atom2), order, stereo); if (contains(bond)) { return; } if (bondCount >= bonds.length) { growBondArray(); } addBond(bond); /* no notifyChanged() here because addBond(bond) does it already */ } /** * Adds a bond to this container. * *@param atom1 Id of the first atom of the Bond in [0,..] *@param atom2 Id of the second atom of the Bond in [0,..] *@param order Bondorder */ public void addBond(int atom1, int atom2, IBond.Order order) { IBond bond = getBuilder().newBond(getAtom(atom1), getAtom(atom2), order); if (bondCount >= bonds.length) { growBondArray(); } addBond(bond); /* no notifyChanged() here because addBond(bond) does it already */ } /** * Adds a LonePair to this Atom. * *@param atomID The atom number to which the LonePair is added in [0,..] */ public void addLonePair(int atomID) { ILonePair lonePair = getBuilder().newLonePair(atoms[atomID]); lonePair.addListener(this); addLonePair(lonePair); /* no notifyChanged() here because addElectronContainer() does it already */ } /** * Adds a LonePair to this Atom. * *@param atomID The atom number to which the LonePair is added in [0,..] */ public void addSingleElectron(int atomID) { ISingleElectron singleElectron = getBuilder().newSingleElectron(atoms[atomID]); singleElectron.addListener(this); addSingleElectron(singleElectron); /* no notifyChanged() here because addSingleElectron() does it already */ } /** * True, if the AtomContainer contains the given atom object. * *@param atom the atom this AtomContainer is searched for *@return true if the AtomContainer contains the given atom object */ public boolean contains(IAtom atom) { for (int i = 0; i < getAtomCount(); i++) { if (atom == atoms[i]) return true; } return false; } /** * True, if the AtomContainer contains the given bond object. * *@param bond the bond this AtomContainer is searched for *@return true if the AtomContainer contains the given bond object */ public boolean contains(IBond bond) { for (int i = 0; i < getBondCount(); i++) { if (bond == bonds[i]) return true; } return false; } /** * True, if the AtomContainer contains the given LonePair object. * *@param lonePair the LonePair this AtomContainer is searched for *@return true if the AtomContainer contains the given LonePair object */ public boolean contains(ILonePair lonePair) { for (int i = 0; i < getLonePairCount(); i++) { if (lonePair == lonePairs[i]) return true; } return false; } /** * True, if the AtomContainer contains the given SingleElectron object. * *@param singleElectron the LonePair this AtomContainer is searched for *@return true if the AtomContainer contains the given LonePair object */ public boolean contains(ISingleElectron singleElectron) { for (int i = 0; i < getSingleElectronCount(); i++) { if (singleElectron == singleElectrons[i]) return true; } return false; } /** * True, if the AtomContainer contains the given ElectronContainer object. * *@param electronContainer ElectronContainer that is searched for *@return true if the AtomContainer contains the given bond object */ public boolean contains(IElectronContainer electronContainer) { if (electronContainer instanceof IBond) return contains((IBond)electronContainer); if (electronContainer instanceof ILonePair) return contains((ILonePair)electronContainer); if (electronContainer instanceof ISingleElectron) return contains((SingleElectron)electronContainer); return false; } /** * Returns a one line string representation of this Container. This method is * conform RFC #9. * *@return The string representation of this Container */ public String toString() { StringBuffer stringContent = new StringBuffer(64); stringContent.append("AtomContainer("); stringContent.append(this.hashCode()); if (getAtomCount() > 0) { stringContent.append(", #A:").append(getAtomCount()); for (int i = 0; i < getAtomCount(); i++) { stringContent.append(", ").append(getAtom(i).toString()); } } if (getBondCount() > 0) { stringContent.append(", #B:").append(getBondCount()); for (int i = 0; i < getBondCount(); i++) { stringContent.append(", ").append(getBond(i).toString()); } } if (getLonePairCount() > 0) { stringContent.append(", #LP:").append(getLonePairCount()); for (int i = 0; i < getLonePairCount(); i++) { stringContent.append(", ").append(getLonePair(i).toString()); } } if (getSingleElectronCount() > 0) { stringContent.append(", #SE:").append(getSingleElectronCount()); for (int i = 0; i < getSingleElectronCount(); i++) { stringContent.append(", ").append(getSingleElectron(i).toString()); } } if (atomParities.size() > 0) { stringContent.append(", AP:[#").append(atomParities.size()); for (IAtomParity iAtomParity : atomParities.values()) { stringContent.append(", ").append(iAtomParity.toString()); } stringContent.append(']'); } stringContent.append(')'); return stringContent.toString(); } /** * Clones this AtomContainer object and its content. * * @return The cloned object * @see #shallowCopy */ public Object clone() throws CloneNotSupportedException { IAtom[] newAtoms; IAtomContainer clone = (IAtomContainer) super.clone(); // start from scratch clone.removeAllElements(); // clone all atoms for (int f = 0; f < getAtomCount(); f++) { clone.addAtom((Atom) getAtom(f).clone()); } // clone bonds IBond bond; IBond newBond; for (int i = 0; i < getBondCount(); ++i) { bond = getBond(i); newBond = (IBond)bond.clone(); 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); } 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); } ISingleElectron se; ISingleElectron newSe; for (int i = 0; i < getSingleElectronCount(); ++i) { se = getSingleElectron(i); newSe = (ISingleElectron)se.clone(); newSe.setAtom(clone.getAtom(getAtomNumber(se.getAtom()))); clone.addSingleElectron(newSe); } // for (int f = 0; f < getElectronContainerCount(); f++) { // electronContainer = this.getElectronContainer(f); // newEC = getBuilder().newElectronContainer(); // if (electronContainer instanceof IBond) { // IBond bond = (IBond) electronContainer; // newEC = (IElectronContainer)bond.clone(); // newAtoms = new IAtom[bond.getAtomCount()]; // for (int g = 0; g < bond.getAtomCount(); g++) { // newAtoms[g] = clone.getAtom(getAtomNumber(bond.getAtom(g))); // } // ((IBond) newEC).setAtoms(newAtoms); // } else if (electronContainer instanceof ILonePair) { // IAtom atom = ((ILonePair) electronContainer).getAtom(); // newEC = (ILonePair)electronContainer.clone(); // ((ILonePair) newEC).setAtom(clone.getAtom(getAtomNumber(atom))); // } else if (electronContainer instanceof ISingleElectron) { // IAtom atom = ((ISingleElectron) electronContainer).getAtom(); // newEC = (ISingleElectron)electronContainer.clone(); // ((ISingleElectron) newEC).setAtom(clone.getAtom(getAtomNumber(atom))); // } else { // //logger.debug("Expecting EC, got: " + electronContainer.getClass().getName()); // newEC = (IElectronContainer) electronContainer.clone(); // } // clone.addElectronContainer(newEC); // } return clone; } /** * Grows the ElectronContainer array by a given size. * *@see #growArraySize */ // protected void growElectronContainerArray() // { // growArraySize = (electronContainers.length < growArraySize) ? growArraySize : electronContainers.length; // IElectronContainer[] newelectronContainers = new IElectronContainer[electronContainers.length + growArraySize]; // System.arraycopy(electronContainers, 0, newelectronContainers, 0, electronContainers.length); // electronContainers = newelectronContainers; // } /** * Grows the atom array by a given size. * *@see #growArraySize */ private void growAtomArray() { growArraySize = (atoms.length < growArraySize) ? growArraySize : atoms.length; IAtom[] newatoms = new IAtom[atoms.length + growArraySize]; System.arraycopy(atoms, 0, newatoms, 0, atoms.length); atoms = newatoms; } /** * Grows the bond array by a given size. * *@see #growArraySize */ private void growBondArray() { growArraySize = (bonds.length < growArraySize) ? growArraySize : bonds.length; IBond[] newBonds = new IBond[bonds.length + growArraySize]; System.arraycopy(bonds, 0, newBonds, 0, bonds.length); bonds = newBonds; } /** * Grows the lone pair array by a given size. * *@see #growArraySize */ private void growLonePairArray() { growArraySize = (lonePairs.length < growArraySize) ? growArraySize : lonePairs.length; ILonePair[] newLonePairs = new ILonePair[lonePairs.length + growArraySize]; System.arraycopy(lonePairs, 0, newLonePairs, 0, lonePairs.length); lonePairs = newLonePairs; } /** * Grows the single electron array by a given size. * *@see #growArraySize */ private void growSingleElectronArray() { growArraySize = (singleElectrons.length < growArraySize) ? growArraySize : singleElectrons.length; ISingleElectron[] newSingleElectrons = new ISingleElectron[singleElectrons.length + growArraySize]; System.arraycopy(singleElectrons, 0, newSingleElectrons, 0, singleElectrons.length); singleElectrons = newSingleElectrons; } /** * Called by objects to which this object has * registered as a listener. * *@param event A change event pointing to the source of the change */ public void stateChanged(IChemObjectChangeEvent event) { notifyChanged(event); } }