001package com.hfg.chem;
002
003
004import java.util.ArrayList;
005import java.util.Collections;
006import java.util.List;
007
008import com.hfg.util.CompareUtil;
009
010//------------------------------------------------------------------------------
011/**
012 Represents an atom - an element plus coordinates.
013
014 @author J. Alex Taylor, hairyfatguy.com
015 */
016//------------------------------------------------------------------------------
017// com.hfg XML/HTML Coding Library
018//
019// This library is free software; you can redistribute it and/or
020// modify it under the terms of the GNU Lesser General Public
021// License as published by the Free Software Foundation; either
022// version 2.1 of the License, or (at your option) any later version.
023//
024// This library is distributed in the hope that it will be useful,
025// but WITHOUT ANY WARRANTY; without even the implied warranty of
026// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
027// Lesser General Public License for more details.
028//
029// You should have received a copy of the GNU Lesser General Public
030// License along with this library; if not, write to the Free Software
031// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
032//
033// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
034// jataylor@hairyfatguy.com
035//------------------------------------------------------------------------------
036
037public class Atom implements Comparable
038{
039   private Element mElement;
040   private Float   mXCoordinate;
041   private Float   mYCoordinate;
042   private Float   mZCoordinate;
043
044   private Integer   mCharge;
045   private Boolean   mIsAromatic;
046   private Integer   mHCount;
047   private Integer   mImplicitHCount;
048   private Integer   mAtomClass;
049   private ChiralityOrder mChiralityOrder;
050   private List<CovalentBond> mBonds;
051
052   private final int mId = sIdSrc++;
053
054   private static int sIdSrc = Integer.MIN_VALUE;
055
056   public enum ChiralityOrder
057   {
058      clockwise,
059      anticlockwise
060   }
061
062   //##########################################################################
063   // CONSTRUCTORS
064   //##########################################################################
065
066   //--------------------------------------------------------------------------
067   public Atom(Element inElement)
068   {
069      mElement = inElement;
070   }
071
072   //##########################################################################
073   // PUBLIC METHODS
074   //##########################################################################
075
076   //--------------------------------------------------------------------------
077   @Override
078   public String toString()
079   {
080      return mElement != null ? mElement.getSymbol() : "*";
081   }
082
083   //--------------------------------------------------------------------------
084   @Override
085   public int hashCode()
086   {
087      return mId;
088   }
089
090   //--------------------------------------------------------------------------
091   @Override
092   public boolean equals(Object inObj)
093   {
094      boolean result = false;
095
096      if (inObj != null)
097      {
098         result = (0 == compareTo(inObj));
099      }
100
101      return result;
102   }
103
104   //--------------------------------------------------------------------------
105   @Override
106   public int compareTo(Object inObj)
107   {
108      int result = -1;
109
110      if (inObj instanceof Atom)
111      {
112         result = CompareUtil.compare(mId, ((Atom) inObj).mId);
113      }
114
115      return result;
116   }
117
118   //--------------------------------------------------------------------------
119   public Element getElement()
120   {
121      return mElement;
122   }
123
124
125   //--------------------------------------------------------------------------
126   public Float getXCoordinate()
127   {
128      return mXCoordinate;
129   }
130
131   //--------------------------------------------------------------------------
132   public Atom setXCoordinate(Float inValue)
133   {
134      mXCoordinate = inValue;
135      return this;
136   }
137
138
139   //--------------------------------------------------------------------------
140   public Float getYCoordinate()
141   {
142      return mYCoordinate;
143   }
144
145   //--------------------------------------------------------------------------
146   public Atom setYCoordinate(Float inValue)
147   {
148      mYCoordinate = inValue;
149      return this;
150   }
151
152
153   //--------------------------------------------------------------------------
154   public Float getZCoordinate()
155   {
156      return mZCoordinate;
157   }
158
159   //--------------------------------------------------------------------------
160   public Atom setZCoordinate(Float inValue)
161   {
162      mZCoordinate = inValue;
163      return this;
164   }
165
166
167   //--------------------------------------------------------------------------
168   public Integer getCharge()
169   {
170      return mCharge;
171   }
172
173   //--------------------------------------------------------------------------
174   public Atom setCharge(Integer inValue)
175   {
176      mCharge = inValue != null && inValue != 0 ? inValue : null;
177      return this;
178   }
179
180
181   //--------------------------------------------------------------------------
182   public Atom addBond(CovalentBond inValue)
183   {
184      if (inValue != null)
185      {
186         if (null == mBonds)
187         {
188            mBonds = new ArrayList<>(3);
189         }
190         else
191         {
192            // Has an equivalent bond already been added?
193            for (CovalentBond bond : mBonds)
194            {
195               if (bond.equals(inValue)
196                   && inValue.getSecondAtom() != null)
197               {
198                  throw new MolecularStructureException("There cannot be two bonds between one pair of Atoms!");
199               }
200            }
201         }
202
203         // Make sure that the bond involves this Atom
204         if (inValue.getFirstAtom() != this
205             && inValue.getSecondAtom() != this)
206         {
207            throw new MolecularStructureException("Can't add a bond to an Atom that doesn't involve the Atom!");
208         }
209
210         mBonds.add(inValue);
211      }
212
213      return this;
214   }
215
216   //--------------------------------------------------------------------------
217   public boolean removeBond(CovalentBond inValue)
218   {
219      boolean result = false;
220      if (mBonds != null)
221      {
222         result = mBonds.remove(inValue);
223      }
224
225      return result;
226   }
227
228   //--------------------------------------------------------------------------
229   public List<CovalentBond> getBonds()
230   {
231      return mBonds != null ? Collections.unmodifiableList(mBonds) : null;
232   }
233
234
235   //--------------------------------------------------------------------------
236   public ChiralityOrder getChiralityOrder()
237   {
238      return mChiralityOrder;
239   }
240
241   //--------------------------------------------------------------------------
242   public Atom setChiralityOrder(ChiralityOrder inValue)
243   {
244      mChiralityOrder = inValue;
245      return this;
246   }
247
248
249   //--------------------------------------------------------------------------
250   public Integer getAtomClass()
251   {
252      return mAtomClass;
253   }
254
255   //--------------------------------------------------------------------------
256   public Atom setAtomClass(Integer inValue)
257   {
258      mAtomClass = inValue;
259      return this;
260   }
261
262
263   //--------------------------------------------------------------------------
264   public Atom setIsAromatic(boolean inValue)
265   {
266      mIsAromatic = inValue;
267      return this;
268   }
269
270   //--------------------------------------------------------------------------
271   public boolean isAromatic()
272   {
273      return mIsAromatic != null ? mIsAromatic : false;
274   }
275
276
277   //--------------------------------------------------------------------------
278   public Atom setHCount(Integer inValue)
279   {
280      mHCount = inValue;
281      return this;
282   }
283
284   //--------------------------------------------------------------------------
285   public Integer getHCount()
286   {
287      return mHCount;
288   }
289
290
291   //--------------------------------------------------------------------------
292   public Atom setImplicitHCount(Integer inValue)
293   {
294      mImplicitHCount = inValue;
295      return this;
296   }
297
298   //--------------------------------------------------------------------------
299   public Integer getImplicitHCount()
300   {
301      return mImplicitHCount;
302   }
303
304}