001package com.hfg.chem;
002
003import com.hfg.util.CompareUtil;
004import com.hfg.xml.XMLNode;
005import com.hfg.xml.XMLTag;
006
007//------------------------------------------------------------------------------
008/**
009 Ionizable chemical group.
010 <div>
011  @author J. Alex Taylor, hairyfatguy.com
012 </div>
013 */
014//------------------------------------------------------------------------------
015// com.hfg XML/HTML Coding Library
016//
017// This library is free software; you can redistribute it and/or
018// modify it under the terms of the GNU Lesser General Public
019// License as published by the Free Software Foundation; either
020// version 2.1 of the License, or (at your option) any later version.
021//
022// This library is distributed in the hope that it will be useful,
023// but WITHOUT ANY WARRANTY; without even the implied warranty of
024// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
025// Lesser General Public License for more details.
026//
027// You should have received a copy of the GNU Lesser General Public
028// License along with this library; if not, write to the Free Software
029// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
030//
031// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
032// jataylor@hairyfatguy.com
033//------------------------------------------------------------------------------
034
035public class IonizableGroup implements Comparable<IonizableGroup>
036{
037
038   public static final String IONIZABLE_GROUP_TAG = "IonizableGrp";
039   public static final String PROTONATED_FORM_ATT = "protonatedForm";
040   public static final String KA_ATT              = "ka";
041
042   //##########################################################################
043   // PRIVATE FIELDS
044   //##########################################################################
045
046   private Charge  mProtonatedForm;
047   private double  mKa;
048
049   //##########################################################################
050   // CONSTRUCTORS
051   //##########################################################################
052
053   //--------------------------------------------------------------------------
054   public IonizableGroup(double inKa, Charge inProtonatedForm)
055   {
056      if (inKa > 1
057          || inKa < 0)
058      {
059         throw new RuntimeException("Illegal Ka value: " + inKa + "! The Ka cannot be > 1 or < 0! (Be sure the value entered is not the pKa.)");
060      }
061
062      mKa = inKa;
063
064      if (null == inProtonatedForm)
065      {
066         throw new RuntimeException("The protonated form cannot be null!");
067      }
068      else if (inProtonatedForm == Charge.NEGATIVE)
069      {
070         throw new RuntimeException("The protonated form cannot be negative!");
071      }
072
073      mProtonatedForm = inProtonatedForm;
074   }
075
076
077   //--------------------------------------------------------------------------
078   public IonizableGroup(XMLNode inXML)
079   {
080      if (! inXML.getTagName().equals(IONIZABLE_GROUP_TAG))
081      {
082         throw new RuntimeException("Cannot construct an " + this.getClass().getSimpleName() + " from a " + inXML.getTagName() + " tag!");
083      }
084
085      mKa = Double.parseDouble(inXML.getAttributeValue(KA_ATT));
086      mProtonatedForm = Charge.valueOf(inXML.getAttributeValue(PROTONATED_FORM_ATT));
087   }
088
089   //##########################################################################
090   // PUBLIC METHODS
091   //##########################################################################
092
093   //--------------------------------------------------------------------------
094   @Override
095   public int hashCode()
096   {
097      return new Float(getKa()).hashCode() + 31 * getProtonatedForm().hashCode();
098   }
099
100   //--------------------------------------------------------------------------
101   @Override
102   public boolean equals(Object inObj2)
103   {
104      boolean result = false;
105
106      if (inObj2 != null
107            && inObj2 instanceof IonizableGroup)
108      {
109         result = (0 == compareTo((IonizableGroup) inObj2));
110      }
111
112      return result;
113   }
114
115   //--------------------------------------------------------------------------
116   @Override
117   public int compareTo(IonizableGroup inObj2)
118   {
119      int result = -1;
120
121      if (inObj2 != null)
122      {
123         result = 0;
124
125         if (this != inObj2)
126         {
127            result = CompareUtil.compare(getKa(), inObj2.getKa());
128
129            if (0 == result)
130            {
131               result = CompareUtil.compare(getProtonatedForm(), inObj2.getProtonatedForm());
132            }
133         }
134      }
135
136      return result;
137   }
138
139   //--------------------------------------------------------------------------
140   public Charge getProtonatedForm()
141   {
142      return mProtonatedForm;
143   }
144
145   //--------------------------------------------------------------------------
146   public float getpKa()
147   {
148      return (float) - Math.log10(mKa);
149   }
150
151   //--------------------------------------------------------------------------
152   public double getKa()
153   {
154      return mKa;
155   }
156
157   //--------------------------------------------------------------------------
158   public double getCharge(int inCount, double inConcOfHIons)
159   {
160      double value = 0;
161
162      if (inCount > 0)
163      {
164         if (getProtonatedForm() == Charge.POSITIVE)
165         {
166            value = inCount * ((inConcOfHIons / (inConcOfHIons + getKa())));
167         }
168         else if (getProtonatedForm() == Charge.NEUTRAL)
169         {
170            value = -1 * inCount * (1 - (inConcOfHIons / (inConcOfHIons + getKa())));
171         }
172      }
173
174      return value;
175   }
176
177   //--------------------------------------------------------------------------
178   @Override
179   public String toString()
180   {
181      return String.format("%.2E (%s)", mKa, mProtonatedForm.toString());
182   }
183
184   //--------------------------------------------------------------------------
185   public XMLNode toXMLNode()
186   {
187      XMLNode node = new XMLTag(IONIZABLE_GROUP_TAG);
188      node.setAttribute(KA_ATT, mKa + "");
189      node.setAttribute(PROTONATED_FORM_ATT, mProtonatedForm.toString());
190
191      return node;
192   }
193}