001package com.hfg.chem;
002
003import java.util.Map;
004
005import com.hfg.util.collection.CollectionUtil;
006
007//------------------------------------------------------------------------------
008/**
009 Elemental composition and mass tracking object.
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 OrganicMatterImpl extends MatterImpl implements OrganicMatter, Cloneable
036{
037
038   //##########################################################################
039   // PRIVATE FIELDS
040   //##########################################################################
041
042   private Double                  mOrganicAverageMass;
043
044   private boolean                 mOrganicAverageMassIsUserSet;
045
046   //##########################################################################
047   // CONSTRUCTORS
048   //##########################################################################
049
050   //--------------------------------------------------------------------------
051   public OrganicMatterImpl()
052   {
053      super();
054   }
055
056   //--------------------------------------------------------------------------
057   public OrganicMatterImpl(Map<Element, Float> inMap)
058   {
059      super(inMap);
060   }
061
062   //--------------------------------------------------------------------------
063   public OrganicMatterImpl(OrganicMatter inInitialValue)
064   {
065      super(inInitialValue);
066
067      if (inInitialValue != null)
068      {
069         setOrganicAverageMass(inInitialValue.getOrganicAverageMass());
070      }
071   }
072
073   //##########################################################################
074   // PUBLIC METHODS
075   //##########################################################################
076
077   //--------------------------------------------------------------------------
078   @Override
079   public boolean equals(Object inObj)
080   {
081      boolean result = false;
082
083      if (inObj != null
084         && inObj instanceof OrganicMatterImpl)
085      {
086         result = (0 == compareTo((OrganicMatterImpl) inObj));
087      }
088
089      return result;
090   }
091
092   //--------------------------------------------------------------------------
093   @Override
094   public OrganicMatterImpl add(Matter inValue, int inCount)
095   {
096      if (inValue != null)
097      {
098         super.add(inValue, inCount);
099
100         if (mOrganicAverageMassIsUserSet
101             || (null == inValue.getElementalComposition()
102                 && ((inValue instanceof OrganicMatter
103                      && ((OrganicMatter)inValue).getOrganicAverageMass() != null)
104                    || inValue.getAverageMass() != null)))
105         {
106            setOrganicAverageMass((mOrganicAverageMassIsUserSet ? mOrganicAverageMass : CollectionUtil.hasValues(getElementalComposition()) ? getOrganicAverageMass() : 0.0)
107                  + (inValue instanceof OrganicMatter ?
108                        ((((OrganicMatter)inValue).getOrganicAverageMass() != null ? ((OrganicMatter)inValue).getOrganicAverageMass() : inValue.getAverageMass()) * inCount) :
109                        inValue.getAverageMass() * inCount));
110         }
111      }
112
113      return this;
114   }
115
116   //--------------------------------------------------------------------------
117   @Override
118   public OrganicMatterImpl remove(Matter inValue)
119   {
120      return remove(inValue, 1);
121   }
122
123   //--------------------------------------------------------------------------
124   @Override
125   public OrganicMatterImpl remove(Matter inValue, int inCount)
126   {
127      // This will call add() with a negative count
128      return (OrganicMatterImpl) super.remove(inValue, inCount);
129   }
130
131   //--------------------------------------------------------------------------
132   /**
133    If the elemental composition is known, use setElementalComposition() and
134    the masses will be derived automatically; this method is for use in those
135    (hopefully) rare times when the mass is known but not the elemental composition.
136    @param inValue the mass to use as the organic average mass for this object
137    @return this OrganicMatterImpl object to enable method chaining
138    */
139   public OrganicMatterImpl setOrganicAverageMass(Double inValue)
140   {
141      mOrganicAverageMass = inValue;
142
143      mOrganicAverageMassIsUserSet = (inValue != null && calculateOrganicMassFromElementalComposition() != mOrganicAverageMass);
144
145      return this;
146   }
147
148   //--------------------------------------------------------------------------
149   public Double getOrganicAverageMass()
150   {
151      if (null == mOrganicAverageMass)
152      {
153         calculateMassFromElementalComposition();
154      }
155
156      return mOrganicAverageMass;
157   }
158
159
160   //--------------------------------------------------------------------------
161   @Override
162   public OrganicMatterImpl clone()
163   {
164      return (OrganicMatterImpl) super.clone();
165   }
166
167
168   //--------------------------------------------------------------------------
169   @Override
170   public void clearCalculatedProperties()
171   {
172      super.clearCalculatedProperties();
173      if (! mOrganicAverageMassIsUserSet) mOrganicAverageMass = null;
174   }
175
176   //##########################################################################
177   // PROTECTED METHODS
178   //##########################################################################
179
180   //--------------------------------------------------------------------------
181   @Override
182   protected void calculateMassFromElementalComposition()
183   {
184      super.calculateMassFromElementalComposition();
185
186      if (! mOrganicAverageMassIsUserSet)
187      {
188         mOrganicAverageMass = calculateOrganicMassFromElementalComposition();
189      }
190   }
191
192
193   //--------------------------------------------------------------------------
194   @Override
195   protected boolean massesAreUserSet()
196   {
197      return (super.massesAreUserSet() || mOrganicAverageMassIsUserSet);
198   }
199
200   //##########################################################################
201   // PRIVATE METHODS
202   //##########################################################################
203
204   //--------------------------------------------------------------------------
205   private double calculateOrganicMassFromElementalComposition()
206   {
207      double organicAvg = 0.0;
208
209      Map<Element, Float> elementalCompositionMap = getElementalComposition();
210      if (elementalCompositionMap != null)
211      {
212         for (Element element : elementalCompositionMap.keySet())
213         {
214            float count = elementalCompositionMap.get(element);
215
216            Double elementalAvgMass = element.getAverageMass();
217            Double elementalOrgAvgMass = element.getOrganicAverageMass();
218
219            organicAvg += count * (elementalOrgAvgMass != null ? elementalOrgAvgMass : elementalAvgMass != null ? elementalAvgMass : element.getMonoisotopicMass());
220         }
221
222      }
223
224      return organicAvg;
225   }
226}