Logo Search packages:      
Sourcecode: cdk version File versions  Download package

AtomTypeFactory.java

/* $Revision$ $Author$ $Date$
 *
 *  Copyright (C) 2001-2007  Christoph Steinbeck <steinbeck@users.sf.net>
 *
 *  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.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.exception.NoSuchAtomTypeException;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomType;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.interfaces.IPseudoAtom;
import org.openscience.cdk.tools.LoggingTool;

/**
 *  General class for defining AtomTypes. This class itself does not define the
 *  items types; for this classes implementing the AtomTypeConfiguration
 *  interface are used.
 *
 *  <p>To see which AtomTypeConfigurator's CDK provides, one should check the
 *  AtomTypeConfigurator API.
 *
 *  <p>The AtomTypeFactory is a singleton class, which means that there exists
 *  only one instance of the class. Well, almost. For each atom type table,
 *  there is one AtomTypeFactory instance. An instance of this class is
 *  obtained with:
 *  <pre>
 *  AtomTypeFactory factory = AtomTypeFactory.getInstance(someChemObjectBuilder);
 *  </pre>
 *  For each atom type list a separate AtomTypeFactory is instantiated.
 *
 *  <p>To get all the atom types of an element from a specific list, this 
 *  code can be used:
 *  <pre>
 *  AtomTypeFactory factory = AtomTypeFactory.getInstance(
 *    "org/openscience/cdk/config/data/jmol_atomtypes.txt",
      someChemObjectBuilder
 *  );
 *  AtomType[] types = factory.getAtomTypes("C");
 *  </pre>
 *
 * @cdk.module core
 * @cdk.githash
 *
 * @author     steinbeck
 * @cdk.created    2001-08-29
 * @cdk.keyword    atom, type
 * @see        IAtomTypeConfigurator
 */
