001package com.hfg.bio.seq;
002
003import java.util.HashSet;
004import java.util.Map;
005import java.util.HashMap;
006import java.util.Set;
007
008import com.hfg.bio.AminoAcid;
009import com.hfg.chem.Element;
010import com.hfg.bio.HfgBioXML;
011import com.hfg.chem.Molecule;
012import com.hfg.util.CompareUtil;
013import com.hfg.util.StringUtil;
014import com.hfg.xml.XMLNode;
015import com.hfg.xml.XMLTag;
016
017//------------------------------------------------------------------------------
018/**
019 * Biological protein sequence cross-link types.
020 *
021 * @author J. Alex Taylor, hairyfatguy.com
022 */
023//------------------------------------------------------------------------------
024// com.hfg XML/HTML Coding Library
025//
026// This library is free software; you can redistribute it and/or
027// modify it under the terms of the GNU Lesser General Public
028// License as published by the Free Software Foundation; either
029// version 2.1 of the License, or (at your option) any later version.
030//
031// This library is distributed in the hope that it will be useful,
032// but WITHOUT ANY WARRANTY; without even the implied warranty of
033// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
034// Lesser General Public License for more details.
035//
036// You should have received a copy of the GNU Lesser General Public
037// License along with this library; if not, write to the Free Software
038// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
039//
040// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
041// jataylor@hairyfatguy.com
042//------------------------------------------------------------------------------
043
044
045public class ProteinXLinkType extends Molecule
046{
047   // This declaration has to come before the public constants below.
048   private static Set<ProteinXLinkType> sValues = new HashSet<>();
049
050   public static final ProteinXLinkType DISULFIDE;
051
052   /**
053    Lysine-arginine protein cross-linking product common with aging of collagen and crystallin.
054    Sjöberg, Johan Svantesson, and Sven Bulterijs. 2009. “Characteristics, Formation, and Pathophysiology of Glucosepane: A Major Protein Cross-Link.”
055            Rejuvenation Research 12 (2) (April): 137–148. doi:10.1089/rej.2009.0846.
056    */
057   public static final ProteinXLinkType GLUCOSEPANE;
058
059   static
060   {
061      Map<Element, Float> elementalComp = new HashMap<>();
062      elementalComp.put(Element.HYDROGEN, -2f);
063
064      DISULFIDE = new ProteinXLinkType("Disulfide", elementalComp)
065            .addDonor(AminoAcid.CYSTEINE)
066            .addAcceptor(AminoAcid.CYSTEINE)
067            .lock()
068            .register();
069
070
071      elementalComp = new HashMap<>();
072      elementalComp.put(Element.CARBON, 6f);
073      elementalComp.put(Element.OXYGEN, 2f);
074      elementalComp.put(Element.HYDROGEN, 4f);
075
076      GLUCOSEPANE = new ProteinXLinkType("Glucosepane", elementalComp)
077            .addDonor(AminoAcid.LYSINE)
078            .addAcceptor(AminoAcid.ARGININE)
079            .lock()
080            .register();
081
082   }
083
084
085   //##########################################################################
086   // PRIVATE FIELDS
087   //##########################################################################
088
089   private Set<AminoAcid> mDonorSpecificity;
090   private Set<AminoAcid> mAcceptorSpecificity;
091
092
093   //##########################################################################
094   // CONSTRUCTORS
095   //##########################################################################
096
097   //--------------------------------------------------------------------------
098   private ProteinXLinkType(String inName,
099                            Map<Element, Float> inElementalComposition)
100   {
101      super(inName, inElementalComposition);
102   }
103
104   //--------------------------------------------------------------------------
105   public ProteinXLinkType(String inName,
106                           Map<Element, Float> inElementalComposition,
107                           Set<AminoAcid> inDonorSpecificity,
108                           Set<AminoAcid> inAcceptorSpecificity)
109   {
110      this(inName, inElementalComposition);
111      mDonorSpecificity = inDonorSpecificity;
112      mAcceptorSpecificity = inAcceptorSpecificity;
113   }
114
115   //--------------------------------------------------------------------------
116   public ProteinXLinkType(XMLNode inXML)
117   {
118      super(inXML);
119
120      if (! inXML.getTagName().equals(HfgBioXML.XLINK_TYPE_TAG))
121      {
122         throw new RuntimeException("Cannot construct an " + this.getClass().getSimpleName() + " from a " + inXML.getTagName() + " tag!");
123      }
124
125      XMLNode donorsTag = inXML.getRequiredSubtagByName(HfgBioXML.DONORS_TAG);
126      for (XMLNode subtag : donorsTag.getXMLNodeSubtags())
127      {
128         addDonor(new AminoAcid(subtag));
129      }
130
131      XMLNode acceptorsTag = inXML.getRequiredSubtagByName(HfgBioXML.ACCEPTORS_TAG);
132      for (XMLNode subtag : acceptorsTag.getXMLNodeSubtags())
133      {
134         addAcceptor(new AminoAcid(subtag));
135      }
136   }
137
138
139   //##########################################################################
140   // PUBLIC METHODS
141   //##########################################################################
142
143   //--------------------------------------------------------------------------
144   /**
145    Returns the ProteinXLinkType whose name matches the specified String.
146    @param inString the name for the ProteinXLinkType to retrieve
147    @return the ProteinXLinkType whose name matches the specified String
148    */
149   public static ProteinXLinkType valueOf(String inString)
150   {
151      ProteinXLinkType value = null;
152
153      if (StringUtil.isSet(inString))
154      {
155         for (ProteinXLinkType xLinkType : sValues)
156         {
157            if (xLinkType.name().equalsIgnoreCase(inString))
158            {
159               value = xLinkType;
160               break;
161            }
162         }
163      }
164
165      return value;
166   }
167
168   //--------------------------------------------------------------------------
169   public static ProteinXLinkType[] values()
170   {
171      return sValues.toArray(new ProteinXLinkType[sValues.size()]);
172   }
173
174   //--------------------------------------------------------------------------
175   /**
176    Puts the ProteinXLinkType into the Set of unique ProteinXLinkType returned by ProteinXLinkType.values().
177    */
178   public ProteinXLinkType register()
179   {
180      if (! isLocked())
181      {
182         throw new RuntimeException("Only locked ProteinXLinkTypes can be added to the values list!");
183      }
184
185      sValues.add(this);
186
187      return this;
188   }
189
190   //--------------------------------------------------------------------------
191   @Override
192   public ProteinXLinkType lock()
193   {
194      return (ProteinXLinkType) super.lock();
195   }
196
197   //--------------------------------------------------------------------------
198   @Override
199   public boolean equals(Object inObj)
200   {
201      boolean result = false;
202
203      if (inObj != null
204         && inObj instanceof ProteinXLinkType)
205      {
206         result = (0 == compareTo(inObj));
207      }
208
209      return result;
210   }
211
212   //--------------------------------------------------------------------------
213   public int compareTo(Object inObj)
214   {
215      int result = -1;
216
217      if (inObj != null)
218      {
219         if (inObj instanceof ProteinXLinkType)
220         {
221            ProteinXLinkType xLinkType2 = (ProteinXLinkType) inObj;
222
223            result = CompareUtil.compare(mAcceptorSpecificity, xLinkType2.mAcceptorSpecificity);
224            if (0 == result)
225            {
226               result = CompareUtil.compare(mDonorSpecificity, xLinkType2.mDonorSpecificity);
227               if (0 == result)
228               {
229                  result = super.compareTo(inObj);
230               }
231            }
232         }
233         else
234         {
235            result = CompareUtil.compare(hashCode(), inObj.hashCode());
236         }
237      }
238
239      return result;
240   }
241
242   //--------------------------------------------------------------------------
243   public boolean isAcceptableSite(AminoAcid inDonor, AminoAcid inAcceptor)
244   {
245      return mDonorSpecificity.contains(inDonor) && mAcceptorSpecificity.contains(inAcceptor);
246   }
247
248   //--------------------------------------------------------------------------
249   public XMLNode toXMLNode()
250   {
251      XMLNode node = super.toXMLNode();
252      node.setTagName(HfgBioXML.XLINK_TYPE_TAG);
253
254      XMLNode donorsTag = new XMLTag(HfgBioXML.DONORS_TAG);
255      node.addSubtag(donorsTag);
256      for (AminoAcid aa : mDonorSpecificity)
257      {
258         donorsTag.addSubtag(aa.toXMLNode());
259      }
260
261      XMLNode acceptorsTag = new XMLTag(HfgBioXML.ACCEPTORS_TAG);
262      node.addSubtag(acceptorsTag);
263      for (AminoAcid aa : mAcceptorSpecificity)
264      {
265         acceptorsTag.addSubtag(aa.toXMLNode());
266      }
267
268      return node;
269   }
270
271   //##########################################################################
272   // PRIVATE METHODS
273   //##########################################################################
274
275   //--------------------------------------------------------------------------
276   private ProteinXLinkType addDonor(AminoAcid inDonor)
277   {
278      if (null == mDonorSpecificity)
279      {
280         mDonorSpecificity = new HashSet<>();
281      }
282
283      mDonorSpecificity.add(inDonor);
284
285      return this;
286   }
287
288   //--------------------------------------------------------------------------
289   private ProteinXLinkType addAcceptor(AminoAcid inAcceptor)
290   {
291      if (null == mAcceptorSpecificity)
292      {
293         mAcceptorSpecificity = new HashSet<>();
294      }
295
296      mAcceptorSpecificity.add(inAcceptor);
297
298      return this;
299   }
300}