001package com.hfg.bio.glyco;
002
003
004import java.awt.Color;
005import java.awt.geom.Point2D;
006import java.util.ArrayList;
007import java.util.List;
008import java.util.Set;
009import java.util.HashSet;
010
011import com.hfg.chem.Charge;
012import com.hfg.chem.Element;
013import com.hfg.chem.IonizableGroup;
014import com.hfg.chem.Molecule;
015import com.hfg.graphics.Shape;
016import com.hfg.svg.SvgAttr;
017import com.hfg.svg.SvgCircle;
018import com.hfg.svg.SvgNode;
019import com.hfg.svg.SvgPolygon;
020import com.hfg.svg.SvgRect;
021import com.hfg.graphics.ColorUtil;
022import com.hfg.util.CompareUtil;
023import com.hfg.util.StringUtil;
024
025//------------------------------------------------------------------------------
026/**
027 Monosaccharide values.
028 <div>
029 See <a href='https://en.wikipedia.org/wiki/Monosaccharide'>https://en.wikipedia.org/wiki/Monosaccharide</a>
030 </div>
031 <div>
032 See <a href='http://www.genome.jp/kegg/catalog/codes2.html'>http://www.genome.jp/kegg/catalog/codes2.html</a>
033 </div>
034 <div>
035 @author J. Alex Taylor, hairyfatguy.com
036 </div>
037 */
038//------------------------------------------------------------------------------
039// com.hfg XML/HTML Coding Library
040//
041// This library is free software; you can redistribute it and/or
042// modify it under the terms of the GNU Lesser General Public
043// License as published by the Free Software Foundation; either
044// version 2.1 of the License, or (at your option) any later version.
045//
046// This library is distributed in the hope that it will be useful,
047// but WITHOUT ANY WARRANTY; without even the implied warranty of
048// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
049// Lesser General Public License for more details.
050//
051// You should have received a copy of the GNU Lesser General Public
052// License along with this library; if not, write to the Free Software
053// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
054//
055// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
056// jataylor@hairyfatguy.com
057//------------------------------------------------------------------------------
058
059public class Monosaccharide extends Molecule
060{
061   //##########################################################################
062   // PUBLIC FIELDS
063   //##########################################################################
064
065   // Hexoses
066   /**
067    Generic hexose.
068    */
069   public static final Monosaccharide Hexose    = new Monosaccharide("Hexose",     "Hex", Shape.CIRCLE, Color.WHITE);
070   public static final Monosaccharide Galactose = new Monosaccharide("Galactose",  "Gal", Shape.CIRCLE, new Color(255, 255, 0)); // Yellow
071   public static final Monosaccharide Glucose   = new Monosaccharide("Glucose",    "Glc", Shape.CIRCLE, new Color(0, 0, 250)); // Blue
072   public static final Monosaccharide Mannose   = new Monosaccharide("Mannose",    "Man", Shape.CIRCLE, new Color(0, 200, 50)); // Green
073
074   // Deoxysugar (hexose or pentose without a hydroxyl group at the 6-position or the 2-position)
075   public static final Monosaccharide Fucose    = new Monosaccharide("Fucose",     "Fuc", Shape.TRIANGLE, new Color(250, 0, 0)); // Red
076
077   // Pentoses
078   public static final Monosaccharide Xylose    = new Monosaccharide("Xylose",     "Xyl", Shape.STAR, new Color(250, 234, 213)); // Orange
079
080   // Amino sugar (hexose with an N-acetylated amino group at the 2-position)
081   public static final Monosaccharide HexNAc    = new Monosaccharide("Hexosamine",  "HexNac", Shape.SQUARE, Color.WHITE);
082   public static final Monosaccharide GalNAc    = new Monosaccharide("N-acetyl-D-galactosamine",  "GalNAc", Shape.SQUARE, new Color(255, 255, 0)); // Yellow
083   public static final Monosaccharide GlcNAc    = new Monosaccharide("N-acetyl-D-glucosamine",    "GlcNAc", Shape.SQUARE, new Color(0, 0, 250)); // Blue
084   public static final Monosaccharide ManNAc    = new Monosaccharide("N-Acetylmannosamine",       "ManNAc", Shape.SQUARE, new Color(0, 200, 50)); // Green
085
086   // Sialic acids
087   public static final Monosaccharide NeuAc     = new Monosaccharide("N-Acetylneuraminic acid",    "NeuAc", Shape.DIAMOND, new Color(200, 0, 200)); // Purple
088   public static final Monosaccharide NeuGc     = new Monosaccharide("N-glycolylneuraminic acid",  "NeuGc", Shape.DIAMOND, new Color(233, 255, 255)); // Light blue
089   public static final Monosaccharide KDN       = new Monosaccharide("Deaminated neuraminic acid", "KDN",   Shape.DIAMOND, new Color(0, 200, 50)); // Green
090   public static final Monosaccharide GlcA      = new Monosaccharide("D-Glucuronic acid",          "GlcA",  Shape.DIAMOND, new Color(0, 0, 250)); // Blue
091
092
093
094   //##########################################################################
095   // PRIVATE FIELDS
096   //##########################################################################
097
098   private String mName;
099   private String mAbbrev;
100   private Color  mColor;
101   private Shape  mShape;
102
103   // This declaration has to come before the public constants below.
104   private static Set<Monosaccharide> sValues = new HashSet<>();
105
106   static
107   {
108      Hexose.addAtoms(Element.CARBON, 6)
109            .addAtoms(Element.HYDROGEN, 12)
110            .addAtoms(Element.OXYGEN, 6)
111            .lock()
112            .register();
113
114      Galactose.addAtoms(Element.CARBON, 6)
115            .addAtoms(Element.HYDROGEN, 12)
116            .addAtoms(Element.OXYGEN, 6)
117            .lock()
118            .register();
119
120      Glucose.addAtoms(Element.CARBON, 6)
121            .addAtoms(Element.HYDROGEN, 12)
122            .addAtoms(Element.OXYGEN, 6)
123            .lock()
124            .register();
125
126      Mannose.addAtoms(Element.CARBON, 6)
127            .addAtoms(Element.HYDROGEN, 12)
128            .addAtoms(Element.OXYGEN, 6)
129            .lock()
130            .register();
131
132      Fucose.addAtoms(Element.CARBON, 6)
133            .addAtoms(Element.HYDROGEN, 12)
134            .addAtoms(Element.OXYGEN, 5)
135            .lock()
136            .register();
137
138      Xylose.addAtoms(Element.CARBON, 5)
139            .addAtoms(Element.HYDROGEN, 10)
140            .addAtoms(Element.OXYGEN, 5)
141            .lock()
142            .register();
143
144
145
146      HexNAc.addAtoms(Element.CARBON, 8)
147            .addAtoms(Element.HYDROGEN, 15)
148            .addAtoms(Element.NITROGEN, 1)
149            .addAtoms(Element.OXYGEN, 6)
150            .lock()
151            .register();
152
153      GalNAc.addAtoms(Element.CARBON, 8)
154            .addAtoms(Element.HYDROGEN, 15)
155            .addAtoms(Element.NITROGEN, 1)
156            .addAtoms(Element.OXYGEN, 6)
157            .lock()
158            .register();
159
160      GlcNAc.addAtoms(Element.CARBON, 8)
161            .addAtoms(Element.HYDROGEN, 15)
162            .addAtoms(Element.NITROGEN, 1)
163            .addAtoms(Element.OXYGEN, 6)
164            .lock()
165            .register();
166
167      ManNAc.addAtoms(Element.CARBON, 8)
168            .addAtoms(Element.HYDROGEN, 15)
169            .addAtoms(Element.NITROGEN, 1)
170            .addAtoms(Element.OXYGEN, 6)
171            .lock()
172            .register();
173
174
175
176      NeuAc.addAtoms(Element.CARBON, 11)
177            .addAtoms(Element.HYDROGEN, 19)
178            .addAtoms(Element.NITROGEN, 1)
179            .addAtoms(Element.OXYGEN, 9)
180            .addKa(new IonizableGroup(6.3E-3, Charge.NEUTRAL))  // pKa 2.2
181//            .addKa(new IonizableGroup(2.5E-3, Charge.NEUTRAL))  // pKa 2.6
182            .lock()
183            .register();
184
185      NeuGc.addAtoms(Element.CARBON, 11)
186            .addAtoms(Element.HYDROGEN, 19)
187            .addAtoms(Element.NITROGEN, 1)
188            .addAtoms(Element.OXYGEN, 10)
189            .lock()
190            .register();
191
192      KDN.addAtoms(Element.CARBON, 9)
193            .addAtoms(Element.HYDROGEN, 16)
194            .addAtoms(Element.OXYGEN, 9)
195            .lock()
196            .register();
197
198      GlcA.addAtoms(Element.CARBON, 6)
199            .addAtoms(Element.HYDROGEN, 10)
200            .addAtoms(Element.OXYGEN, 7)
201            .lock()
202            .register();
203   }
204
205
206
207   //##########################################################################
208   // CONSTRUCTORS
209   //##########################################################################
210
211   //--------------------------------------------------------------------------
212   private Monosaccharide(String inName, String inAbbrev)
213   {
214      mName   = inName;
215      mAbbrev = inAbbrev;
216   }
217
218   //--------------------------------------------------------------------------
219   private Monosaccharide(String inName, String inAbbrev, Shape inShape, Color inColor)
220   {
221      this(inName, inAbbrev);
222      mShape = inShape;
223      mColor = inColor;
224   }
225
226   //##########################################################################
227   // PUBLIC METHODS
228   //##########################################################################
229
230   //--------------------------------------------------------------------------
231   public static Monosaccharide valueOf(String inString)
232   {
233      Monosaccharide value = null;
234
235      if (StringUtil.isSet(inString))
236      {
237         for (Monosaccharide monosaccharide : sValues)
238         {
239            if (monosaccharide.name().equalsIgnoreCase(inString)
240                  || monosaccharide.getAbbrev().equals(inString))
241            {
242               value = monosaccharide;
243               break;
244            }
245         }
246      }
247
248      return value;
249   }
250
251   //--------------------------------------------------------------------------
252   public static Monosaccharide[] values()
253   {
254      return sValues.toArray(new Monosaccharide[sValues.size()]);
255   }
256
257
258   //--------------------------------------------------------------------------
259   /**
260    Puts the Monosaccharide into the Set of unique Monosaccharide returned by Monosaccharide.values().
261    */
262   public void register()
263   {
264      if (! isLocked())
265      {
266         throw new RuntimeException("Only locked Monosaccharides can be added to the values list!");
267      }
268
269      sValues.add(this);
270   }
271
272   //--------------------------------------------------------------------------
273   @Override
274   public Monosaccharide addAtoms(Element inElement, int inCount)
275   {
276      return (Monosaccharide) super.addAtoms(inElement, inCount);
277   }
278
279   //--------------------------------------------------------------------------
280   @Override
281   public Monosaccharide addAtoms(Element inElement, float inCount)
282   {
283      return (Monosaccharide) super.addAtoms(inElement, inCount);
284   }
285
286   //--------------------------------------------------------------------------
287   @Override
288   public Monosaccharide lock()
289   {
290      return (Monosaccharide) super.lock();
291   }
292
293   //--------------------------------------------------------------------------
294   public String name()
295   {
296      return mName;
297   }
298
299   //--------------------------------------------------------------------------
300   public String getAbbrev()
301   {
302      return mAbbrev;
303   }
304
305   //--------------------------------------------------------------------------
306   public Shape getShape()
307   {
308      return mShape;
309   }
310
311   //--------------------------------------------------------------------------
312   public Color getColor()
313   {
314      return mColor;
315   }
316
317   //--------------------------------------------------------------------------
318   @Override
319   public Monosaccharide addKa(IonizableGroup inValue)
320   {
321      return (Monosaccharide) super.addKa(inValue);
322   }
323
324   //--------------------------------------------------------------------------
325   @Override
326   public String toString()
327   {
328      return mAbbrev;
329   }
330
331   //--------------------------------------------------------------------------
332   public SvgNode toSVGNode()
333   {
334      SvgNode svgNode = null;
335      if (Shape.SQUARE.equals(getShape()))
336      {
337         svgNode = new SvgRect().setWidth(10).setHeight(10);
338      }
339      else if (Shape.CIRCLE.equals(getShape()))
340      {
341         svgNode = new SvgCircle().setR(5);
342      }
343      else if (Shape.DIAMOND.equals(getShape()))
344      {
345         List<Point2D> points = new ArrayList<>(4);
346         points.add(new Point2D.Float(0, 5));
347         points.add(new Point2D.Float(5, 10));
348         points.add(new Point2D.Float(10, 5));
349         points.add(new Point2D.Float(5, 0));
350
351         svgNode = new SvgPolygon(points);
352      }
353      else if (Shape.TRIANGLE.equals(getShape()))
354      {
355         List<Point2D> points = new ArrayList<>(3);
356         points.add(new Point2D.Float(0, 10));
357         points.add(new Point2D.Float(10, 10));
358         points.add(new Point2D.Float(5, 0));
359
360         svgNode = new SvgPolygon(points);
361      }
362
363      if (svgNode != null)
364      {
365         svgNode.setAttribute(SvgAttr.title, name());
366         svgNode.addStyle(SvgAttr.stroke + ": #000000");
367         svgNode.addStyle(SvgAttr.strokeWidth + ":1");
368
369         if (getColor() != null)
370         {
371            svgNode.addStyle(SvgAttr.fill + ": #" + ColorUtil.colorToHex(getColor()));
372         }
373      }
374
375      return svgNode;
376   }
377
378   //--------------------------------------------------------------------------
379   @Override
380   public int compareTo(Object inObj2)
381   {
382      int result = -1;
383
384      if (inObj2 != null)
385      {
386         if (inObj2 instanceof Monosaccharide)
387         {
388            Monosaccharide monosaccharide2 = (Monosaccharide) inObj2;
389
390            result = CompareUtil.compare(getAbbrev(), monosaccharide2.getAbbrev());
391         }
392         else
393         {
394            result = CompareUtil.compare(hashCode(), inObj2.hashCode());
395         }
396      }
397
398      return result;
399   }
400
401}