001package com.hfg.bio.proteinproperty;
002
003import java.lang.reflect.Method;
004import java.math.BigDecimal;
005import java.math.BigInteger;
006import java.util.Collection;
007import java.util.HashMap;
008import java.util.Map;
009
010import com.hfg.bio.seq.Protein;
011import com.hfg.exception.ProgrammingException;
012import com.hfg.util.DataType;
013import com.hfg.util.StringUtil;
014
015//------------------------------------------------------------------------------
016/**
017 * Abstract base Class for single value protein properties.
018 * @author J. Alex Taylor, hairyfatguy.com
019 */
020//------------------------------------------------------------------------------
021// com.hfg Library
022//
023// This library is free software; you can redistribute it and/or
024// modify it under the terms of the GNU Lesser General Public
025// License as published by the Free Software Foundation; either
026// version 2.1 of the License, or (at your option) any later version.
027//
028// This library is distributed in the hope that it will be useful,
029// but WITHOUT ANY WARRANTY; without even the implied warranty of
030// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
031// Lesser General Public License for more details.
032//
033// You should have received a copy of the GNU Lesser General Public
034// License along with this library; if not, write to the Free Software
035// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
036//
037// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
038// jataylor@hairyfatguy.com
039//------------------------------------------------------------------------------
040
041public abstract class SimpleProteinProperty<S extends SimpleProteinPropertyCalcSettings, T> implements SingleValueProteinProperty<S, T>
042{
043   private String mName;
044   private String mDescription;
045   private String mReference;
046
047   private static Map<String, SimpleProteinProperty> sUniqueMap = new HashMap<>();
048
049   private static boolean sInitialized = false;
050
051   //###########################################################################
052   // CONSTRUCTORS
053   //###########################################################################
054
055   //---------------------------------------------------------------------------
056   protected SimpleProteinProperty(String inName)
057   {
058      if (sUniqueMap.containsKey(inName))
059      {
060         throw new ProgrammingException("A SimpleProteinProperty already exists with name " + StringUtil.singleQuote(inName) + "!");
061      }
062
063      mName = inName;
064      sUniqueMap.put(inName, this);
065   }
066
067
068   //###########################################################################
069   // PUBLIC METHODS
070   //###########################################################################
071
072   public abstract String getType();
073
074   //---------------------------------------------------------------------------
075   @Override
076   public String toString()
077   {
078      return name();
079   }
080
081   //---------------------------------------------------------------------------
082   public String name()
083   {
084      return mName;
085   }
086
087   //---------------------------------------------------------------------------
088   public SimpleProteinProperty setDescription(String inValue)
089   {
090      mDescription = inValue;
091      return this;
092   }
093
094   //---------------------------------------------------------------------------
095   public String getDescription()
096   {
097      return mDescription;
098   }
099
100   //---------------------------------------------------------------------------
101   public SimpleProteinProperty setReference(String inValue)
102   {
103      mReference = inValue;
104      return this;
105   }
106
107   //---------------------------------------------------------------------------
108   public String getReference()
109   {
110      return mReference;
111   }
112
113   //--------------------------------------------------------------------------
114   public DataType getDataType()
115   {
116      Class clazz = getReturnType();
117
118      DataType dataType = null;
119      if (clazz.equals(Integer.class))
120      {
121         dataType = DataType.INTEGER;
122      }
123      else if (clazz.equals(BigInteger.class)
124               || clazz.equals(Long.class))
125      {
126         dataType = DataType.BIGINT;
127      }
128      else if (clazz.equals(Float.class))
129      {
130         dataType = DataType.FLOAT;
131      }
132      else if (clazz.equals(Double.class)
133            || clazz.equals(BigDecimal.class))
134      {
135         dataType = DataType.DOUBLE;
136      }
137      else if (clazz.equals(String.class))
138      {
139         dataType = DataType.STRING;
140      }
141
142      return dataType;
143   }
144
145   //--------------------------------------------------------------------------
146   /**
147    Returns the Number data type returned by the calculate() method.
148    */
149   // Unfortunately there isn't a simple way to just return T.class
150   public Class getReturnType()
151   {
152      Class dataType = null;
153      try
154      {
155         Method method = this.getClass().getMethod("calculate", new Class[] { Protein.class, SimpleProteinPropertyCalcSettings.class });
156         dataType = method.getReturnType();
157      }
158      catch (Exception e)
159      {
160
161      }
162
163      return dataType;
164   }
165
166   //---------------------------------------------------------------------------
167   public static SimpleProteinProperty valueOf(String inName)
168   {
169      ensureExtendingClassesAreInitialized();
170
171      return sUniqueMap.get(inName);
172   }
173
174   //---------------------------------------------------------------------------
175   public static Collection<? extends SimpleProteinProperty> values()
176   {
177      ensureExtendingClassesAreInitialized();
178
179      return sUniqueMap.values();
180   }
181
182   //---------------------------------------------------------------------------
183   // This is done to ensure that calls to values() and valueOf() have registered values to work with.
184   // The file /META-DATA/services/com.hfg.bio.proteinproperty.SimpleProteinPropery holds the names of
185   // the classes to be initialized.
186   // (Had to create a custom ServiceLoader that doesn't try to instantiate the properties but just
187   // calls Class.forName() to initialize the static definitions.)
188   private static void ensureExtendingClassesAreInitialized()
189   {
190      if (! sInitialized)
191      {
192         try
193         {
194            new ProteinPropertyServiceLoader().load();
195         }
196         catch (Exception e)
197         {
198            // Ignore
199         }
200
201         sInitialized = true;
202      }
203   }
204
205}