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}