package org.openscience.cdk.io.iterator;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.ConformerContainer;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.interfaces.IMolecule;
import java.io.InputStream;
import java.io.Reader;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Iterate over conformers of a collection of molecules stored in SDF format.
* <p/>
* This class is analogous to the {@link org.openscience.cdk.io.iterator.IteratingMDLReader} except that
* rather than return a single {@link org.openscience.cdk.interfaces.IMolecule} at each iteration this
* class will return all the conformers for a given molecule at each iteration.
* <p/>
* The class assumes that the molecules are stored in SDF format and that all conformers for a given
* molecule are in sequential order.
* <p/>
* Currently, the code uses the title of each molecule in the SD file to perform te conformer check
* and so it is important that all conformers for a given molecule have the same title field, but
* different from the title fields of conformers of other molecules. In
* the future the class will allow the user to perform the check using either the title or a more
* rigorous (but more time-consuming) graph isomorphism check.
* <p/>
* Example usage is
* <pre>
* String filename = "/Users/rguha/conf2.sdf";
* IteratingMDLConformerReader2 reader = new IteratingMDLConformerReader2(
* new FileReader(new File(filename)), DefaultChemObjectBuilder.getInstance());
* while (reader.hasNext()) {
* ConformerContainer2 cc = (ConformerContainer2) reader.next();
* }
* <p/>
* // do something with this set of conformers
* <p/>
* </pre>
*
* @cdk.module extra
* @cdk.githash
* @author Rajarshi Guha
* @see org.openscience.cdk.ConformerContainer
* @cdk.keyword file format SDF
* @cdk.keyword conformer conformation
*/
@TestClass("org.openscience.cdk.io.iterator.IteratingMDLConformerReaderTest")
public class IteratingMDLConformerReader implements Iterator {
private IteratingMDLReader imdlr;
private ConformerContainer container;
private IMolecule lastMol = null;
private boolean hasNext = false;
private boolean nextIsKnown = false;
@TestMethod("testSDF")
public IteratingMDLConformerReader(Reader in, IChemObjectBuilder builder) {
imdlr = new IteratingMDLReader(in, builder);
container = new ConformerContainer();
}
@TestMethod("testSDF")
public IteratingMDLConformerReader(InputStream in, IChemObjectBuilder builder) {
imdlr = new IteratingMDLReader(in, builder);
container = new ConformerContainer();
}
@TestMethod("testSDF")
public boolean hasNext() {
boolean slurpedConformers = false;
if (lastMol != null)
container = new ConformerContainer(lastMol);
if (!nextIsKnown) {
while (imdlr.hasNext()) {
slurpedConformers = true;
IMolecule mol = (IMolecule) imdlr.next();
if (container.size() == 0) container.add(mol);
else {
if (container.getTitle().equals(mol.getProperty(CDKConstants.TITLE))) container.add(mol);
else {
lastMol = mol;
hasNext = true;
break;
}
}
}
hasNext = container.size() > 0 && slurpedConformers;
}
if (!hasNext) container = null;
nextIsKnown = true;
return hasNext;
}
@TestMethod("testSDF")
public Object next() {
if (!nextIsKnown) hasNext();
nextIsKnown = false;
if (!hasNext) throw new NoSuchElementException();
return container; //To change body of implemented methods use File | Settings | File Templates.
}
@TestMethod("testRemove")
public void remove() {
throw new UnsupportedOperationException();
}
}