/* $Revision$ $Author$ $Date$ * * Copyright (C) 2005-2007 Egon Willighagen <egonw@sci.kun.nl> * * 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.io.iterator.event; import java.util.Hashtable; import java.util.Map; import javax.vecmath.Point2d; import javax.vecmath.Point3d; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IChemObjectBuilder; import org.openscience.cdk.interfaces.IPseudoAtom; import org.openscience.cdk.io.cml.CMLHandler; import org.openscience.cdk.tools.ILoggingTool; import org.openscience.cdk.tools.LoggingToolFactory; /** * CDO object needed as interface with the JCFL library for reading CML * in a event based manner. * * <p>The CDO only takes care about atoms, bonds and molecules. * * @cdk.module io * @cdk.githash * * @author Egon Willighagen <egonw@sci.kun.nl> */ public class EventCMLHandler extends CMLHandler { private IChemObjectBuilder builder; private IAtomContainer currentMolecule; private IAtom currentAtom; private Map<String,Integer> atomEnumeration; private int numberOfAtoms = 0; private int bond_a1; private int bond_a2; private IBond.Order bond_order; private IBond.Stereo bond_stereo; private String bond_id; protected static ILoggingTool logger = LoggingToolFactory.createLoggingTool(EventCMLHandler.class); private DefaultEventChemObjectReader eventReader; /** * Constructs an iterating-abled CDO. After reading one molecule it * fires a frameRead event. */ public EventCMLHandler(DefaultEventChemObjectReader eventReader, IChemObjectBuilder builder) { super(builder.newChemFile()); this.eventReader = eventReader; this.builder = builder; clearData(); } private void clearData() { currentMolecule = null; atomEnumeration = null; currentAtom = null; } public IAtomContainer getAtomContainer() { return currentMolecule; } // procedures required by CDOInterface /** * Procedure required by the CDOInterface. This function is only * supposed to be called by the JCFL library */ public void startDocument() { logger.info("New CDO Object"); } /** * Procedure required by the CDOInterface. This function is only * supposed to be called by the JCFL library */ public void endDocument() { logger.debug("Closing document"); logger.info("End CDO Object"); } /** * Procedure required by the CDOInterface. This function is only * supposed to be called by the JCFL library */ public void setDocumentProperty(String type, String value) {} /** * Procedure required by the CDOInterface. This function is only * supposed to be called by the JCFL library */ public void startObject(String objectType) { logger.debug("START:" + objectType); if (objectType.equals("Molecule")) { currentMolecule = builder.newAtomContainer(); atomEnumeration = new Hashtable<String,Integer>(); } else if (objectType.equals("Atom")) { currentAtom = builder.newAtom("H"); logger.debug("Atom # " + numberOfAtoms); numberOfAtoms++; } else if (objectType.equals("Bond")) { bond_id = null; bond_stereo = (IBond.Stereo)CDKConstants.UNSET; } } /** * Procedure required by the CDOInterface. This function is only * supposed to be called by the JCFL library */ public void endObject(String objectType) { logger.debug("END: " + objectType); if (objectType.equals("Molecule")) { eventReader.fireFrameRead(); clearData(); } else if (objectType.equals("Atom")) { currentMolecule.addAtom(currentAtom); } else if (objectType.equals("Bond")) { logger.debug("Bond(" + bond_id + "): " + bond_a1 + ", " + bond_a2 + ", " + bond_order); if (bond_a1 > currentMolecule.getAtomCount() || bond_a2 > currentMolecule.getAtomCount()) { logger.error("Cannot add bond between at least one non-existant atom: " + bond_a1 + " and " + bond_a2); } else { IAtom a1 = currentMolecule.getAtom(bond_a1); IAtom a2 = currentMolecule.getAtom(bond_a2); IBond b = builder.newBond(a1, a2, bond_order); if (bond_id != null) b.setID(bond_id); if (bond_stereo != CDKConstants.UNSET) { b.setStereo(bond_stereo); } currentMolecule.addBond(b); } } } /** * Procedure required by the CDOInterface. This function is only * supposed to be called by the JCFL library */ public void setObjectProperty(String objectType, String propertyType, String propertyValue) { logger.debug("objectType: " + objectType); logger.debug("propType: " + propertyType); logger.debug("property: " + propertyValue); if (objectType == null) { logger.error("Cannot add property for null object"); return; } if (propertyType == null) { logger.error("Cannot add property for null property type"); return; } if (propertyValue == null) { logger.warn("Will not add null property"); return; } if (objectType.equals("Molecule")) { if (propertyType.equals("id")) { currentMolecule.setID(propertyValue); } else if (propertyType.equals("inchi")) { currentMolecule.setProperty("iupac.nist.chemical.identifier", propertyValue); } } else if (objectType.equals("PseudoAtom")) { if (propertyType.equals("label")) { if (!(currentAtom instanceof IPseudoAtom)) { currentAtom = builder.newPseudoAtom(currentAtom); } ((IPseudoAtom)currentAtom).setLabel(propertyValue); } } else if (objectType.equals("Atom")) { if (propertyType.equals("type")) { if (propertyValue.equals("R") && !(currentAtom instanceof IPseudoAtom)) { currentAtom = builder.newPseudoAtom(currentAtom); } currentAtom.setSymbol(propertyValue); } else if (propertyType.equals("x2")) { Point2d coord = currentAtom.getPoint2d(); if (coord == null) coord = new Point2d(); coord.x = Double.parseDouble(propertyValue); currentAtom.setPoint2d(coord); } else if (propertyType.equals("y2")) { Point2d coord = currentAtom.getPoint2d(); if (coord == null) coord = new Point2d(); coord.y = Double.parseDouble(propertyValue); currentAtom.setPoint2d(coord); } else if (propertyType.equals("x3")) { Point3d coord = currentAtom.getPoint3d(); if (coord == null) coord = new Point3d(); coord.x = Double.parseDouble(propertyValue); currentAtom.setPoint3d(coord); } else if (propertyType.equals("y3")) { Point3d coord = currentAtom.getPoint3d(); if (coord == null) coord = new Point3d(); coord.y = Double.parseDouble(propertyValue); currentAtom.setPoint3d(coord); } else if (propertyType.equals("z3")) { Point3d coord = currentAtom.getPoint3d(); if (coord == null) coord = new Point3d(); coord.z = Double.parseDouble(propertyValue); currentAtom.setPoint3d(coord); } else if (propertyType.equals("xFract")) { Point3d coord = currentAtom.getFractionalPoint3d(); if (coord == null) coord = new Point3d(); coord.x = Double.parseDouble(propertyValue); currentAtom.setFractionalPoint3d(coord); } else if (propertyType.equals("yFract")) { Point3d coord = currentAtom.getFractionalPoint3d(); if (coord == null) coord = new Point3d(); coord.y = Double.parseDouble(propertyValue); currentAtom.setFractionalPoint3d(coord); } else if (propertyType.equals("zFract")) { Point3d coord = currentAtom.getFractionalPoint3d(); if (coord == null) coord = new Point3d(); coord.z = Double.parseDouble(propertyValue); currentAtom.setFractionalPoint3d(coord); } else if (propertyType.equals("formalCharge")) { currentAtom.setFormalCharge(Integer.parseInt(propertyValue)); } else if (propertyType.equals("charge") || propertyType.equals("partialCharge")) { currentAtom.setCharge(Double.parseDouble(propertyValue)); } else if (propertyType.equals("hydrogenCount")) { currentAtom.setHydrogenCount(Integer.parseInt(propertyValue)); } else if (propertyType.equals("dictRef")) { currentAtom.setProperty("org.openscience.cdk.dict", propertyValue); } else if (propertyType.equals("atomicNumber")) { currentAtom.setAtomicNumber(Integer.parseInt(propertyValue)); } else if (propertyType.equals("massNumber")) { currentAtom.setMassNumber((int)Double.parseDouble(propertyValue)); } else if (propertyType.equals("id")) { logger.debug("id: ", propertyValue); currentAtom.setID(propertyValue); atomEnumeration.put(propertyValue, numberOfAtoms); } } else if (objectType.equals("Bond")) { if (propertyType.equals("atom1")) { bond_a1 = Integer.parseInt(propertyValue); } else if (propertyType.equals("atom2")) { bond_a2 = Integer.parseInt(propertyValue); } else if (propertyType.equals("id")) { logger.debug("id: " + propertyValue); bond_id = propertyValue; } else if (propertyType.equals("order")) { try { Double order = Double.parseDouble(propertyValue); if (order == 1.0) { bond_order = IBond.Order.SINGLE; } else if (order == 2.0) { bond_order = IBond.Order.DOUBLE; } else if (order == 3.0) { bond_order = IBond.Order.TRIPLE; } else if (order == 4.0) { bond_order = IBond.Order.QUADRUPLE; } else { bond_order = IBond.Order.SINGLE; } } catch (Exception e) { logger.error("Cannot convert to double: " + propertyValue); bond_order = IBond.Order.SINGLE; } } else if (propertyType.equals("stereo")) { if (propertyValue.equals("H")) { bond_stereo = IBond.Stereo.DOWN; } else if (propertyValue.equals("W")) { bond_stereo = IBond.Stereo.UP; } } } logger.debug("Object property set..."); } }