@TestClass("org.openscience.cdk.config.AtomTypeFactoryTest")
00077 public class AtomTypeFactory {

    /**
     *  Used as an ID to describe the atom type.
     */
00082     public final static String ATOMTYPE_ID_STRUCTGEN = "structgen";
    /**
     *  Used as an ID to describe the atom type.
     */
00086     public final static String ATOMTYPE_ID_MODELING = "modeling";
    // these are not available
    /**
     *  Used as an ID to describe the atom type.
     */
00091     public final static String ATOMTYPE_ID_JMOL = "jmol";
    
    private final static String TXT_EXTENSION = "txt";
    private final static String XML_EXTENSION = "xml";
    private final static String OWL_EXTENSION = "owl";
    
    private static LoggingTool logger;
    private static Map<String, AtomTypeFactory> tables = null;
    private List<IAtomType> atomTypes = null;

      /**
       * Private constructor for the AtomTypeFactory singleton.
       *
       *
       */
00106     private AtomTypeFactory(String configFile, IChemObjectBuilder builder) {
        if (logger == null) {
            logger = new LoggingTool(this);
        }
        atomTypes = new ArrayList<IAtomType>(100);
        readConfiguration(configFile, builder);
    }

      /**
       * Private constructor for the AtomTypeFactory singleton.
       *
       */
00118     private AtomTypeFactory(InputStream ins, String format, IChemObjectBuilder builder) {
        if (logger == null) {
            logger = new LoggingTool(this);
        }
        atomTypes = new ArrayList<IAtomType>(100);
        readConfiguration(ins, format, builder);
    }

    /**
     * Method to create a default AtomTypeFactory, using the given InputStream.
     * An AtomType of this kind is not cached.
     *
     * @see #getInstance(String, IChemObjectBuilder)
     * @param  ins                    InputStream containing the data
     * @param  format                 String representing the possible formats ('xml' and 'txt')
     * @param  builder                IChemObjectBuilder used to make IChemObject instances
     * @return                        The AtomTypeFactory for the given data file
     */
    @TestMethod("testGetInstance_InputStream_String_IChemObjectBuilder")
00137     public static AtomTypeFactory getInstance(InputStream ins, String format, IChemObjectBuilder builder) {
        return new AtomTypeFactory(ins, format, builder);
    }

    /**
     * Method to create a default AtomTypeFactory, using the structgen atom type list.
     *
     * @see #getInstance(String, IChemObjectBuilder)
     * @param  builder                IChemObjectBuilder used to make IChemObject instances
     * @return                        The AtomTypeFactory for the given data file
     */
    @TestMethod("testGetInstance_IChemObjectBuilder")
00149     public static AtomTypeFactory getInstance(IChemObjectBuilder builder) {
        return getInstance("org/openscience/cdk/config/data/structgen_atomtypes.xml", builder);
    }

    /**
     * Method to create a specialized AtomTypeFactory. Available lists in CDK are:
     * <ul>
     *  <li>org/openscience/cdk/config/data/jmol_atomtypes.txt
     *  <li>org/openscience/cdk/config/data/mol2_atomtypes.xml
     *  <li>org/openscience/cdk/config/data/structgen_atomtypes.xml
     *  <li>org/openscience/cdk/config/data/mm2_atomtypes.xml
     *  <li>org/openscience/cdk/config/data/mmff94_atomtypes.xml
     *  <li>org/openscience/cdk/dict/data/cdk-atom-types.owl
     *  <li>org/openscience/cdk/dict/data/sybyl-atom-types.owl
     * </ul>
     *
     * @param  configFile             String the name of the data file
     * @param  builder                IChemObjectBuilder used to make IChemObject instances
     * @return                        The AtomTypeFactory for the given data file
     */
    @TestMethod("testGetInstance_String_IChemObjectBuilder")
00170     public static AtomTypeFactory getInstance(String configFile, IChemObjectBuilder builder) {
        if (tables == null) {
            tables = new Hashtable<String, AtomTypeFactory>();
        }
        if (!(tables.containsKey(configFile))) {
            tables.put(configFile, new AtomTypeFactory(configFile, builder));
        }
        return tables.get(configFile);
    }

      /**
       * Read the config from a text file.
       *
       * @param  fileName  name of the config file
     * @param  builder     IChemObjectBuilder used to make IChemObject instances
       */
00186       private void readConfiguration(String fileName, IChemObjectBuilder builder)
      {
            logger.info("Reading config file from ", fileName);

            InputStream ins;
            {
                  //try to see if this is a resource
                  ins = this.getClass().getClassLoader().getResourceAsStream(fileName);
                  if(ins==null){
                        // try to see if this configFile is an actual file
                        File file = new File(fileName);
                  if (file.exists()) {
                      logger.debug("configFile is a File");
                      // what's next?
                      try {
                          ins = new FileInputStream(file);
                      } catch (Exception exception) {
                          logger.error(exception.getMessage());
                          logger.debug(exception);
                      }
                  } else {
                        logger.error("no stream and no file");
                  }
            }
            }

        String format = XML_EXTENSION;
        if (fileName.endsWith(TXT_EXTENSION)) {
            format = TXT_EXTENSION;
        } else if (fileName.endsWith(XML_EXTENSION)) {
            format = XML_EXTENSION;
        } else if (fileName.endsWith(OWL_EXTENSION)) {
            format = OWL_EXTENSION;
        }
        readConfiguration(ins, format, builder);
    }
    
    private IAtomTypeConfigurator constructConfigurator(String format) {
        try {
            if (format.equals(TXT_EXTENSION)) {
                return (IAtomTypeConfigurator) this.getClass().getClassLoader().
                    loadClass("org.openscience.cdk.config.TXTBasedAtomTypeConfigurator").
                    newInstance();
            } else if (format.equals(XML_EXTENSION)) {
                return (IAtomTypeConfigurator) this.getClass().getClassLoader().
                 loadClass("org.openscience.cdk.config.CDKBasedAtomTypeConfigurator").
                 newInstance();
            } else if (format.equals(OWL_EXTENSION)) {
                return (IAtomTypeConfigurator) this.getClass().getClassLoader().
                 loadClass("org.openscience.cdk.config.OWLBasedAtomTypeConfigurator").
                 newInstance();
            }
            } catch (Exception exc) {
                  logger.error("Could not get instance of AtomTypeConfigurator for format ", format);
            logger.debug(exc);
            }
        return null;
    }
    
    private void readConfiguration(InputStream ins, String format, IChemObjectBuilder builder) {
      IAtomTypeConfigurator atc = constructConfigurator(format);
            if (atc != null) {
                  atc.setInputStream(ins);
                  try
                  {
                        atomTypes = atc.readAtomTypes(builder);
                  } catch (Exception exc)
                  {
                        logger.error("Could not read AtomType's from file due to: ", exc.getMessage());
                logger.debug(exc);
                  }
            } else
            {
                  logger.debug("AtomTypeConfigurator was null!");
                  atomTypes = new ArrayList<IAtomType>();
            }
      }


      /**
       * Returns the number of atom types in this list.
       *
       * @return    The number of atom types
       */
    @TestMethod("testGetSize")
00271     public int getSize()
      {
            return atomTypes.size();
      }


      /**
       * Get an AtomType with the given ID.
       *
       * @param  identifier                   an ID for a particular atom type (like C$)
       * @return                              The AtomType for this id
       * @exception  NoSuchAtomTypeException  Thrown if the atom type does not exist.
       */
    @TestMethod("testGetAtomType_String,testGetAtomTypeFromJmol,testGetAtomTypeFromMM2,testGetAtomTypeFromPDB")
00285     public IAtomType getAtomType(String identifier) throws NoSuchAtomTypeException
      {
        for (IAtomType atomType : atomTypes) {
            if (atomType.getAtomTypeName().equals(identifier)) {
                return atomType;
            }
        }
        throw new NoSuchAtomTypeException("The AtomType " + identifier + " could not be found");
      }


      /**
       * Get an array of all atomTypes known to the AtomTypeFactory for the given
       * element symbol and atomtype class.
       *
       * @param  symbol  An element symbol to search for
       * @return         An array of atomtypes that matches the given element symbol
       *                 and atomtype class
       */
    @TestMethod("testGetAtomTypes_String")
00305     public IAtomType[] getAtomTypes(String symbol)
      {
        logger.debug("Request for atomtype for symbol ", symbol);
        List<IAtomType> atomList = new ArrayList<IAtomType>();
        for (IAtomType atomType : atomTypes) {
            // logger.debug("  does symbol match for: ", atomType);
            if (atomType.getSymbol().equals(symbol)) {
                // logger.debug("Atom type found for symbol: ", atomType);
                IAtomType clone;
                try {
                    clone = (IAtomType) atomType.clone();
                    atomList.add(clone);
                } catch (CloneNotSupportedException e) {
                    logger.error("Could not clone IAtomType: ", e.getMessage());
                    logger.debug(e);
                }
            }
        }
        IAtomType[] atomTypes = (IAtomType[])atomList.toArray(new IAtomType[atomList.size()]);
        if (atomTypes.length > 0)
            logger.debug("Atomtype for symbol ", symbol, " has this number of types: " + atomTypes.length);
        else
            logger.debug("No atomtype for symbol ", symbol);
        return atomTypes;
      }


      /**
       * Gets the allAtomTypes attribute of the AtomTypeFactory object.
       *
       * @return    The allAtomTypes value
       */
    @TestMethod("testGetAllAtomTypes")
00338     public IAtomType[] getAllAtomTypes()
      {
            logger.debug("Returning list of size: ", getSize());
            List<IAtomType> atomtypeList = new ArrayList<IAtomType>();
        for (IAtomType atomType : atomTypes) {
            IAtomType clone;
            try {
                clone = (IAtomType) atomType.clone();
                atomtypeList.add(clone);
            } catch (CloneNotSupportedException e) {
                logger.error("Could not clone IAtomType: ", e.getMessage());
                logger.debug(e);
            }
        }
        return (IAtomType[])atomtypeList.toArray(new IAtomType[atomtypeList.size()]);
      }


      /**
       * Configures an atom. Finds the correct element type by looking at the Atom's
       * atom type name, and if that fails, picks the first atom type matching
     * the Atom's element symbol..
       *
       * @param  atom  The atom to be configured
       * @return       The configured atom
       * @throws       CDKException when it could not recognize and configure the 
       *               IAtom
       */
    @TestMethod("testConfigure_IAtom")
00367     public IAtom configure(IAtom atom) throws CDKException {
        if (atom instanceof IPseudoAtom) {
            // do not try to configure PseudoAtom's
            return atom;
        }
        try {
            IAtomType atomType;
            String atomTypeName = atom.getAtomTypeName();
            if (atomTypeName == null || atomTypeName.length() == 0) {
                logger.debug("Using atom symbol because atom type name is empty...");
                IAtomType[] types = getAtomTypes(atom.getSymbol());
                if (types.length > 0) {
                    logger.warn("Taking first atom type, but other may exist");
                    atomType = types[0];
                } else {
                    String message = "Could not configure atom with unknown ID: " +
                        atom.toString() + " + (id=" + atom.getAtomTypeName() + ")";
                    logger.warn(message);
                    throw new CDKException(message);
                }
            } else {
                atomType = getAtomType(atom.getAtomTypeName());
            }
            logger.debug("Configuring with atomtype: ", atomType);
            atom.setSymbol(atomType.getSymbol());
            atom.setMaxBondOrder(atomType.getMaxBondOrder());
            atom.setBondOrderSum(atomType.getBondOrderSum());
            atom.setCovalentRadius(atomType.getCovalentRadius());
            atom.setHybridization(atomType.getHybridization());
            Object color = atomType.getProperty("org.openscience.cdk.renderer.color");
            if (color != null) {
                atom.setProperty("org.openscience.cdk.renderer.color", color);
            }
            atom.setAtomicNumber(atomType.getAtomicNumber());
            atom.setExactMass(atomType.getExactMass());
        } catch (Exception exception) {
            logger.warn("Could not configure atom with unknown ID: ", atom,
                        " + (id=", atom.getAtomTypeName(), ")");
            logger.debug(exception);
            throw new CDKException(exception.toString(), exception);
        }
        logger.debug("Configured: ", atom);
        return atom;
    }
}


Generated by  Doxygen 1.6.0   Back to index