diff --git a/base/core/src/main/java/org/openscience/cdk/config/AtomTypeFactory.java b/base/core/src/main/java/org/openscience/cdk/config/AtomTypeFactory.java index caa8ba8304c..23f16a3974a 100644 --- a/base/core/src/main/java/org/openscience/cdk/config/AtomTypeFactory.java +++ b/base/core/src/main/java/org/openscience/cdk/config/AtomTypeFactory.java @@ -22,6 +22,7 @@ import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; @@ -93,7 +94,7 @@ public class AtomTypeFactory { private static ILoggingTool logger = LoggingToolFactory .createLoggingTool(AtomTypeFactory.class); private static Map tables = null; - private List atomTypes = null; + private Map atomTypes = null; /** * Private constructor for the AtomTypeFactory singleton. @@ -101,7 +102,7 @@ public class AtomTypeFactory { * */ private AtomTypeFactory(String configFile, IChemObjectBuilder builder) { - atomTypes = new ArrayList(100); + atomTypes = new HashMap(100); readConfiguration(configFile, builder); } @@ -110,7 +111,7 @@ private AtomTypeFactory(String configFile, IChemObjectBuilder builder) { * */ private AtomTypeFactory(InputStream ins, String format, IChemObjectBuilder builder) { - atomTypes = new ArrayList(100); + atomTypes = new HashMap(100); readConfiguration(ins, format, builder); } @@ -231,14 +232,17 @@ private void readConfiguration(InputStream ins, String format, IChemObjectBuilde if (atc != null) { atc.setInputStream(ins); try { - atomTypes = atc.readAtomTypes(builder); + List readAtomTypes = atc.readAtomTypes(builder); + for (IAtomType type : readAtomTypes) { + atomTypes.put(type.getAtomTypeName(), new ImmutableAtomType(type)); + } } 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(); + atomTypes = new HashMap(); } } @@ -259,11 +263,8 @@ public int getSize() { * @exception NoSuchAtomTypeException Thrown if the atom type does not exist. */ public IAtomType getAtomType(String identifier) throws NoSuchAtomTypeException { - for (IAtomType atomType : atomTypes) { - if (atomType.getAtomTypeName().equals(identifier)) { - return atomType; - } - } + IAtomType type = atomTypes.get(identifier); + if (type != null) return type; throw new NoSuchAtomTypeException("The AtomType " + identifier + " could not be found"); } @@ -278,18 +279,10 @@ public IAtomType getAtomType(String identifier) throws NoSuchAtomTypeException { public IAtomType[] getAtomTypes(String symbol) { logger.debug("Request for atomtype for symbol ", symbol); List atomList = new ArrayList(); - for (IAtomType atomType : atomTypes) { + for (IAtomType atomType : atomTypes.values()) { // 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); - } + atomList.add(atomType); } } IAtomType[] atomTypes = (IAtomType[]) atomList.toArray(new IAtomType[atomList.size()]); @@ -307,18 +300,7 @@ public IAtomType[] getAtomTypes(String symbol) { */ public IAtomType[] getAllAtomTypes() { logger.debug("Returning list of size: ", getSize()); - List atomtypeList = new ArrayList(); - 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()]); + return (IAtomType[]) atomTypes.values().toArray(new IAtomType[atomTypes.size()]); } /** diff --git a/base/core/src/main/java/org/openscience/cdk/config/ImmutableAtomType.java b/base/core/src/main/java/org/openscience/cdk/config/ImmutableAtomType.java new file mode 100644 index 00000000000..9628743477d --- /dev/null +++ b/base/core/src/main/java/org/openscience/cdk/config/ImmutableAtomType.java @@ -0,0 +1,302 @@ +/* Copyright (C) 2012-2015 Egon Willighagen + * 2012-2014 John May + * + * 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.config; + +import java.util.Collections; +import java.util.Map; + +import org.openscience.cdk.CDKConstants; +import org.openscience.cdk.interfaces.IAtomType; +import org.openscience.cdk.interfaces.IBond; +import org.openscience.cdk.interfaces.IBond.Order; +import org.openscience.cdk.interfaces.IChemObjectBuilder; +import org.openscience.cdk.interfaces.IChemObjectChangeEvent; +import org.openscience.cdk.interfaces.IChemObjectListener; + +/** + * An immutable {@link IAtomType} implementation to support the {@link AtomTypeFactory}. + * + * @author egonw + */ +public final class ImmutableAtomType implements IAtomType { + + private String element; + private Integer atomicNumber; + private Double naturalAbundance; + private Double exactMass; + private Integer massNumber; + private Integer formalCharge; + private IAtomType.Hybridization hybridization; + private Integer electronValency; + private Integer formalNeighbourCount; + private String identifier; + private IBond.Order maxBondOrder; + private Double bondOrderSum; + private Double covalentRadius; + private short flags; + private Map properties; + + protected ImmutableAtomType(IAtomType type) { + this.element = type.getSymbol(); + this.atomicNumber = type.getAtomicNumber(); + this.naturalAbundance = type.getNaturalAbundance(); + this.exactMass = type.getExactMass(); + this.massNumber = type.getMassNumber(); + this.formalCharge = type.getFormalCharge(); + this.hybridization = type.getHybridization(); + this.electronValency = type.getValency(); + this.formalNeighbourCount = type.getFormalNeighbourCount(); + this.identifier = type.getAtomTypeName(); + this.maxBondOrder = type.getMaxBondOrder(); + this.bondOrderSum = type.getBondOrderSum(); + this.covalentRadius = type.getCovalentRadius(); + this.flags = (short)type.getFlagValue(); + this.properties = Collections.unmodifiableMap(type.getProperties()); + } + + // ignored methods + + @Override + public void addListener(IChemObjectListener col) {} + + @Override + public int getListenerCount() { + return 0; + } + + @Override + public void removeListener(IChemObjectListener col) {} + + @Override + public void setNotification(boolean bool) {} + + @Override + public boolean getNotification() { + return false; + } + + @Override + public void notifyChanged() {} + + @Override + public void notifyChanged(IChemObjectChangeEvent evt) {} + + // unsupported methods + + @Override + public Number getFlagValue() { + return (short) 0; + } + + @Override + public void setProperty(Object description, Object property) {} + + @Override + public void removeProperty(Object description) {} + + @Override + public T getProperty(Object description) { + if (!properties.containsKey(description)) return null; + @SuppressWarnings("unchecked") + T value = (T) properties.get(description); + return value; + } + + @Override + public T getProperty(Object description, Class c) { + Object value = properties.get(description); + + if (c.isInstance(value)) { + + @SuppressWarnings("unchecked") + T typed = (T) value; + return typed; + + } else if (value != null) { + throw new IllegalArgumentException("attempted to access a property of incorrect type, expected " + + c.getSimpleName() + " got " + value.getClass().getSimpleName()); + } + + return null; + } + + @Override + public Map getProperties() { + return properties; + } + + @Override + public String getID() { + return null; + } + + @Override + public void setID(String identifier) {} + + @Override + public void setFlag(int flagType, boolean flagValue) {} + + @Override + public boolean getFlag(int flagType) { + return (flags & flagType) != 0; + } + + @Override + public void setProperties(Map properties) {} + + @Override + public void addProperties(Map properties) {} + + @Override + public void setFlags(boolean[] flagsNew) {} + + @Override + public boolean[] getFlags() { + // could use a list a invoke .toArray() on the return + boolean[] flagArray = new boolean[CDKConstants.MAX_FLAG_INDEX + 1]; + for (int i = 0; i < CDKConstants.FLAG_MASKS.length; i++) { + int mask = CDKConstants.FLAG_MASKS[i]; + flagArray[i] = getFlag(mask); + } + return flagArray; + + } + + @Override + public IChemObjectBuilder getBuilder() { + return null; + } + + @Override + public void setAtomicNumber(Integer atomicNumber) {} + + @Override + public void setSymbol(String symbol) {} + + @Override + public void setExactMass(Double exactMass) {} + + @Override + public void setNaturalAbundance(Double naturalAbundance) {} + + @Override + public void setMassNumber(Integer massNumber) {} + + // implemented methods + + @Override + public String getSymbol() { + return element; + } + + @Override + public Integer getAtomicNumber() { + return atomicNumber; + } + + @Override + public Double getNaturalAbundance() { + return naturalAbundance; + } + + @Override + public Double getExactMass() { + return exactMass; + }; + + @Override + public Integer getMassNumber() { + return massNumber; + } + + @Override + public Object clone() { + return this; + } + + @Override + public void setAtomTypeName(String identifier) {} + + @Override + public void setMaxBondOrder(Order maxBondOrder) {} + + @Override + public void setBondOrderSum(Double bondOrderSum) {} + + @Override + public String getAtomTypeName() { + return this.identifier; + } + + @Override + public Order getMaxBondOrder() { + return this.maxBondOrder; + } + + @Override + public Double getBondOrderSum() { + return this.bondOrderSum; + } + + @Override + public void setFormalCharge(Integer charge) {} + + @Override + public Integer getFormalCharge() { + return this.formalCharge; + } + + @Override + public void setFormalNeighbourCount(Integer count) {} + + @Override + public Integer getFormalNeighbourCount() { + return this.formalNeighbourCount; + } + + @Override + public void setHybridization(Hybridization hybridization) {} + + @Override + public Hybridization getHybridization() { + return this.hybridization; + } + + @Override + public void setCovalentRadius(Double radius) {} + + @Override + public Double getCovalentRadius() { + return this.covalentRadius; + } + + @Override + public void setValency(Integer valency) {} + + @Override + public Integer getValency() { + return this.electronValency; + } + +}