001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package armyc2.c2sd.renderer.utilities;
006
007import java.text.SimpleDateFormat;
008import java.util.Date;
009import java.util.Locale;
010import java.util.TimeZone;
011import java.util.logging.Level;
012import java.util.regex.Pattern;
013
014/**
015 *
016 * @author michael.spinelli
017 */
018public class SymbolUtilities
019{
020
021    private static SimpleDateFormat dateFormatFront = new SimpleDateFormat("ddHHmmss", Locale.US);
022    private static SimpleDateFormat dateFormatBack = new SimpleDateFormat("MMMyy", Locale.US);
023    private static SimpleDateFormat dateFormatFull = new SimpleDateFormat("ddHHmmssZMMMyy", Locale.US);
024    private static SimpleDateFormat dateFormatZulu = new SimpleDateFormat("Z", Locale.US);
025
026    //this regex is from: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html
027    private static final String Digits     = "(\\p{Digit}+)";
028    private static final String HexDigits  = "(\\p{XDigit}+)";
029    // an exponent is 'e' or 'E' followed by an optionally
030    // signed decimal integer.
031    private static final String Exp        = "[eE][+-]?"+Digits;
032    private static final String fpRegex    =
033            ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
034                    "[+-]?(" + // Optional sign character
035                    "NaN|" +           // "NaN" string
036                    "Infinity|" +      // "Infinity" string
037
038                    // A decimal floating-point string representing a finite positive
039                    // number without a leading sign has at most five basic pieces:
040                    // Digits . Digits ExponentPart FloatTypeSuffix
041                    //
042                    // Since this method allows integer-only strings as input
043                    // in addition to strings of floating-point literals, the
044                    // two sub-patterns below are simplifications of the grammar
045                    // productions from section 3.10.2 of
046                    // The Java™ Language Specification.
047
048                    // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
049                    "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
050
051                    // . Digits ExponentPart_opt FloatTypeSuffix_opt
052                    "(\\.("+Digits+")("+Exp+")?)|"+
053
054                    // Hexadecimal strings
055                    "((" +
056                    // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
057                    "(0[xX]" + HexDigits + "(\\.)?)|" +
058
059                    // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
060                    "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
061
062                    ")[pP][+-]?" + Digits + "))" +
063                    "[fFdD]?))" +
064                    "[\\x00-\\x20]*");// Optional trailing "whitespace"
065
066    private static final Pattern pIsNumber = Pattern.compile(fpRegex);
067
068    private static RendererSettings rendererSettings = RendererSettings.getInstance();
069
070  /*if (Pattern.matches(fpRegex, myString))
071      Double.valueOf(myString); // Will not throw NumberFormatException
072  else {
073      // Perform suitable alternative action
074       }*/
075    /**
076     * @name getBasicSymbolID
077     *
078     * @desc Returns a formatted string that has only the necessary static
079     * characters needed to draw a symbol. For instance
080     * GetBasicSymbolID("GFTPGLB----K---") returns "G*T*GLB---****X"
081     *
082     * @param strSymbolID - IN - A 15 character MilStd code
083     * @return A properly formated basic symbol ID
084     */
085    public static String getBasicSymbolID(String strSymbolID)
086    {
087        try
088        {
089            StringBuilder sb = new StringBuilder();
090            if ((strSymbolID != null) && (strSymbolID.length() == 15))
091            {
092                // Check to make sure it is a tactical graphic symbol.
093                if ((isWeather(strSymbolID)) || (isBasicShape(strSymbolID)))
094                {
095                    return strSymbolID;
096                }
097                else if (isTacticalGraphic(strSymbolID) == true)
098                {
099                    sb.append(strSymbolID.charAt(0));
100                    sb.append("*");
101                    sb.append(strSymbolID.charAt(2));
102                    sb.append("*");
103                    sb.append(strSymbolID.substring(4, 10));
104                    sb.append("****");
105                    sb.append("X");
106
107                    if (isEMSNaturalEvent(strSymbolID) == true)
108                    {
109                        sb.deleteCharAt(14).append("*");
110                    }
111
112                    return sb.toString();
113                }
114                else if (isWarfighting(strSymbolID))
115                {
116                        
117                    sb.append(strSymbolID.charAt(0));
118                    sb.append("*");
119                    sb.append(strSymbolID.charAt(2));
120                    sb.append("*");
121                    sb.append(strSymbolID.substring(4, 10));
122
123                        if(isSIGINT(strSymbolID))
124                                sb.append("--***");
125                        else if(isInstallation(strSymbolID))
126                                sb.append("H****");
127                        else
128                    {
129                        sb.append("*****");
130                        UnitDefTable udt = UnitDefTable.getInstance();
131                        String temp = sb.toString();
132                        for(int i = 0; i < 2; i++)
133                        {
134                            if(udt.hasUnitDef(temp,i)==true)
135                            {
136                                return temp;
137                            }
138                            else
139                            {
140                                temp = temp.substring(0,10) + "H****";
141                                if(udt.hasUnitDef(temp,i)==true)
142                                {
143                                    return temp;
144                                }
145                                else
146                                {
147                                    temp = temp.substring(0,10) + "MO***";
148                                    if(udt.hasUnitDef(temp,i)==true)
149                                    {
150                                        return temp;
151                                    }
152                                }
153                            }
154                            temp = temp.substring(0,10) + "*****";
155                        }
156
157                    }
158
159                    return sb.toString();
160                }
161                else // Don't do anything for bridge symbols
162                {
163                    return strSymbolID;
164                }
165            }
166            else
167            {
168                return strSymbolID;
169            }
170        }
171        catch (Throwable t)
172        {
173            System.out.println(t);
174        }
175        return "";
176    }
177
178    /**
179     * Only for renderer use.  Please use getBasicSymbolID.
180     * @param strSymbolID
181     * @return
182     */
183    public static String getBasicSymbolIDStrict(String strSymbolID)
184    {
185        if(strSymbolID != null && strSymbolID.length() == 15)
186        {
187            StringBuilder sb = new StringBuilder();
188            char scheme = strSymbolID.charAt(0);
189            if (scheme == 'G')
190            {
191                sb.append(strSymbolID.charAt(0));
192                sb.append("*");
193                sb.append(strSymbolID.charAt(2));
194                sb.append("*");
195                sb.append(strSymbolID.substring(4, 10));
196                sb.append("****X");
197            }
198            else if (scheme != 'W' && scheme != 'B' && scheme != 'P')
199            {
200                sb.append(strSymbolID.charAt(0));
201                sb.append("*");
202                sb.append(strSymbolID.charAt(2));
203                sb.append("*");
204                sb.append(strSymbolID.substring(4, 10));
205                sb.append("*****");
206            }
207            else
208            {
209                return strSymbolID;
210            }
211            return sb.toString();
212        }
213        return strSymbolID;
214    }
215
216    public static String reconcileSymbolID(String symbolID)
217    {
218        return reconcileSymbolID(symbolID, false);
219    }
220
221    public static String reconcileSymbolID(String symbolID, boolean isMultiPoint)
222    {
223        StringBuilder sb = new StringBuilder("");
224        char codingScheme = symbolID.charAt(0);
225
226        if (symbolID.startsWith("BS_") || symbolID.startsWith("BBS_") || symbolID.startsWith("PBS_"))
227        {
228            return symbolID;
229        }
230
231        if (symbolID.length() < 15)
232        {
233            while (symbolID.length() < 15)
234            {
235                symbolID += "-";
236            }
237        }
238        if (symbolID.length() > 15)
239        {
240            symbolID = symbolID.substring(0, 15);
241        }
242
243        if (symbolID != null && symbolID.length() == 15)
244        {
245            if (codingScheme == 'S' || //warfighting
246                    codingScheme == 'I' ||//sigint
247                    codingScheme == 'O' ||//stability operation
248                    codingScheme == 'E')//emergency management
249            {
250                sb.append(codingScheme);
251
252                if (SymbolUtilities.hasValidAffiliation(symbolID) == false)
253                {
254                    sb.append('U');
255                }
256                else
257                {
258                    sb.append(symbolID.charAt(1));
259                }
260
261                if (SymbolUtilities.hasValidBattleDimension(symbolID) == false)
262                {
263                    sb.append('Z');
264                    sb.replace(0, 1, "S");
265                }
266                else
267                {
268                    sb.append(symbolID.charAt(2));
269                }
270
271                if (SymbolUtilities.hasValidStatus(symbolID) == false)
272                {
273                    sb.append('P');
274                }
275                else
276                {
277                    sb.append(symbolID.charAt(3));
278                }
279
280                sb.append("------");
281                sb.append(symbolID.substring(10, 15));
282
283            }
284            else if (codingScheme == 'G')//tactical
285            {
286                sb.append(codingScheme);
287
288                if (SymbolUtilities.hasValidAffiliation(symbolID) == false)
289                {
290                    sb.append('U');
291                }
292                else
293                {
294                    sb.append(symbolID.charAt(1));
295                }
296
297                //if(SymbolUtilities.hasValidBattleDimension(SymbolID)==false)
298                sb.append('G');
299                //else
300                //    sb.append(SymbolID.charAt(2));
301
302                if (SymbolUtilities.hasValidStatus(symbolID) == false)
303                {
304                    sb.append('P');
305                }
306                else
307                {
308                    sb.append(symbolID.charAt(3));
309                }
310
311                if (isMultiPoint)
312                {
313                    sb.append("GAG---");//return a boundary
314                }
315                else
316                {
317                    sb.append("GPP---");//return an action point
318                }
319                sb.append(symbolID.substring(10, 15));
320
321            }
322            else if (codingScheme == 'W')//weather
323            {//no default weather graphic
324                return "SUZP-----------";//unknown
325            }
326            else//bad codingScheme
327            {
328                sb.append('S');
329                if (SymbolUtilities.hasValidAffiliation(symbolID) == false)
330                {
331                    sb.append('U');
332                }
333                else
334                {
335                    sb.append(symbolID.charAt(1));
336                }
337
338                if (SymbolUtilities.hasValidBattleDimension(symbolID) == false)
339                {
340                    sb.append('Z');
341                    //sb.replace(0, 1, "S");
342                }
343                else
344                {
345                    sb.append(symbolID.charAt(2));
346                }
347
348                if (SymbolUtilities.hasValidStatus(symbolID) == false)
349                {
350                    sb.append('P');
351                }
352                else
353                {
354                    sb.append(symbolID.charAt(3));
355                }
356
357                sb.append("------");
358                sb.append(symbolID.substring(10, 15));
359            }
360        }
361        else
362        {
363            return "SUZP-----------";//unknown
364        }
365        return sb.toString();
366    }
367
368    /**
369     * Returns true if the SymbolID has a valid Status (4th character)
370     *
371     * @param SymbolID
372     * @return
373     */
374    public static
375            Boolean hasValidStatus(String SymbolID)
376    {
377        if (SymbolID != null && SymbolID.length() >= 10)
378        {
379            char status = SymbolID.charAt(3);
380
381            char codingScheme = SymbolID.charAt(0);
382
383            if (codingScheme == 'S' || //warfighting
384                    codingScheme == 'I' ||//sigint
385                    codingScheme == 'O' ||//stability operation
386                    codingScheme == 'E')//emergency management
387            {
388                if (status == 'A'
389                        || status == 'P'
390                        || status == 'C'
391                        || status == 'D'
392                        || status == 'X'
393                        || status == 'F')
394                {
395                    return true;
396                }
397                else
398                {
399                    return false;
400                }
401            }
402            else if (codingScheme == 'G')
403            {
404                if (status == 'A'
405                        || status == 'S'
406                        || status == 'P'
407                        || status == 'K')
408                {
409                    return true;
410                }
411                else
412                {
413                    return false;
414                }
415            }
416            else if (codingScheme == 'W')
417            {
418                return true;//doesn't apply
419            }
420
421            return false;
422        }
423        else
424        {
425            return false;
426        }
427    }
428
429    /**
430     * Returns true if the SymbolID has a valid Affiliation (2nd character)
431     *
432     * @param SymbolID
433     * @return
434     */
435    public static
436            Boolean hasValidAffiliation(String SymbolID)
437    {
438        if (SymbolID != null && SymbolID.length() >= 10 && isWeather(SymbolID) == false)
439        {
440            char affiliation = SymbolID.charAt(1);
441            if (affiliation == 'P'
442                    || affiliation == 'U'
443                    || affiliation == 'A'
444                    || affiliation == 'F'
445                    || affiliation == 'N'
446                    || affiliation == 'S'
447                    || affiliation == 'H'
448                    || affiliation == 'G'
449                    || affiliation == 'W'
450                    || affiliation == 'M'
451                    || affiliation == 'D'
452                    || affiliation == 'L'
453                    || affiliation == 'J'
454                    || affiliation == 'K')
455            {
456                return true;
457            }
458            else
459            {
460                return false;
461            }
462        }
463        else
464        {
465            return false;
466        }
467    }
468
469    public static
470            Boolean hasValidCodingScheme(String symbolID)
471    {
472        if (symbolID != null && symbolID.length() > 0)
473        {
474            char codingScheme = symbolID.charAt(0);
475            if (codingScheme == 'S'
476                    || codingScheme == 'G'
477                    || codingScheme == 'W'
478                    || codingScheme == 'I'
479                    || codingScheme == 'O'
480                    || codingScheme == 'E')
481            {
482                return true;
483            }
484            else
485            {
486                return false;
487            }
488        }
489        else
490        {
491            return false;
492        }
493    }
494
495    /**
496     * Returns true if the SymbolID has a valid BattleDimension (3rd character)
497     * "Category" for tactical graphics
498     *
499     * @param SymbolID 15 character String
500     * @return
501     */
502    public static
503            Boolean hasValidBattleDimension(String SymbolID)
504    {
505        if (SymbolID != null && SymbolID.length() >= 10)
506        {
507            char codingScheme = SymbolID.charAt(0);
508            char bd = SymbolID.charAt(2);
509
510            if (codingScheme == 'S')//warfighting
511            {
512                if (bd == 'P'
513                        || bd == 'A'
514                        || bd == 'G'
515                        || bd == 'S'
516                        || bd == 'U'
517                        || bd == 'F'
518                        || //status == 'X' ||//doesn't seem to be a valid use for this one
519                        bd == 'Z')
520                {
521                    return true;
522                }
523                else
524                {
525                    return false;
526                }
527            }
528            else if (codingScheme == 'O')//stability operation
529            {
530                if (bd == 'V'
531                        || bd == 'L'
532                        || bd == 'O'
533                        || bd == 'I'
534                        || bd == 'P'
535                        || bd == 'G'
536                        || bd == 'R')
537                {
538                    return true;
539                }
540                else
541                {
542                    return false;
543                }
544            }
545            else if (codingScheme == 'E')//emergency management
546            {
547                if (bd == 'I'
548                        || bd == 'N'
549                        || bd == 'O'
550                        || bd == 'F')
551                {
552                    return true;
553                }
554                else
555                {
556                    return false;
557                }
558            }
559            else if (codingScheme == 'G')//tactical grahpic
560            {
561                if (bd == 'T'
562                        || bd == 'G'
563                        || bd == 'M'
564                        || bd == 'F'
565                        || bd == 'S'
566                        || bd == 'O')
567                {
568                    return true;
569                }
570                else
571                {
572                    return false;
573                }
574            }
575            else if (codingScheme == 'W')//weather
576            {
577                return true;//doesn't apply
578            }
579            else if (codingScheme == 'I')//sigint
580            {
581                if (bd == 'P'
582                        || bd == 'A'
583                        || bd == 'G'
584                        || bd == 'S'
585                        || bd == 'U'
586                        || //status == 'X' ||//doesn't seem to be a valid use for this one
587                        bd == 'Z')
588                {
589                    return true;
590                }
591                else
592                {
593                    return false;
594                }
595            }
596            else//bad codingScheme, can't confirm battle dimension
597            {
598                return false;
599            }
600        }
601        else
602        {
603            return false;
604        }
605    }
606
607    public static
608            Boolean hasValidCountryCode(String symbolID)
609    {
610        if (Character.isLetter(symbolID.charAt(12))
611                && Character.isLetter(symbolID.charAt(13)))
612        {
613            return true;
614        }
615        else
616        {
617            return false;
618        }
619    }
620
621    /**
622     * converts a Java Date object into a properly formated String for W or W1
623     *
624     * @param time
625     * @return
626     */
627    public static
628            String getDateLabel(Date time)
629    {
630
631        String modifierString = null;
632
633        String zulu = "";
634        zulu = dateFormatZulu.format(time);
635
636        if (zulu != null && zulu.length() == 5)
637        {
638
639            if (zulu.startsWith("+"))//Integer.valueOf doesn't like '+'
640            {
641                zulu = zulu.substring(1, 3);
642            }
643            else
644            {
645                zulu = zulu.substring(0, 3);
646            }
647
648            int intZulu = Integer.valueOf(zulu);
649
650            zulu = getZuluCharFromTimeZoneOffset(intZulu);
651        }
652        else
653        {
654            zulu = getZuluCharFromTimeZoneOffset(time);
655        }
656
657        modifierString = dateFormatFront.format(time) + zulu + dateFormatBack.format(time);
658
659        return modifierString.toUpperCase();
660    }
661
662    /**
663     * Given date, return character String representing which NATO time zone
664     * you're in.
665     *
666     * @param time
667     * @return
668     */
669    private static
670            String getZuluCharFromTimeZoneOffset(Date time)
671    {
672        TimeZone tz = TimeZone.getDefault();
673        Date offset = new Date(tz.getOffset(time.getTime()));
674        long lOffset = offset.getTime() / 3600000;//3600000 = (1000(ms)*60(s)*60(m))
675
676        int hour = (int) lOffset;
677
678        return getZuluCharFromTimeZoneOffset(hour);
679    }
680
681    /**
682     * Given hour offset from Zulu return character String representing which
683     * NATO time zone you're in.
684     *
685     * @param hour
686     * @return
687     */
688    private static
689            String getZuluCharFromTimeZoneOffset(int hour)
690    {
691        if (hour == 0)
692        {
693            return "Z";
694        }
695        else if (hour == -1)
696        {
697            return "N";
698        }
699        else if (hour == -2)
700        {
701            return "O";
702        }
703        else if (hour == -3)
704        {
705            return "P";
706        }
707        else if (hour == -4)
708        {
709            return "Q";
710        }
711        else if (hour == -5)
712        {
713            return "R";
714        }
715        else if (hour == -6)
716        {
717            return "S";
718        }
719        else if (hour == -7)
720        {
721            return "T";
722        }
723        else if (hour == -8)
724        {
725            return "U";
726        }
727        else if (hour == -9)
728        {
729            return "V";
730        }
731        else if (hour == -10)
732        {
733            return "W";
734        }
735        else if (hour == -11)
736        {
737            return "X";
738        }
739        else if (hour == -12)
740        {
741            return "Y";
742        }
743        else if (hour == 1)
744        {
745            return "A";
746        }
747        else if (hour == 2)
748        {
749            return "B";
750        }
751        else if (hour == 3)
752        {
753            return "C";
754        }
755        else if (hour == 4)
756        {
757            return "D";
758        }
759        else if (hour == 5)
760        {
761            return "E";
762        }
763        else if (hour == 6)
764        {
765            return "F";
766        }
767        else if (hour == 7)
768        {
769            return "G";
770        }
771        else if (hour == 8)
772        {
773            return "H";
774        }
775        else if (hour == 9)
776        {
777            return "I";
778        }
779        else if (hour == 10)
780        {
781            return "K";
782        }
783        else if (hour == 11)
784        {
785            return "L";
786        }
787        else if (hour == 12)
788        {
789            return "M";
790        }
791        else
792        {
793            return "-";
794        }
795    }
796
797    /**
798     *
799     * @param symbolID
800     * @param unitModifier
801     * @return
802     */
803    public static
804            boolean canUnitHaveModifier(String symbolID, int unitModifier)
805    {
806        boolean returnVal = false;
807        try
808        {
809            if (unitModifier == (ModifiersUnits.B_ECHELON))
810            {
811                return (SymbolUtilities.isUnit(symbolID) || SymbolUtilities.isSTBOPS(symbolID));
812            }
813            else if (unitModifier == (ModifiersUnits.C_QUANTITY))
814            {
815                return (SymbolUtilities.isEquipment(symbolID)
816                        || SymbolUtilities.isEMSEquipment(symbolID)
817                        || SymbolUtilities.isEMSIncident(symbolID));
818            }
819            else if (unitModifier == (ModifiersUnits.D_TASK_FORCE_INDICATOR))
820            {
821                return (SymbolUtilities.isUnit(symbolID)
822                        || SymbolUtilities.isSTBOPS(symbolID));
823            }
824            else if (unitModifier == (ModifiersUnits.F_REINFORCED_REDUCED))
825            {
826                return (SymbolUtilities.isUnit(symbolID)
827                        || SymbolUtilities.isSTBOPS(symbolID));
828            }
829            else if (unitModifier == (ModifiersUnits.G_STAFF_COMMENTS))
830            {
831                return (SymbolUtilities.isEMS(symbolID) == false);
832            }
833            else if (unitModifier == (ModifiersUnits.H_ADDITIONAL_INFO_1))
834            {
835                return true;
836            }
837            else if (unitModifier == (ModifiersUnits.J_EVALUATION_RATING))
838            {
839                return true;
840            }
841            else if (unitModifier == (ModifiersUnits.K_COMBAT_EFFECTIVENESS))
842            {
843                return (SymbolUtilities.isUnit(symbolID)
844                        || SymbolUtilities.isSTBOPS(symbolID)
845                        || (SymbolUtilities.hasInstallationModifier(symbolID) && SymbolUtilities.isEMS(symbolID) == false));
846            }
847            else if (unitModifier == (ModifiersUnits.L_SIGNATURE_EQUIP))
848            {
849                return (SymbolUtilities.isEquipment(symbolID)
850                        || SymbolUtilities.isSIGINT(symbolID));
851            }
852            else if (unitModifier == (ModifiersUnits.M_HIGHER_FORMATION))
853            {
854                return (SymbolUtilities.isUnit(symbolID)
855                        || SymbolUtilities.isSIGINT(symbolID));
856            }
857            else if (unitModifier == (ModifiersUnits.N_HOSTILE))
858            {
859                return (SymbolUtilities.isEquipment(symbolID));
860            }
861            else if (unitModifier == (ModifiersUnits.P_IFF_SIF))
862            {
863                return (symbolID.charAt(0) == 'S'
864                        || SymbolUtilities.isSTBOPS(symbolID));
865            }
866            else if (unitModifier == (ModifiersUnits.Q_DIRECTION_OF_MOVEMENT))
867            {
868                return ((SymbolUtilities.hasInstallationModifier(symbolID) == false)
869                        && (SymbolUtilities.isSIGINT(symbolID) == false));
870            }
871            else if (unitModifier == (ModifiersUnits.R_MOBILITY_INDICATOR))
872            {
873                return (SymbolUtilities.isEquipment(symbolID)
874                        || SymbolUtilities.isEMSEquipment(symbolID));
875            }
876            else if (unitModifier == (ModifiersUnits.R2_SIGNIT_MOBILITY_INDICATOR))
877            {
878                return (SymbolUtilities.isSIGINT(symbolID));
879            }
880            else if (unitModifier == (ModifiersUnits.S_HQ_STAFF_OR_OFFSET_INDICATOR))
881            {
882                return (SymbolUtilities.isSIGINT(symbolID) == false);
883            }
884            else if (unitModifier == (ModifiersUnits.T_UNIQUE_DESIGNATION_1))
885            {
886                return true;
887            }
888            else if (unitModifier == (ModifiersUnits.V_EQUIP_TYPE))
889            {
890                return (SymbolUtilities.isEquipment(symbolID)
891                        || SymbolUtilities.isSIGINT(symbolID)
892                        || SymbolUtilities.isEMSEquipment(symbolID));
893            }
894            else if (unitModifier == (ModifiersUnits.W_DTG_1))
895            {
896                return true;
897            }
898            else if (unitModifier == (ModifiersUnits.X_ALTITUDE_DEPTH))
899            {
900                return (SymbolUtilities.isSIGINT(symbolID) == false);
901            }
902            else if (unitModifier == (ModifiersUnits.Y_LOCATION))
903            {
904                return true;
905            }
906            else if (unitModifier == (ModifiersUnits.Z_SPEED))
907            {
908                return ((SymbolUtilities.hasInstallationModifier(symbolID) == false)
909                        && (SymbolUtilities.isSIGINT(symbolID) == false));
910            }
911            else if (unitModifier == (ModifiersUnits.AA_SPECIAL_C2_HQ))
912            {
913                return (SymbolUtilities.isUnit(symbolID)
914                        || SymbolUtilities.isSTBOPS(symbolID));
915            }
916            else if (unitModifier == (ModifiersUnits.AB_FEINT_DUMMY_INDICATOR))
917            {
918                return ((SymbolUtilities.isSIGINT(symbolID) == false)
919                        && (SymbolUtilities.isEMS(symbolID) == false));
920            }
921            else if (unitModifier == (ModifiersUnits.AC_INSTALLATION))
922            {
923                return (SymbolUtilities.isSIGINT(symbolID) == false);
924            }
925            else if (unitModifier == (ModifiersUnits.AD_PLATFORM_TYPE))
926            {
927                return (SymbolUtilities.isSIGINT(symbolID));
928            }
929            else if (unitModifier == (ModifiersUnits.AE_EQUIPMENT_TEARDOWN_TIME))
930            {
931                return (SymbolUtilities.isSIGINT(symbolID));
932            }
933            else if (unitModifier == (ModifiersUnits.AF_COMMON_IDENTIFIER))
934            {
935                return (SymbolUtilities.isSIGINT(symbolID));
936            }
937            else if (unitModifier == (ModifiersUnits.AG_AUX_EQUIP_INDICATOR))
938            {
939                return (SymbolUtilities.isEquipment(symbolID));
940            }
941            else if (unitModifier == (ModifiersUnits.AH_AREA_OF_UNCERTAINTY)
942                    || unitModifier == (ModifiersUnits.AI_DEAD_RECKONING_TRAILER)
943                    || unitModifier == (ModifiersUnits.AJ_SPEED_LEADER))
944            {
945                return ((SymbolUtilities.isSIGINT(symbolID) == false)
946                        && (SymbolUtilities.hasInstallationModifier(symbolID) == false));
947            }
948            else if (unitModifier == (ModifiersUnits.AK_PAIRING_LINE))
949            {
950                return ((SymbolUtilities.isSIGINT(symbolID) == false)
951                        && (SymbolUtilities.isEMS(symbolID) == false)
952                        && (SymbolUtilities.hasInstallationModifier(symbolID) == false));
953            }
954            else if (unitModifier == (ModifiersUnits.AL_OPERATIONAL_CONDITION))
955            {
956                return (SymbolUtilities.isUnit(symbolID) == false);
957            }
958            else if (unitModifier == (ModifiersUnits.AO_ENGAGEMENT_BAR))
959            {
960                return ((SymbolUtilities.isEquipment(symbolID)
961                        || SymbolUtilities.isUnit(symbolID)
962                        || SymbolUtilities.hasInstallationModifier(symbolID))
963                        && SymbolUtilities.isEMS(symbolID) == false);
964            } //out of order because used less often
965            else if (unitModifier == (ModifiersUnits.A_SYMBOL_ICON))
966            {
967                return true;
968            }
969            else if (unitModifier == (ModifiersUnits.E_FRAME_SHAPE_MODIFIER))
970            {
971                //return (SymbolUtilities.isSIGINT(symbolID)==false);
972                //not sure why milstd say sigint don't have it.
973                //they clearly do.
974                return true;
975            }
976            else if(unitModifier == (ModifiersUnits.SCC_SONAR_CLASSIFICATION_CONFIDENCE))
977            {
978                if(SymbolUtilities.isSubSurface(symbolID))
979                {
980                    //these symbols only exist in 2525C
981                    String temp = symbolID.substring(4, 10);
982                    if(temp.equals("WMGC--") ||
983                            temp.equals("WMMC--") ||
984                            temp.equals("WMFC--") ||
985                            temp.equals("WMC---"))
986                    {
987                        return true;
988                    }
989                }
990                return false;
991            }
992            else
993            {
994                return false;
995            }
996
997        }
998        catch (Exception exc)
999        {
1000            ErrorLogger.LogException("SymbolUtilties", "canHaveModifier", exc);
1001        }
1002        return returnVal;
1003    }
1004
1005    public static
1006            Boolean hasModifier(String symbolID, int modifier)
1007    {
1008        return hasModifier(symbolID, modifier, rendererSettings.getSymbologyStandard());
1009    }
1010
1011    /**
1012     *
1013     * @param symbolID
1014     * @param modifier - from the constants ModifiersUnits or ModifiersTG
1015     * @param symStd - 0=2525B, 1=2525C. Constants available in
1016     * RendererSettings.
1017     * @return
1018     */
1019    public static
1020            Boolean hasModifier(String symbolID, int modifier, int symStd)
1021    {
1022        Boolean returnVal = false;
1023
1024        if (isTacticalGraphic(symbolID) == true)
1025        {
1026            returnVal = canSymbolHaveModifier(symbolID, modifier, symStd);
1027        }
1028        else
1029        {
1030            returnVal = canUnitHaveModifier(symbolID, modifier);
1031        }
1032        return returnVal;
1033    }
1034
1035    ;
1036
1037      /**
1038       * Checks if a tactical graphic has the passed modifier.
1039       * @param symbolID - symbolID of Tactical Graphic
1040       * @param tgModifier - ModifiersTG.AN_AZIMUTH
1041       * @return 
1042       */
1043      public static
1044            boolean canSymbolHaveModifier(String symbolID, int tgModifier)
1045    {
1046        return canSymbolHaveModifier(symbolID, tgModifier, rendererSettings.getSymbologyStandard());
1047    }
1048
1049    /**
1050     * Checks if a tactical graphic has the passed modifier.
1051     *
1052     * @param symbolID - symbolID of Tactical Graphic
1053     * @param tgModifier - ModifiersTG.AN_AZIMUTH
1054     * @param symStd - like RendererSettings.Symbology_2525C
1055     * @return
1056     */
1057    public static boolean canSymbolHaveModifier(String symbolID, int tgModifier, int symStd)
1058    {
1059        String basic = null;
1060        SymbolDef sd = null;
1061        boolean returnVal = false;
1062        String modCode = ModifiersTG.getModifierLetterCode(tgModifier);
1063        try
1064        {
1065
1066            basic = SymbolUtilities.getBasicSymbolID(symbolID);
1067            sd = SymbolDefTable.getInstance().getSymbolDef(basic, symStd);
1068            if (sd != null && modCode.equals("") == false)
1069            {
1070                int dc = sd.getDrawCategory();
1071                if (tgModifier == (ModifiersTG.AM_DISTANCE))
1072                {
1073                    switch (dc)
1074                    {
1075                        case SymbolDef.DRAW_CATEGORY_RECTANGULAR_PARAMETERED_AUTOSHAPE:
1076                        case SymbolDef.DRAW_CATEGORY_SECTOR_PARAMETERED_AUTOSHAPE:
1077                        case SymbolDef.DRAW_CATEGORY_TWO_POINT_RECT_PARAMETERED_AUTOSHAPE:
1078                            returnVal = true;
1079                            break;
1080                        case SymbolDef.DRAW_CATEGORY_CIRCULAR_PARAMETERED_AUTOSHAPE:
1081                        case SymbolDef.DRAW_CATEGORY_CIRCULAR_RANGEFAN_AUTOSHAPE:
1082                            returnVal = true;
1083                            break;
1084                        case SymbolDef.DRAW_CATEGORY_LINE://air corridor
1085                                if(sd.getModifiers().indexOf(modCode + ".") > -1)
1086                                        returnVal = true;
1087                            break;
1088                        default:
1089                            returnVal = false;
1090                    }
1091                }
1092                else if (tgModifier == (ModifiersTG.AN_AZIMUTH))
1093                {
1094                    switch (dc)
1095                    {
1096                        case SymbolDef.DRAW_CATEGORY_RECTANGULAR_PARAMETERED_AUTOSHAPE:
1097                        case SymbolDef.DRAW_CATEGORY_SECTOR_PARAMETERED_AUTOSHAPE:
1098                            returnVal = true;
1099                            break;
1100                        default:
1101                            returnVal = false;
1102                    }
1103                }
1104                else
1105                {
1106                    if (sd.getModifiers().indexOf(modCode + ".") > -1)
1107                    {
1108                        returnVal = true;
1109                    }
1110                }
1111            }
1112
1113            return returnVal;
1114
1115        }
1116        catch (Exception exc)
1117        {
1118            ErrorLogger.LogException("SymbolUtilities", "canSymbolHaveModifier", exc);
1119        }
1120        return returnVal;
1121    }
1122
1123
1124    /**
1125     * Gets line color used if no line color has been set. The color is
1126     * specified based on the affiliation of the symbol and whether it is a unit
1127     * or not.
1128     *
1129     * @param symbolID
1130     * @return
1131     */
1132    public static Color getLineColorOfAffiliation(String symbolID)
1133    {
1134        Color retColor = null;
1135        String basicSymbolID = getBasicSymbolID(symbolID);
1136        try
1137        {
1138            // We can't get the fill color if there is no symbol id, since that also means there is no affiliation
1139            if ((symbolID == null) || (symbolID.equals("")))
1140            {
1141                return retColor;
1142            }
1143
1144            if (SymbolUtilities.isTacticalGraphic(symbolID))// && !SymbolUtilities.isTGWithFill(symbolID))
1145            {
1146                if ((symbolID.substring(0, 4).equals("ESRI")) || SymbolUtilities.isJWARN(symbolID))
1147                {
1148                    //retColor = Color.BLACK;//0x000000;        // Black
1149                    retColor =  rendererSettings.getFriendlyGraphicLineColor();
1150                }
1151                else if (SymbolUtilities.isWeather(symbolID))
1152                {
1153                    retColor = getLineColorOfWeather(symbolID);
1154                }
1155                else if (SymbolUtilities.isObstacle(symbolID))
1156                {
1157                    //retColor = Color.GREEN;   // Green
1158                    retColor =  rendererSettings.getNeutralGraphicLineColor();
1159                }
1160                else if ((SymbolUtilities.isNBC(symbolID))
1161                        && (basicSymbolID.equals("G*M*NR----****X") == true || //Radioactive Area
1162                        basicSymbolID.equals("G*M*NC----****X") == true || //Chemically Contaminated Area
1163                        basicSymbolID.equals("G*M*NB----****X") == true)) //Biologically Contaminated Area
1164                {
1165                    //retColor = Color.BLACK;//0xffff00;
1166                    retColor =  rendererSettings.getFriendlyGraphicLineColor();//
1167                }
1168                else if(SymbolUtilities.isEMSNaturalEvent(symbolID))
1169                {
1170                    //retColor = Color.BLACK;//0xffff00;
1171                    retColor =  rendererSettings.getFriendlyGraphicLineColor();
1172                }
1173                else
1174                {
1175                    String switchChar = symbolID.substring(1, 2);
1176                    if (switchChar.equals("F")
1177                            || switchChar.equals("A")
1178                            || switchChar.equals("D")
1179                            || switchChar.equals("M"))
1180                    {
1181                        retColor =  rendererSettings.getFriendlyGraphicLineColor();
1182                    }
1183                    else if (switchChar.equals("H")
1184                            || switchChar.equals("S")
1185                            || switchChar.equals("J")
1186                            || switchChar.equals("K"))
1187                    {
1188
1189                        if (SymbolUtilities.getBasicSymbolID(symbolID).equals("G*G*GLC---****X")) // Line of Contact
1190                        {
1191                            //retColor = Color.BLACK;//0x000000;        // Black
1192                            retColor = rendererSettings.getFriendlyGraphicLineColor();
1193                        }
1194                        else
1195                        {
1196                            //retColor = Color.RED;//0xff0000;  // Red
1197                            retColor = rendererSettings.getHostileGraphicLineColor();
1198                        }
1199
1200                    }
1201                    else if (switchChar.equals("N")
1202                            || switchChar.equals("L")) // Neutral:
1203                    {
1204                        //retColor = Color.GREEN;//0x00ff00;    // Green
1205                        retColor = rendererSettings.getNeutralGraphicLineColor();
1206
1207                    }
1208                    else if (switchChar.equals("U")
1209                            || switchChar.equals("P")
1210                            || switchChar.equals("O")
1211                            || switchChar.equals("G")
1212                            || switchChar.equals("W"))
1213                    {
1214                        if (symbolID.substring(0, 8).equals("WOS-HDS-"))
1215                        {
1216                            retColor = Color.GRAY;//0x808080;   // Gray
1217                        }
1218                        else
1219                        {
1220                            //retColor = Color.YELLOW;//0xffff00;       // Yellow
1221                            retColor =  rendererSettings.getUnknownGraphicLineColor();
1222                        }
1223
1224                    }
1225                    else
1226                    {
1227                        //retColor = Color.black;//null;//0;//Color.Empty;
1228                        retColor = rendererSettings.getFriendlyGraphicLineColor();
1229                    }   // End default
1230
1231                }       // End else
1232            }// End if (SymbolUtilities.IsTacticalGraphic(this.SymbolID))
1233            else
1234            {
1235                //stopped doing check because all warfighting
1236                //should have black for line color.
1237                //retColor = Color.BLACK;
1238                retColor = rendererSettings.getFriendlyUnitLineColor();
1239            }   // End else
1240        } // End try
1241        catch (Exception e)
1242        {
1243            // Log Error
1244            ErrorLogger.LogException("SymbolUtilties", "getLineColorOfAffiliation", e);
1245            //throw e;
1246        }       // End catch
1247        return retColor;
1248    }   // End get LineColorOfAffiliation
1249
1250    /**
1251     * Is the fill color used if no fill color has been set. The color is
1252     * specified based on the affiliation of the symbol and whether it is a unit
1253     * or not.
1254     *
1255     * @param symbolID
1256     * @return
1257     */
1258    public static Color getFillColorOfAffiliation(String symbolID)
1259    {
1260        Color retColor = null;
1261        String basicSymbolID = getBasicSymbolID(symbolID);
1262
1263        try
1264        {
1265            char switchChar;
1266            // We can't get the fill color if there is no symbol id, since that also means there is no affiliation
1267            if ((symbolID == null) || (symbolID.equals("")))
1268            {
1269                return retColor;
1270            }
1271
1272            if (basicSymbolID.equals("G*M*NZ----****X") ||//ground zero
1273                    //basicSymbolID.equals("G*M*NF----****X") || //fallout producing
1274                    basicSymbolID.equals("G*M*NEB---****X") ||//biological
1275                    basicSymbolID.equals("G*M*NEC---****X"))//chemical
1276            {
1277                //retColor = AffiliationColors.UnknownUnitFillColor;//  Color.yellow;
1278                retColor = rendererSettings.getUnknownUnitFillColor();
1279            }
1280            else if (SymbolUtilities.isTacticalGraphic(symbolID) && !SymbolUtilities.isTGSPWithFill(symbolID))
1281            {
1282                if (basicSymbolID.equals("G*M*NZ----****X") ||//ground zero
1283                        //basicSymbolID.equals("G*M*NF----****X") || //fallout producing
1284                        basicSymbolID.equals("G*M*NEB---****X") ||//biological
1285                        basicSymbolID.equals("G*M*NEC---****X"))//chemical
1286                {
1287                    //retColor = Color.yellow;
1288                    retColor = rendererSettings.getUnknownUnitFillColor();
1289                }
1290                else
1291                {
1292                    switchChar = symbolID.charAt(1);
1293                    if (switchChar == 'F'
1294                            || switchChar == 'A'
1295                            || switchChar == 'D'
1296                            || switchChar == 'M')
1297                    {
1298                        //retColor = AffiliationColors.FriendlyGraphicFillColor;//0x00ffff;     // Cyan
1299                        retColor = rendererSettings.getFriendlyGraphicFillColor();
1300
1301                    }
1302                    else if (switchChar == 'H'
1303                            || switchChar == 'S'
1304                            || switchChar == 'J'
1305                            || switchChar == 'K')
1306                    {
1307                        //retColor = AffiliationColors.HostileGraphicFillColor;//0xfa8072;      // Salmon
1308                        retColor = rendererSettings.getHostileGraphicFillColor();
1309
1310                    }
1311                    else if (switchChar == 'N'
1312                            || switchChar == 'L')
1313                    {
1314                        //retColor = AffiliationColors.NeutralGraphicFillColor;//0x7fff00;      // Light Green
1315                        retColor = rendererSettings.getNeutralGraphicFillColor();
1316                    }
1317                    else if (switchChar == 'U'
1318                            || switchChar == 'P'
1319                            || switchChar == 'O'
1320                            || switchChar == 'G'
1321                            || switchChar == 'W')
1322                    {
1323                        retColor = new Color(255, 250, 205);// yellowish //0xfffacd;    // LemonChiffon 255 250 205
1324                    }
1325                    else
1326                    {
1327                        //retColor = AffiliationColors.UnknownGraphicFillColor;
1328                        retColor = rendererSettings.getUnknownGraphicFillColor();
1329                    }
1330                }
1331            } // End if(SymbolUtilities.IsTacticalGraphic(this._strSymbolID))
1332            else
1333            {
1334                switchChar = symbolID.charAt(1);
1335                if (switchChar == 'F'
1336                        || switchChar == 'A'
1337                        || switchChar == 'D'
1338                        || switchChar == 'M')
1339                {
1340                    //retColor = AffiliationColors.FriendlyUnitFillColor;//0x00ffff;    // Cyan
1341                    retColor = rendererSettings.getFriendlyUnitFillColor();
1342
1343                }
1344                else if (switchChar == 'H'
1345                        || switchChar == 'S'
1346                        || switchChar == 'J'
1347                        || switchChar == 'K')
1348                {
1349                    //retColor = AffiliationColors.HostileUnitFillColor;//0xfa8072;     // Salmon
1350                    retColor = rendererSettings.getHostileUnitFillColor();
1351
1352                }
1353                else if (switchChar == 'N'
1354                        || switchChar == 'L')
1355                {
1356                    //retColor = AffiliationColors.NeutralUnitFillColor;//0x7fff00;     // Light Green
1357                    retColor = rendererSettings.getNeutralUnitFillColor();
1358
1359                }
1360                else if (switchChar == 'U'
1361                        || switchChar == 'P'
1362                        || switchChar == 'O'
1363                        || switchChar == 'G'
1364                        || switchChar == 'W')
1365                {
1366                    //retColor = AffiliationColors.UnknownUnitFillColor;//new Color(255,250, 205); //0xfffacd;  // LemonChiffon 255 250 205
1367                    retColor = rendererSettings.getUnknownUnitFillColor();
1368                }
1369                else
1370                {
1371                    //retColor = AffiliationColors.UnknownUnitFillColor;//null;
1372                    retColor = rendererSettings.getUnknownUnitFillColor();
1373                }
1374
1375            }   // End else
1376        } // End try
1377        catch (Exception e)
1378        {
1379            // Log Error
1380            ErrorLogger.LogException("SymbolUtilties", "getFillColorOfAffiliation", e);
1381            //throw e;
1382        }       // End catch
1383
1384        return retColor;
1385    }   // End FillColorOfAffiliation
1386
1387    public static
1388            Color getLineColorOfWeather(String symbolID)
1389    {
1390        Color retColor = Color.BLACK;
1391        // Get the basic id
1392        //String symbolID = SymbolUtilities.getBasicSymbolID(symbolID);
1393
1394        //if(symbolID.equals(get))
1395        if(symbolID.equals("WAS-WSGRL-P----") || // Hail - Light not Associated With Thunder
1396            symbolID.equals("WAS-WSGRMHP----") || // Hail - Moderate/Heavy not Associated with Thunder
1397            symbolID.equals("WAS-PL----P----") || // Low Pressure Center - Pressure Systems
1398            symbolID.equals("WAS-PC----P----") || // Cyclone Center - Pressure Systems
1399            symbolID.equals("WAS-WSIC--P----") || // Ice Crystals (Diamond Dust)
1400            symbolID.equals("WAS-WSPLL-P----") || // Ice Pellets - Light
1401            symbolID.equals("WAS-WSPLM-P----") || // Ice Pellets - Moderate
1402            symbolID.equals("WAS-WSPLH-P----") || // Ice Pellets - Heavy
1403            symbolID.equals("WAS-WST-NPP----") || // Thunderstorm - No Precipication
1404            symbolID.equals("WAS-WSTMR-P----") || // Thunderstorm Light to Moderate with Rain/Snow - No Hail
1405            symbolID.equals("WAS-WSTHR-P----") || // Thunderstorm Heavy with Rain/Snow - No Hail
1406            symbolID.equals("WAS-WSTMH-P----") || // Thunderstorm Light to Moderate - With Hail
1407            symbolID.equals("WAS-WSTHH-P----") || // Thunderstorm Heavy - With Hail
1408            symbolID.equals("WAS-WST-FCP----") || // Funnel Cloud (Tornado/Waterspout)
1409            symbolID.equals("WAS-WST-SQP----") || // Squall
1410            symbolID.equals("WAS-WST-LGP----") || // Lightning
1411            symbolID.equals("WAS-WSFGFVP----") || // Fog - Freezing, Sky Visible
1412            symbolID.equals("WAS-WSFGFOP----") || // Fog - Freezing, Sky not Visible
1413            symbolID.equals("WAS-WSTSD-P----") || // Tropical Depression
1414            symbolID.equals("WAS-WSTSS-P----") || // Tropical Storm
1415            symbolID.equals("WAS-WSTSH-P----") || // Hurricane/Typhoon
1416            symbolID.equals("WAS-WSRFL-P----") || // Freezing Rain - Light
1417            symbolID.equals("WAS-WSRFMHP----") || // Freezing Rain - Moderate/Heavy
1418            symbolID.equals("WAS-WSDFL-P----") || // Freezing Drizzle - Light
1419            symbolID.equals("WAS-WSDFMHP----") || // Freezing Drizzle - Moderate/Heavy
1420            symbolID.equals("WOS-HHDMDBP----") || //mine-naval (doubtful)
1421            symbolID.equals("WOS-HHDMDFP----") || // mine-naval (definited)
1422            symbolID.substring(0,7).equals("WA-DPFW") || //warm front
1423            //symbolID.substring(0,7).equals("WA-DPFS")//stationary front (actually, it's red & blue)
1424            symbolID.equals("WA-DBAIF----A--") || // INSTRUMENT FLIGHT RULE (IFR)
1425            symbolID.equals("WA-DBAFP----A--") || // 
1426            symbolID.equals("WA-DBAT-----A--") || // 
1427            symbolID.equals("WA-DIPIS---L---") || // 
1428            symbolID.equals("WA-DIPTH---L---") || // 
1429            symbolID.equals("WA-DWJ-----L---") || // Jet Stream  
1430            symbolID.equals("WO-DGMSB----A--") || //
1431            symbolID.equals("WO-DGMRR----A--") ||
1432            symbolID.equals("WO-DGMCH----A--") ||
1433            symbolID.equals("WO-DGMIBE---A--") ||
1434            symbolID.equals("WO-DGMBCC---A--") ||
1435            symbolID.equals("WO-DOBVI----A--"))
1436
1437        {
1438            retColor = Color.RED;//0xff0000;    // Red
1439        }
1440        else if(symbolID.equals("WAS-PH----P----") || // High Pressure Center - Pressure Systems
1441                symbolID.equals("WAS-PA----P----")  || // Anticyclone Center - Pressure Systems
1442                symbolID.equals("WA-DBAMV----A--")  || // MARGINAL VISUAL FLIGHT RULE (MVFR)
1443                symbolID.equals("WA-DBATB----A--")  || // BOUNDED AREAS OF WEATHER / TURBULENCE
1444                symbolID.substring(0,5).equals("WAS-T")  || // Turbulence
1445                symbolID.substring(0,7).equals("WA-DPFC") || //cold front
1446                symbolID.equals("WO-DGMIBA---A--"))
1447        {
1448            retColor = Color.BLUE;
1449        }
1450        else if(
1451        symbolID.equals("WAS-WSFGPSP----") || // Fog - Shallow Patches
1452        symbolID.equals("WAS-WSFGCSP----") || // Fog - Shallow Continuous
1453        symbolID.equals("WAS-WSFGP-P----") || // Fog - Patchy
1454        symbolID.equals("WAS-WSFGSVP----") || // Fog - Sky Visible
1455        symbolID.equals("WAS-WSFGSOP----") || // Fog - Sky Obscured
1456        symbolID.equals("WA-DBAFG----A--") || // Fog
1457        symbolID.equals("WO-DGMRM----A--") ||
1458        symbolID.equals("WO-DGMCM----A--") ||
1459        symbolID.equals("WO-DGMIBC---A--") ||
1460        symbolID.equals("WO-DGMBCB---A--") ||
1461        symbolID.equals("WO-DGMBTE---A--") ||
1462        symbolID.equals("WAS-WSBR--P----")) // Mist
1463        {
1464            retColor = Color.YELLOW;//0xffff00; // Yellow
1465        }
1466        else if(
1467        symbolID.equals("WAS-WSFU--P----") || // Smoke
1468        symbolID.equals("WAS-WSHZ--P----") || // Haze
1469        symbolID.equals("WAS-WSDSLMP----") || // Dust/Sand Storm - Light to Moderate
1470        symbolID.equals("WAS-WSDSS-P----") || // Dust/Sand Storm - Severe
1471        symbolID.equals("WAS-WSDD--P----") || // Dust Devil
1472        symbolID.equals("WA-DBAD-----A--") || // Dust or Sand
1473        symbolID.equals("WAS-WSBD--P----")) // Blowing Dust or Sand
1474        {
1475            retColor = new Color(165,42,42);  //165 42 42 //0xa52a2a;   // Brown
1476        }
1477        else if(
1478        symbolID.equals("WA-DBALPNC--A--") || // 
1479        symbolID.equals("WA-DBALPC---A--") || // 
1480        symbolID.equals("WA-DIPID---L---") || // 
1481        symbolID.equals("WO-DGMSIM---A--") || //
1482        symbolID.equals("WO-DGMRS----A--") ||
1483        symbolID.equals("WO-DGMCL----A--") ||
1484        symbolID.equals("WO-DGMIBB---A--") ||
1485        symbolID.equals("WO-DGMBCA---A--") ||
1486        symbolID.equals("WAS-WSR-LIP----") || // Rain - Intermittent Light
1487        symbolID.equals("WAS-WSR-LCP----") || // Rain - Continuous Light
1488        symbolID.equals("WAS-WSR-MIP----") || // Rain - Intermittent Moderate
1489        symbolID.equals("WAS-WSR-MCP----") || // Rain - Continuous Moderate
1490        symbolID.equals("WAS-WSR-HIP----") || // Rain - Intermittent Heavy
1491        symbolID.equals("WAS-WSR-HCP----") || // Rain - Continuous Heavy
1492        symbolID.equals("WAS-WSRSL-P----") || // Rain Showers - Light
1493        symbolID.equals("WAS-WSRSMHP----") || // Rain Showers - Moderate/Heavy
1494        symbolID.equals("WAS-WSRST-P----") || // Rain Showers - Torrential
1495        symbolID.equals("WAS-WSD-LIP----") || // Drizzle - Intermittent Light
1496        symbolID.equals("WAS-WSD-LCP----") || // Drizzle - Continuous Light
1497        symbolID.equals("WAS-WSD-MIP----") || // Drizzle - Intermittent Moderate
1498        symbolID.equals("WAS-WSD-MCP----") || // Drizzle - Continuous Moderate
1499        symbolID.equals("WAS-WSD-HIP----") || // Drizzle - Intermittent Heavy
1500        symbolID.equals("WAS-WSD-HCP----") || // Drizzle - Continuous Heavy
1501        symbolID.equals("WAS-WSM-L-P----") || // Rain or Drizzle and Snow - Light
1502        symbolID.equals("WAS-WSM-MHP----") || // Rain or Drizzle and Snow - Moderate/Heavy
1503        symbolID.equals("WAS-WSMSL-P----") || // Rain and Snow Showers - Light
1504        symbolID.equals("WAS-WSMSMHP----") || // Rain and Snow Showers - Moderate/Heavy
1505        symbolID.equals("WAS-WSUKP-P----") || // Precipitation of unknown type & intensity
1506        symbolID.equals("WAS-WSS-LIP----") || // Snow - Intermittent Light
1507        symbolID.equals("WAS-WSS-LCP----") || // Snow - Continuous Light
1508        symbolID.equals("WAS-WSS-MIP----") || // Snow - Intermittent Moderate
1509        symbolID.equals("WAS-WSS-MCP----") || // Snow - Continuous Moderate
1510        symbolID.equals("WAS-WSS-HIP----") || // Snow - Intermittent Heavy
1511        symbolID.equals("WAS-WSS-HCP----") || // Snow - Continuous Heavy
1512        symbolID.equals("WAS-WSSBLMP----") || // Blowing Snow - Light/Moderate
1513        symbolID.equals("WAS-WSSBH-P----") || // Blowing Snow - Heavy
1514        symbolID.equals("WAS-WSSG--P----") || // Snow Grains
1515        symbolID.equals("WAS-WSSSL-P----") || // Snow Showers - Light
1516        symbolID.equals("WAS-WSSSMHP----")) // Snow Showers - Moderate/Heavy
1517        {
1518            retColor = Color.GREEN;// 0x00ff00; // Green
1519        }
1520        else if(symbolID.equals("WO-DHCF----L---") || //
1521                symbolID.equals("WO-DHCF-----A--"))
1522        {
1523            retColor = new Color(173,255,47);// 0xADFF2F;// GreenYellow
1524        }
1525        else if(symbolID.startsWith("WAS-IC") || // Clear Icing
1526                                    symbolID.startsWith("WAS-IR")  || // Rime Icing
1527                                    symbolID.startsWith("WAS-IM")) // Mixed Icing
1528        {
1529            retColor = new Color(128,96,16);
1530        }
1531        else if(symbolID.equals("WOS-HDS---P----")|| // Soundings
1532            symbolID.equals("WOS-HHDF--P----")||//foul ground
1533            symbolID.equals("WO-DHHDF----A--")||//foul ground
1534            symbolID.equals("WOS-HPFS--P----")||//fish stakes/traps/weirs
1535            symbolID.equals("WOS-HPFS---L---")||//fish stakes
1536            symbolID.equals("WOS-HPFF----A--")||//fish stakes/traps/weirs
1537            symbolID.equals("WO-DHDDL---L---")||//depth curve
1538            symbolID.equals("WO-DHDDC---L---")||//depth contour
1539            symbolID.equals("WO-DHCC----L---")||//coastline
1540            symbolID.equals("WO-DHPBP---L---")||//ports
1541            symbolID.equals("WO-DHPMO---L---")||//offshore loading
1542            symbolID.equals("WO-DHPSPA--L---")||//sp above water
1543            symbolID.equals("WO-DHPSPB--L---")||//sp below water
1544            symbolID.equals("WO-DHPSPS--L---")||//sp sea wall
1545            symbolID.equals("WO-DHHDK--P----")||//kelp seaweed
1546            symbolID.equals("WO-DHHDK----A--")||//kelp seaweed
1547            symbolID.equals("WO-DHHDB---L---")||//breakers
1548            symbolID.equals("WO-DTCCCFE-L---")||//current flow - ebb
1549            symbolID.equals("WO-DTCCCFF-L---")||//current flow - flood
1550            symbolID.equals("WOS-TCCTD-P----")||//tide data point    
1551            symbolID.equals("WO-DHCW-----A--")||
1552            symbolID.equals("WO-DMOA-----A--") ||
1553            symbolID.equals("WO-DMPA----L---"))//water
1554            retColor = Color.GRAY;//0x808080;   // Gray
1555        else if(
1556            symbolID.equals("WO-DBSM-----A--") ||
1557            symbolID.equals("WO-DBSF-----A--") ||
1558            symbolID.equals("WO-DGMN-----A--")) // 
1559        {
1560                retColor = new Color(230,230,230);//230,230,230;        // light gray
1561        }
1562        else if(
1563            symbolID.equals("WO-DBSG-----A--") ||
1564                    symbolID.equals("WO-DBST-----A--")) //
1565        {
1566                retColor = new Color(169,169,169);//169,169,169;        // dark gray
1567        }
1568        else if(
1569        symbolID.equals("WAS-WSVE--P----") || // Volcanic Eruption
1570        symbolID.equals("WAS-WSVA--P----") || // Volcanic Ash
1571        symbolID.equals("WAS-WST-LVP----") || // Tropopause Level
1572        symbolID.equals("WAS-WSF-LVP----")) // Freezing Level
1573        {
1574                retColor = Color.BLACK;//0x000000;      // Black
1575        }
1576        else if(
1577        symbolID.equals("WOS-HPBA--P----") || // anchorage
1578        symbolID.equals("WOS-HPBA---L---") || // anchorage
1579        symbolID.equals("WOS-HPBA----A--") || // anchorage
1580        symbolID.equals("WOS-HPCP--P----") || // call in point
1581        symbolID.equals("WOS-HPFH--P----") || // fishing harbor
1582        symbolID.equals("WOS-HPM-FC-L---") || //ferry crossing
1583        symbolID.equals("WOS-HABM--P----") || //marker
1584        symbolID.equals("WOS-HAL---P----") || //light
1585        symbolID.equals("WA-DIPIT---L---") || //ISOTACH
1586        symbolID.equals("WOS-TCCTG-P----") || // Tide gauge
1587        symbolID.equals("WO-DL-ML---L---") ||
1588        symbolID.equals("WOS-HPM-FC-L---") ||
1589        symbolID.equals("WO-DL-RA---L---") ||
1590        symbolID.equals("WO-DHPBA---L---") ||
1591        symbolID.equals("WO-DMCA----L---") ||
1592        symbolID.equals("WO-DHPBA----A--") ||
1593        symbolID.equals("WO-DL-MA----A--") ||
1594        symbolID.equals("WO-DL-SA----A--") ||
1595        symbolID.equals("WO-DL-TA----A--") ||
1596        symbolID.equals("WO-DGMSR----A--")) 
1597        {
1598            retColor = new Color(255,0,255);//magenta
1599        }
1600        else if(symbolID.substring(0,7).equals("WA-DPFO")//occluded front
1601        )
1602        {
1603            retColor = new Color(226,159,255);//light purple
1604        }
1605        else if(
1606        symbolID.equals("WA-DPXITCZ-L---") || // inter-tropical convergance zone oragne?
1607        symbolID.equals("WO-DL-O-----A--") ||
1608        symbolID.equals("WA-DPXCV---L---")) // 
1609        {
1610            retColor = new Color(255,165,0);//orange
1611        }
1612        else if(
1613        symbolID.equals("WA-DBAI-----A--") || //BOUNDED AREAS OF WEATHER / ICING
1614        symbolID.startsWith("WAS-IC") || // clear icing
1615        symbolID.startsWith("WAS-IR") || // rime icing
1616        symbolID.startsWith("WAS-IM")) // mixed icing
1617        {
1618            retColor = new Color(128,96,16);//mud?
1619        }
1620        else if(
1621        symbolID.equals("WO-DHCI-----A--") || //Island
1622        symbolID.equals("WO-DHCB-----A--") || //Beach
1623        symbolID.equals("WO-DHPMO----A--")||//offshore loading
1624        symbolID.equals("WO-DHCI-----A--")) // mixed icing
1625        {
1626            retColor = new Color(210,176,106);//light/soft brown
1627        }
1628        else if(symbolID.equals("WO-DOBVA----A--")
1629        )
1630        {
1631            retColor = new Color(26,153,77);//dark green
1632        }
1633        else if(symbolID.equals("WO-DGMBTI---A--")
1634        )
1635        {
1636            retColor = new Color(255,48,0);//orange red
1637        }
1638        else if(symbolID.equals("WO-DGMBTH---A--")
1639        )
1640        {
1641            retColor = new Color(255,80,0);//dark orange
1642        }
1643        //255,127,0
1644        //WO-DGMBTG---A--
1645        else if (symbolID.equals("WO-DGMBTG---A--")) {
1646            retColor = new Color(255, 127, 0);
1647        }
1648        //255,207,0
1649        //WO-DGMBTF---A--
1650        else if (symbolID.equals("WO-DGMBTF---A--")) {
1651            retColor = new Color(255, 207, 0);
1652        }
1653        //048,255,0
1654        //WO-DGMBTA---A--
1655        else if (symbolID.equals("WO-DGMBTA---A--")) {
1656            retColor = new Color(48, 255, 0);
1657        }
1658        //220,220,220
1659        //WO-DGML-----A--
1660        else if (symbolID.equals("WO-DGML-----A--")) {
1661            retColor = new Color(220, 220, 220);
1662        }
1663        //255,220,220
1664        //WO-DGMS-SH--A--
1665        else if (symbolID.equals("WO-DGMS-SH--A--")) {
1666            retColor = new Color(255, 220, 220);
1667        }
1668        //255,190,190
1669        //WO-DGMS-PH--A--
1670        else if (symbolID.equals("WO-DGMS-PH--A--")) {
1671            retColor = new Color(255, 190, 190);
1672        }
1673        //lime green 128,255,51
1674        //WO-DOBVC----A--
1675        else if (symbolID.equals("WO-DOBVC----A--")) {
1676            retColor = new Color(128, 255, 51);
1677        }
1678        //255,255,0
1679        //WO-DOBVE----A--
1680        else if (symbolID.equals("WO-DOBVE----A--")) {
1681            retColor = new Color(255, 255, 0);
1682        }
1683        //255,150,150
1684        //WO-DGMS-CO--A--
1685        else if (symbolID.equals("WO-DGMS-CO--A--")) {
1686            retColor = new Color(255, 150, 150);
1687        }
1688        //175,255,0
1689        //WO-DGMBTC---A--
1690        else if (symbolID.equals("WO-DGMBTC---A--")) {
1691            retColor = new Color(175, 255, 0);
1692        }
1693        //207,255,0
1694        //WO-DGMBTD---A--
1695        else if (symbolID.equals("WO-DGMBTD---A--")) {
1696            retColor = new Color(207, 255, 0);
1697        }
1698        //127,255,0
1699        //WO-DGMBTB---A--
1700        else if (symbolID.equals("WO-DGMBTB---A--")) {
1701            retColor = new Color(127, 255, 0);
1702        }
1703        //255,127,0
1704        //WO-DGMIBD---A--
1705        else if (symbolID.equals("WO-DGMIBD---A--")) {
1706            retColor = new Color(255, 127, 0);
1707        }
1708        else if (symbolID.equals("WO-DGMSIF---A--")) {
1709            retColor = new Color(25, 255, 230);
1710        }
1711        //0,215,255
1712        //WO-DGMSIVF--A--
1713        else if (symbolID.equals("WO-DGMSIVF--A--")) {
1714            retColor = new Color(0, 215, 255);
1715        }
1716        //255,255,220
1717        //WO-DGMSSVF--A--
1718        else if (symbolID.equals("WO-DGMSSVF--A--")) {
1719            retColor = new Color(255, 255, 220);
1720        }
1721        //255,255,140
1722        //WO-DGMSSF---A--
1723        else if (symbolID.equals("WO-DGMSSF---A--")) {
1724            retColor = new Color(255, 255, 140);
1725        }
1726        //255,235,0
1727        //WO-DGMSSM---A--
1728        else if (symbolID.equals("WO-DGMSSM---A--")) {
1729            retColor = new Color(255, 235, 0);
1730        }
1731        //255,215,0
1732        //WO-DGMSSC---A--
1733        else if (symbolID.equals("WO-DGMSSC---A--")) {
1734            retColor = new Color(255, 215, 0);
1735        }
1736        //255,180,0
1737        //WO-DGMSSVS--A--
1738        else if (symbolID.equals("WO-DGMSSVS--A--")) {
1739            retColor = new Color(255, 180, 0);
1740        }
1741        //200,255,105
1742        //WO-DGMSIC---A--
1743        else if (symbolID.equals("WO-DGMSIC---A--")) {
1744            retColor = new Color(200, 255, 105);
1745        }
1746        //100,130,255
1747        //WO-DGMSC----A--
1748        else if (symbolID.equals("WO-DGMSC----A--")) {
1749            retColor = new Color(100, 130, 255);
1750        }
1751        //255,77,0
1752        //WO-DOBVH----A--
1753        else if (symbolID.equals("WO-DOBVH----A--")) {
1754            retColor = new Color(255, 77, 0);
1755        }
1756        //255,128,0
1757        //WO-DOBVG----A--
1758        else if (symbolID.equals("WO-DOBVG----A--")) {
1759            retColor = new Color(255, 128, 0);
1760        }
1761        //255,204,0
1762        //WO-DOBVF----A--
1763        else if (symbolID.equals("WO-DOBVF----A--")) {
1764            retColor = new Color(255, 204, 0);
1765        }
1766        //204,255,26
1767        //WO-DOBVD----A--
1768        else if (symbolID.equals("WO-DOBVD----A--")) {
1769            retColor = new Color(204, 255, 26);
1770        }
1771        else
1772        {
1773            retColor = Color.BLACK;//0x000000;  // Black
1774        }
1775        
1776        return retColor;
1777    }
1778
1779    /**
1780     * Only for single points at the moment
1781     *
1782     * @param symbolID
1783     * @return
1784     */
1785    public static
1786            Color getFillColorOfWeather(String symbolID)
1787    {
1788        if(symbolID.equals("WOS-HPM-R-P----"))//landing ring - brown 148,48,0
1789            return new Color(148,48,0);
1790        else if(symbolID.equals("WOS-HPD---P----"))//dolphin facilities - brown
1791            return new Color(148,48,0);
1792        else if(symbolID.equals("WO-DHCB-----A--"))//
1793            return new Color(249,243,241);
1794        else if(symbolID.equals("WOS-HABB--P----"))//buoy default - 255,0,255
1795            return new Color(255,0,255);//magenta
1796        else if(symbolID.equals("WOS-HHRS--P----"))//rock submerged - 0,204,255
1797            return new Color(0,204,255);//a type of blue
1798        else if(symbolID.equals("WOS-HHDS--P----"))//snags/stumps - 0,204,255
1799            return new Color(0,204,255);
1800        else if(symbolID.equals("WOS-HHDWB-P----"))//wreck - 0,204,255
1801            return new Color(0,204,255);
1802        else if(symbolID.equals("WOS-TCCTG-P----"))//tide gauge - 210, 176, 106
1803            return new Color(210,176,106);
1804        else if(symbolID.equals("WO-DHCW-----A--"))//water
1805            return new Color(255,255,255);
1806        else if (symbolID.equals("WO-DHABP----A--") ||
1807                symbolID.equals("WO-DMCC-----A--"))
1808        {
1809            return new Color(0,0,255);
1810        }
1811        else if(symbolID.equals("WO-DHHD-----A--") ||
1812                symbolID.equals("WO-DHHDD----A--")  ||//discolored water (DeepSkyBlue)
1813                symbolID.equals("WO-DHDDA----A--"))//Depth Area
1814        {
1815            return new Color(0,191,255);
1816        }
1817        else if(symbolID.equals("WO-DHPMD----A--"))//drydock
1818            return new Color(188,153,58);
1819        else if(symbolID.equals("WO-DHCF----L---") || //FORESHORE
1820                symbolID.equals("WO-DHCF-----A--"))
1821        {
1822            return new Color(173,255,47);// 0xADFF2F;// GreenYellow
1823        }
1824        else return null;
1825    }
1826
1827    /**
1828     * @name hierarchyToSymbolID
1829     *
1830     * @desc Takes in the hierarchy passed in and, returns a formatted string
1831     * that has only the necessary static characters needed to draw a symbol.
1832     *
1833     * @param strHierarchy - IN - A MilStd hierarchy
1834     * @return A properly formated basic symbol ID
1835     * @deprecated - Not all symbols have a hierarchy anymore
1836     */
1837    public static
1838            String hierarchyToSymbolID(String strHierarchy)
1839    {/*
1840         try
1841         {
1842         String strBasicID = "";
1843         SymbolDefTable symDefTable = SymbolDefTable.getInstance();
1844         UnitDefTable unitDefTable = UnitDefTable.getInstance();
1845         // var arrUD:ArrayCollection;
1846         // var arrSD:ArrayCollection;
1847         String[] arrUD;
1848         String[] arrSD;
1849         if(strHierarchy.charAt(0) == ("1")
1850         || strHierarchy.charAt(0) == ("4")
1851         || strHierarchy.charAt(0) == ("5"))
1852         {
1853         arrUD = unitDefTable.searchByHierarchy(strHierarchy);
1854         if((arrUD != null) && (arrUD.length > 0) && (arrUD[0] != null))
1855         {
1856         // strBasicID = UnitDef(arrUD[0]).basicSymbolId;
1857         }
1858         }
1859         else if(strHierarchy.charAt(0) == ("2") || strHierarchy.charAt(0) == ("3"))
1860         {
1861         // arrSD = symDefTable.searchByHierarchy(strHierarchy);
1862         arrSD = new String[] {};
1863         if((arrSD != null) && (arrSD.length > 0) && (arrSD[0] != null))
1864         {
1865         // strBasicID = SymbolDef(arrSD[0]).basicSymbolId;
1866         }
1867         }
1868         else
1869         {
1870         arrUD = unitDefTable.searchByHierarchy(strHierarchy);
1871         // If symbol is in UnitDefTable
1872         if((arrUD != null) && (arrUD.length > 0) && (arrUD[0] != null))
1873         {
1874         // strBasicID = UnitDef(arrUD[0]).basicSymbolId;
1875         }
1876         else
1877         {
1878         // Symbol is not in UnitDefTable, see if it is in SymbolDefTable
1879         // arrSD = symDefTable.searchByHierarchy(strHierarchy);
1880         arrSD = new String[] {};
1881         if((arrSD != null) && (arrSD.length > 0) && (arrSD[0] != null))
1882         {
1883         // strBasicID = SymbolDef(arrSD[0]).basicSymbolId;
1884         }
1885         }
1886         }
1887         return strBasicID;
1888         }
1889         catch(Throwable t)
1890         {
1891         System.out.println(t);
1892         }*/
1893
1894        return "";
1895    }
1896
1897
1898    /**
1899     * Determines if the symbol is a tactical graphic
1900     *
1901     * @param strSymbolID
1902     * @return true if symbol starts with "G", or is a weather graphic, or a
1903     * bridge graphic
1904     */
1905    public static boolean isTacticalGraphic(String strSymbolID)
1906    {
1907        try
1908        {
1909            if (strSymbolID == null) // Error handling
1910            {
1911                return false;
1912            }
1913            if ((strSymbolID.charAt(0) == 'G') || (isWeather(strSymbolID))
1914                    || isEMSNaturalEvent(strSymbolID)
1915                    || isBasicShape(strSymbolID))
1916            {
1917                return true;
1918            }
1919        }
1920        catch (Throwable t)
1921        {
1922            System.out.println(t);
1923        }
1924        return false;
1925    }
1926
1927    public static boolean isBasicShape(String symbolID)
1928    {
1929        if (symbolID != null && symbolID.length() >= 2)
1930        {
1931            if (symbolID.startsWith("BS_") || symbolID.startsWith("BBS_") || symbolID.startsWith("PBS_"))
1932            {
1933                return true;
1934            }
1935            else
1936            {
1937                return false;
1938            }
1939        }
1940        else
1941        {
1942            return false;
1943        }
1944    }
1945
1946    /**
1947     * Determines if symbols is a warfighting symbol.
1948     *
1949     * @param strSymbolID
1950     * @return True if code starts with "O", "S", or "I". (or "E" in 2525C)
1951     */
1952    public static
1953            boolean isWarfighting(String strSymbolID)
1954    {
1955        try
1956        {
1957            if (strSymbolID == null) // Error handling
1958            {
1959                return false;
1960            }
1961            if ((strSymbolID.charAt(0) == 'O' || (strSymbolID.charAt(0) == 'S')
1962                    || (strSymbolID.charAt(0) == 'I') || (strSymbolID.charAt(0) == 'E' && strSymbolID.charAt(2) != 'N')))
1963            {
1964                return true;
1965            }
1966        }
1967        catch (Throwable t)
1968        {
1969            System.out.println(t);
1970        }
1971        return false;
1972    }
1973
1974    /**
1975     * Determines if the symbol is a weather graphic
1976     *
1977     * @param strSymbolID
1978     * @return true if symbolID starts with a "W"
1979     */
1980    public static
1981            boolean isWeather(String strSymbolID)
1982    {
1983        try
1984        {
1985            if(strSymbolID.charAt(0) == 'W')
1986                return true;
1987            else
1988                return false;
1989        }
1990        catch (Throwable t)
1991        {
1992            System.out.println(t);
1993        }
1994        return false;
1995    }
1996
1997    /**
1998     * Determines if a String represents a valid number
1999     *
2000     * @param text
2001     * @return "1.56" == true, "1ab" == false
2002     */
2003    public static boolean isNumber(String text)
2004    {
2005        return pIsNumber.matcher(text).matches();
2006    }
2007
2008
2009    public static String colorToHexString(Color color, Boolean withAlpha)
2010    {
2011        String hex = color.toHexString();
2012        if(withAlpha)
2013                return hex;
2014        else
2015                return hex.substring(2);
2016    }
2017
2018    /**
2019     *
2020     * @param hexValue - String representing hex value (formatted "0xRRGGBB"
2021     * i.e. "0xFFFFFF") OR formatted "0xAARRGGBB" i.e. "0x00FFFFFF" for a color
2022     * with an alpha value I will also put up with "RRGGBB" and "AARRGGBB"
2023     * without the starting "0x"
2024     * @return
2025     */
2026    public static Color getColorFromHexString(String hexValue)
2027    {
2028        try
2029        {
2030            if(hexValue==null || hexValue.isEmpty())
2031                return null;
2032            String hexOriginal = hexValue;
2033
2034            String hexAlphabet = "0123456789ABCDEF";
2035
2036            if (hexValue.charAt(0) == '#')
2037            {
2038                hexValue = hexValue.substring(1);
2039            }
2040            if (hexValue.substring(0, 2).equals("0x") || hexValue.substring(0, 2).equals("0X"))
2041            {
2042                hexValue = hexValue.substring(2);
2043            }
2044
2045            hexValue = hexValue.toUpperCase();
2046
2047            int count = hexValue.length();
2048            int[] value = null;
2049            int k = 0;
2050            int int1 = 0;
2051            int int2 = 0;
2052
2053            if (count == 8 || count == 6)
2054            {
2055                value = new int[(count / 2)];
2056                for (int i = 0; i < count; i += 2)
2057                {
2058                    int1 = hexAlphabet.indexOf(hexValue.charAt(i));
2059                    int2 = hexAlphabet.indexOf(hexValue.charAt(i + 1));
2060                    value[k] = (int1 * 16) + int2;
2061                    k++;
2062                }
2063
2064                if (count == 8)
2065                {
2066                    return new Color(value[1], value[2], value[3], value[0]);
2067                }
2068                else if (count == 6)
2069                {
2070                    return new Color(value[0], value[1], value[2]);
2071                }
2072            }
2073            else
2074            {
2075                ErrorLogger.LogMessage("SymbolUtilties", "getColorFromHexString", "Bad hex value: " + hexOriginal, Level.WARNING);
2076            }
2077            return null;
2078
2079            /*//Old Approach
2080             Color returnVal = null;
2081         
2082             if(hexValue.startsWith("0x"))//0xRRGGBB or 0xAARRGGBB
2083             {
2084             if(hexValue.length()==8)
2085             {
2086             returnVal = Color.decode(hexValue);
2087             }
2088             else if(hexValue.length()==10)
2089             {
2090             String color = "0x"+hexValue.substring(4);
2091             String alpha = "0x"+hexValue.substring(2,4);
2092             returnVal = Color.decode(color);
2093             returnVal = new Color(returnVal.getRed(), returnVal.getGreen(), returnVal.getBlue(), Integer.decode(alpha));
2094             }
2095             }
2096             else if(hexValue.startsWith("#"))//#RRGGBB or #AARRGGBB
2097             {
2098             if(hexValue.length()==7)
2099             {
2100             returnVal = Color.decode("0x"+hexValue.substring(1, 7));
2101             }
2102             else if(hexValue.length()==9)
2103             {
2104             String color = "0x"+hexValue.substring(3);
2105             String alpha = "0x"+hexValue.substring(1,3);
2106             returnVal = Color.decode(color);
2107             returnVal = new Color(returnVal.getRed(), returnVal.getGreen(), returnVal.getBlue(), Integer.decode(alpha));
2108             }
2109             }
2110             else//just RRGGBB or AARRGGBB without the starting 0x
2111             {
2112             if(hexValue.length()==6)
2113             {
2114             returnVal = Color.decode("0x"+hexValue);
2115             }
2116             else if(hexValue.length()==8)
2117             {
2118             String color = "0x"+hexValue.substring(2);
2119             String alpha = "0x"+hexValue.substring(0,2);
2120             returnVal = Color.decode(color);
2121             returnVal = new Color(returnVal.getRed(), returnVal.getGreen(), returnVal.getBlue(), Integer.decode(alpha));
2122             }
2123             }
2124         
2125             return returnVal;*/
2126        }
2127        catch (Exception exc)
2128        {
2129            ErrorLogger.LogException("SymbolUtilities", "getColorFromHexString", exc);
2130            return null;
2131        }
2132    }
2133
2134
2135    /**
2136     * Symbols that don't exist outside of MCS
2137     *
2138     * @param sd
2139     * @return
2140     */
2141    public static
2142            boolean isMCSSpecificTacticalGraphic(SymbolDef sd)
2143    {
2144        if (sd.getHierarchy().startsWith("2.X.7") || //Engineering Overlay graphics (ESRI----)
2145                sd.getHierarchy().startsWith("2.X.5.2.3") || //Route Critical Points
2146                sd.getBasicSymbolId().startsWith("G*R*") || //Route Critical Points
2147                sd.getHierarchy().startsWith("21.X") || //JCID (21.X)
2148                sd.getBasicSymbolId().startsWith("G*E*"))//MCS Eng (20.X)
2149        {
2150            return true;
2151        }
2152        else
2153        {
2154            return false;
2155        }
2156    }
2157
2158    public static
2159            boolean is3dAirspace(String symbolID)
2160    {
2161        if (symbolID == ("CYLINDER-------")
2162                || symbolID == ("ORBIT----------")
2163                || symbolID == ("ROUTE----------")
2164                || symbolID == ("POLYGON--------")
2165                || symbolID == ("RADARC---------")
2166                || symbolID == ("POLYARC--------")
2167                || symbolID == ("CAKE-----------")
2168                || symbolID == ("TRACK----------")
2169                || symbolID == ("CURTAIN--------"))
2170        {
2171            return true;
2172        }
2173        else
2174        {
2175            return false;
2176        }
2177    }
2178
2179    /**
2180     * Symbols that don't exist outside of MCS or units that are no longer
2181     * supported like those from the SASO Proposal.
2182     *
2183     * @param ud
2184     * @return
2185     */
2186    public static
2187            boolean isMCSSpecificForceElement(UnitDef ud)
2188    {
2189        if (isSASO(ud))//SASO
2190        {
2191            return true;
2192        }
2193        else
2194        {
2195            return false;
2196        }
2197    }
2198
2199    /**
2200     * Just checks the symbolID if it could be rendered in 3D. Does not check
2201     * for needed modifiers.
2202     *
2203     * @param symbolID
2204     * @return
2205     */
2206    public static
2207            Boolean is3dGraphic(String symbolID)
2208    {
2209        String symbolId = symbolID.substring(4, 10);
2210
2211        if (symbolId.equals("ACAI--") || // Airspace Coordination Area Irregular
2212                symbolId.equals("ACAR--") || // Airspace Coordination Area Rectangular
2213                symbolId.equals("ACAC--") || // Airspace Coordination Area Circular
2214                symbolId.equals("AKPC--") || // Kill box circular
2215                symbolId.equals("AKPR--") || // Kill box rectangular
2216                symbolId.equals("AKPI--") || // Kill box irregular
2217                symbolId.equals("ALC---") || // Air corridor
2218                symbolId.equals("ALM---") || // 
2219                symbolId.equals("ALS---") || // SAAFR
2220                symbolId.equals("ALU---") || // UAV
2221                symbolId.equals("ALL---") || // Low level transit route
2222                symbolId.equals("AAR---")
2223                || symbolId.equals("AAF---")
2224                || symbolId.equals("AAH---")
2225                || symbolId.equals("AAM---") || // MEZ
2226                symbolId.equals("AAML--") || // LOMEZ
2227                symbolId.equals("AAMH--"))
2228        {
2229            return true;
2230        }
2231        else
2232        {
2233            return false;
2234        }
2235
2236    }
2237
2238    /**
2239     * Symbols from the SASO Proposal. Most were replaced by the USAS 13-14
2240     * update or 2525C.
2241     *
2242     * @param sd
2243     * @return
2244     */
2245    public static
2246            boolean isSASO(UnitDef sd)
2247    {
2248        if (sd.getHierarchy().startsWith("5.X.10") || //SASOP Individuals
2249                sd.getHierarchy().startsWith("5.X.11") || //SASOP Organization/groups
2250                sd.getHierarchy().startsWith("5.X.12") ||//SASOP //replaced by USAS 13-14 update
2251                sd.getHierarchy().startsWith("5.X.13") || //SASOP Structures
2252                sd.getHierarchy().startsWith("5.X.14")) //SASOP Equipment/Weapons
2253        {
2254            return true;
2255        }
2256        else
2257        {
2258            return false;
2259        }
2260    }
2261
2262    public static
2263            boolean isCheckPoint(String strSymbolID)
2264    {
2265        try
2266        {
2267            String strBasicSymbolID = getBasicSymbolID(strSymbolID);
2268            boolean blRetVal = false;
2269            if (strBasicSymbolID.equals("G*G*GPPE--****X")//release point
2270                    || strBasicSymbolID.equals("G*G*GPPK--****X")//check point
2271                    || strBasicSymbolID.equals("G*G*GPPS--****X"))//start point
2272            {
2273                blRetVal = true;
2274            }
2275            return blRetVal;
2276        }
2277        catch (Throwable t)
2278        {
2279            System.out.println(t);
2280        }
2281        return false;
2282    } // End IsCheckPoint
2283
2284    /**
2285     * @name IsCriticalPoint
2286     *
2287     * @desc Returns true if the symbolID is a critical point.
2288     *
2289     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2290     * critical point
2291     * @return True if the graphic is a critical point, false otherwise.
2292     */
2293    public static
2294            boolean isCriticalPoint(String strSymbolID)
2295    {
2296        try
2297        {
2298            String strBasicSymbolID = getBasicSymbolID(strSymbolID);
2299            boolean blRetVal = false;
2300            if (isTacticalGraphic(strBasicSymbolID))
2301            {
2302                String[] arr = new String[]
2303                {
2304                    "G*M*BDD---****X",
2305                    "G*M*BDE---****X",
2306                    "G*M*BDI---****X",
2307                    "G*R*CN----****X",
2308                    "G*R*CP----****X",
2309                    "G*R*FD----****X",
2310                    "G*R*FR----****X",
2311                    "G*R*PCC---****X",
2312                    "G*R*PCO---****X",
2313                    "G*R*PDC---****X",
2314                    "G*R*PHP---****X",
2315                    "G*R*PMC---****X",
2316                    "G*R*PO----****X",
2317                    "G*R*PPO---****X",
2318                    "G*R*PTO---****X",
2319                    "G*R*RLGC--****X",
2320                    "G*R*SG----****X",
2321                    "G*R*SSC---****X",
2322                    "G*R*SC----****X",
2323                    "G*R*TN----****X",
2324                    "G*R*UP----****X"
2325                };
2326                int arrLength = arr.length;
2327                for (int i = 0; i < arrLength; i++)
2328                {
2329                    if (arr[i].equals(strBasicSymbolID))
2330                    {
2331                        blRetVal = true;
2332                        break;
2333                    }
2334                }
2335            }
2336            else
2337            {
2338                if (strBasicSymbolID.equals("O*E*AL---------")
2339                        || strBasicSymbolID.equals("O*E*AM---------")
2340                        || strBasicSymbolID.equals("S*G*IMNB-------"))
2341                {
2342                    blRetVal = true;
2343                }
2344            }
2345            return blRetVal;
2346        }
2347        catch (Throwable t)
2348        {
2349            System.out.println(t);
2350        }
2351        return false;
2352    }
2353
2354    /**
2355     * @name IsRoute
2356     *
2357     * @desc Returns true if the symbolID is a route.
2358     *
2359     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2360     * route
2361     * @return True if the graphic is a route, false otherwise.
2362     */
2363    public static
2364            boolean isRoute(String strSymbolID)
2365    {
2366        try
2367        {
2368            String strBasicSymbolID = getBasicSymbolID(strSymbolID);
2369            boolean blRetVal = false;
2370            if (strBasicSymbolID.equals("G*S*LRA---****X") || strBasicSymbolID.equals("G*S*LRM---****X"))
2371            {
2372                blRetVal = true;
2373            }
2374            return blRetVal;
2375        }
2376        catch (Throwable t)
2377        {
2378            System.out.println(t);
2379        }
2380        return false;
2381    } // End IsRoute
2382
2383    /**
2384     * @name IsRoad
2385     *
2386     * @desc Returns true if the symbolID is a road.
2387     *
2388     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2389     * road
2390     * @return True if the graphic is a road, false otherwise.
2391     */
2392    public static
2393            boolean isRoad(String strSymbolID)
2394    {
2395        try
2396        {
2397            String strBasicSymbolID = getBasicSymbolID(strSymbolID);
2398            boolean blRetVal = false;
2399            if (strBasicSymbolID.equals("ROAD------****X"))
2400            {
2401                blRetVal = true;
2402            }
2403            return blRetVal;
2404        }
2405        catch (Throwable t)
2406        {
2407            System.out.println(t);
2408        }
2409        return false;
2410    } // End IsRoad
2411
2412    /**
2413     * @name IsJWARN
2414     *
2415     * @desc Returns true if the symbolID is a JWARN symbol.
2416     *
2417     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2418     * JWARN graphic
2419     * @return True if the graphic is a JWARN symbol, false otherwise.
2420     */
2421    public static
2422            boolean isJWARN(String strSymbolID)
2423    {
2424        try
2425        {
2426            if (strSymbolID.substring(0, 5).equals("JWARN"))
2427            {
2428                return true;
2429            }
2430            else
2431            {
2432                return false;
2433            }
2434        }
2435        catch (Throwable t)
2436        {
2437            System.out.println(t);
2438        }
2439        return false;
2440    } // End IsJWARN
2441
2442    /**
2443     * @name IsMOOTW
2444     *
2445     * @desc Returns true if the symbolID is a MOOTW symbol.
2446     *
2447     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2448     * MOOTW graphic
2449     * @return True if the graphic is a MOOTW symbol in the MIL-STD 2525B or
2450     * STBOPS in 2525C, false otherwise.
2451     */
2452    public static
2453            boolean isMOOTW(String strSymbolID)
2454    {
2455        try
2456        {
2457            if (strSymbolID.charAt(0) == 'O')
2458            {
2459                return true;
2460            }
2461            else
2462            {
2463                return false;
2464            }
2465        }
2466        catch (Throwable t)
2467        {
2468            System.out.println(t);
2469        }
2470        return false;
2471    } // End IsMOOTW
2472
2473    /**
2474     * @name isSTBOPS
2475     *
2476     * @desc Returns true if the symbolID is a Stability Operations (STBOPS)
2477     * symbol.
2478     *
2479     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2480     * isStabilityOperations graphic
2481     * @return True if the graphic is a MOOTW symbol in the MIL-STD 2525B or
2482     * STBOPS in 2525C, false otherwise.
2483     */
2484    public static
2485            boolean isSTBOPS(String strSymbolID)
2486    {
2487        try
2488        {
2489            if (strSymbolID.charAt(0) == 'O')
2490            {
2491                return true;
2492            }
2493            else
2494            {
2495                return false;
2496            }
2497        }
2498        catch (Throwable t)
2499        {
2500            System.out.println(t);
2501        }
2502        return false;
2503    } // End isStabilityOperations
2504
2505    /**
2506     * @name IsMOOTW
2507     *
2508     * @desc Returns true if the symbolID is an event symbol.
2509     *
2510     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2511     * MOOTW graphic
2512     * @return True if the graphic is a MOOTW symbol in the MIL-STD 2525B, false
2513     * otherwise.
2514     */
2515    public static
2516            boolean isEvent(String strSymbolID)
2517    {
2518        try
2519        {
2520            String[] arr = null;
2521            char category = strSymbolID.charAt(2);
2522            String strBasicSymbolID = getBasicSymbolID(strSymbolID);
2523            if (isMOOTW(strSymbolID)
2524                    || (isEMS(strSymbolID)
2525                    && (category == 'I' || category == 'N' || category == 'O')))
2526            {
2527                return true;
2528            }
2529            else
2530            {
2531
2532                arr = new String[]
2533                {
2534                    "S*G*EXI---*****",
2535                    "S*G*EXI---MO***"
2536                };
2537                int arrLength = arr.length;
2538                for (int i = 0; i < arrLength; i++)
2539                {
2540                    if (arr[i].equals(strBasicSymbolID))
2541                    {
2542                        return true;
2543                    }
2544                }
2545            }
2546        }
2547        catch (Throwable t)
2548        {
2549            System.out.println(t);
2550        }
2551        return false;
2552    } // End IsMOOTW
2553
2554    /**
2555     * @name isHQ
2556     *
2557     * @desc Determines if the symbol id passed in contains a flag for one of
2558     * the various HQ options Pos 11 of the symbol code
2559     *
2560     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a HQ
2561     * @return True if the graphic is a HQ symbol in the MIL-STD 2525B, false
2562     * otherwise.
2563     */
2564    public static boolean isHQ(String strSymbolID)
2565    {
2566        boolean blRetVal = false;
2567        try
2568        {
2569            char hq = strSymbolID.charAt(10);
2570            if(hq != '-' && hq != '*')
2571            {
2572                if(hq == 'A' || hq == 'B' || hq == 'C' || hq == 'D')
2573                {
2574                    blRetVal = true;
2575                }
2576            }
2577            else if (strSymbolID.charAt(0) == 'S' && strSymbolID.substring(4,6).equals("UH"))
2578            {
2579                blRetVal = true;
2580            }
2581        }
2582        catch (Throwable t)
2583        {
2584            System.out.println(t);
2585        }
2586        return blRetVal;
2587    } // End isHQ
2588
2589    /**
2590     * @name isTaskForce
2591     *
2592     * @desc Returns whether or not the given symbol id contains task force.
2593     *
2594     * @param strSymbolID - IN - Symbol Id we are checking to see if it contains
2595     * task force
2596     * @return Returns true if the symbol id contains task force, false
2597     * otherwise.
2598     */
2599    public static
2600            boolean isTaskForce(String strSymbolID)
2601    {
2602        try
2603        {
2604            // Return whether or not task force is included in the symbol id.
2605            char mod1 = strSymbolID.charAt(10);
2606            boolean blRetVal = (mod1 == 'B'
2607                    || mod1 == 'D'
2608                    || mod1 == 'E' || mod1 == 'G');
2609            return blRetVal;
2610        }
2611        catch (Throwable t)
2612        {
2613            System.out.println(t);
2614        }
2615        return false;
2616    } // End IsTaskForce
2617
2618    /**
2619     * @name isFeintDummy
2620     *
2621     * @desc Returns whether or not the given symbol id contains FeintDummy.
2622     *
2623     * @param strSymbolID - IN - Symbol Id we are checking to see if it contains
2624     * feint dummy
2625     * @return Returns true if the symbol id contains FeintDummy, false
2626     * otherwise.
2627     */
2628    public static
2629            boolean isFeintDummy(String strSymbolID)
2630    {
2631        try
2632        {
2633            char mod1 = strSymbolID.charAt(10);
2634            // Return whether or not feintdummy is included in the symbol id.
2635            boolean blRetVal = (mod1 == 'C'
2636                    || mod1 == 'D'
2637                    || mod1 == 'F' || mod1 == 'G');
2638
2639            return blRetVal;
2640        }
2641        catch (Throwable t)
2642        {
2643            System.out.println(t);
2644        }
2645        return false;
2646    } // End IsFeintDummy
2647
2648    /**
2649     * @name isMobilityWheeled
2650     *
2651     * @desc Determines if the symbol id passed in contains a flag for the
2652     * various Wheeled Mobility options Pos 11 and 12 of the symbol code
2653     *
2654     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2655     * Wheeled Mobility
2656     * @return True if the graphic (equipment only) is a Wheeled Mobility in the
2657     * MIL-STD 2525B, false otherwise.
2658     */
2659    public static
2660            boolean isMobilityWheeled(String strSymbolID)
2661    {
2662        boolean mobilityWheeledIsOn = false;
2663        try
2664        {
2665            // See if the mobility wheeled modifier is on.
2666            mobilityWheeledIsOn = (isEquipment(strSymbolID)
2667                    && strSymbolID.charAt(10) == 'M'
2668                    && strSymbolID.charAt(11) == 'O');
2669        }
2670        catch (Throwable t)
2671        {
2672            System.out.println(t);
2673        }
2674        // Return whether or not the mobility wheeled modifier is on.
2675        return mobilityWheeledIsOn;
2676    }
2677
2678    /**
2679     * Symbol has a mobility modifier
2680     *
2681     * @param strSymbolID
2682     * @return
2683     */
2684    public static
2685            boolean isMobility(String strSymbolID)
2686    {
2687        boolean mobilityIsOn = false;
2688        try
2689        {
2690            String mod = strSymbolID.substring(10, 12);
2691            //if(isEquipment(strSymbolID))
2692            //{
2693            if (mod.equals("MO")
2694                    || mod.equals("MP")
2695                    || mod.equals("MQ")
2696                    || mod.equals("MR")
2697                    || mod.equals("MS")
2698                    || mod.equals("MT")
2699                    || mod.equals("MU")
2700                    || mod.equals("MV")
2701                    || mod.equals("MW")
2702                    || mod.equals("MX")
2703                    || mod.equals("MY")
2704                    || mod.equals("NS")
2705                    || mod.equals("NL"))
2706            {
2707                mobilityIsOn = true;
2708            }
2709            //}
2710        }
2711        catch (Throwable t)
2712        {
2713            System.out.println(t);
2714        }
2715        // Return whether or not the mobility wheeled modifier is on.
2716        return mobilityIsOn;
2717    }
2718
2719    /**
2720     * Returns true if Symbol is a Target
2721     *
2722     * @param strSymbolID
2723     * @return
2724     */
2725    public static Boolean isTarget(String strSymbolID)
2726    {
2727        String basicID = SymbolUtilities.getBasicSymbolID(strSymbolID);
2728        String sub = basicID.substring(0, 6);
2729        if (sub.equals("G*F*PT") ||//fire support/point/point target
2730                sub.equals("G*F*LT") ||//fire support/lines/linear target
2731                sub.equals("G*F*AT"))//fire support/area/area target
2732        {
2733            return true;
2734        }
2735        else
2736        {
2737            return false;
2738        }
2739    }
2740
2741    /**
2742     * Returns true if Symbol is an Air Track
2743     *
2744     * @param strSymbolID
2745     * @return
2746     */
2747    public static Boolean isAirTrack(String strSymbolID)
2748    {
2749        if (strSymbolID.charAt(0) == 'S'
2750                && strSymbolID.charAt(2) == 'A')
2751        {
2752            return true;
2753        }
2754        else
2755        {
2756            return false;
2757        }
2758    }
2759
2760    /**
2761     * @name isObstacle
2762     *
2763     * @desc Returns true if the symbol id passed in is an Obstacle symbol code.
2764     *
2765     * @param strSymbolID - IN - Symbol Id we are checking to see if it is an
2766     * Obstacle
2767     * @return True if the graphic is an Obstacle in the MIL-STD 2525B, false
2768     * otherwise.
2769     */
2770    public static
2771            boolean isObstacle(String strSymbolID)
2772    {
2773        try
2774        {
2775            // An Obstacle is denoted by the symbol code "G*M*O"
2776            // So see if it is a tactical graphic then check to see
2777            // if we have the M and then the O in the correct position.
2778            boolean blRetVal = ((isTacticalGraphic(strSymbolID)) && ((strSymbolID.charAt(2) == 'M') && (strSymbolID.charAt(4) == 'O')));
2779            return blRetVal;
2780        }
2781        catch (Throwable t)
2782        {
2783            System.out.println(t);
2784        }
2785        return false;
2786    } // End isObstacle
2787
2788    /**
2789     * @name isDeconPoint
2790     *
2791     * @desc Returns true if the symbol id is a DECON (NBC graphic) point
2792     * symbol.
2793     *
2794     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
2795     * Decon Point
2796     * @return True if the graphic is a Decon Point in the MIL-STD 2525B, false
2797     * otherwise.
2798     */
2799    public static
2800            boolean isDeconPoint(String strSymbolID)
2801    {
2802        try
2803        {
2804            boolean blRetVal = ((isNBC(strSymbolID)) && (strSymbolID.substring(4, 6).equals("ND")));
2805            return blRetVal;
2806        }
2807        catch (Throwable t)
2808        {
2809            System.out.println(t);
2810        }
2811        return false;
2812    } // End isDeconPoint
2813
2814    /**
2815     * @name isEchelonGraphic
2816     *
2817     * @desc Returns true if the graphic is to have an echelon associated with
2818     * it.
2819     *
2820     *
2821     * Here's the rules: Single point tactical graphics do not have an echelon
2822     * (see ms2525b ch2 5.5.2.2) Weather graphics do not have an echelon - don't
2823     * set one Neither do Decon Point graphics Neither do Bridge graphics Pretty
2824     * much only Obstacles, Units, and SOF get echelons
2825     *
2826     * @param strSymbolID - IN - A basic MilStd2525B symbolID
2827     * @param symStd RendererSettings.Symbology_2525C
2828     * @return True if the graphic displays an echelon, false if it ignores the
2829     * echelon field
2830     * @deprecated
2831     */
2832    public static
2833            boolean isEchelonGraphic(String strSymbolID, int symStd)
2834    {
2835        try
2836        {
2837            // Here's the rules:
2838            // Single point tactical graphics do not have an echelon (see ms2525b ch2
2839            // 5.5.2.2)
2840            // Weather graphics do not have an echelon - don't set one
2841            // Neither do Decon Point graphics
2842            // Neither do Bridge graphics
2843            // Pretty much only Obstacles, Units, and SOF get echelons
2844            boolean blIsSinglePointTG = false;
2845            String basicID = getBasicSymbolID(strSymbolID);
2846            if (isTacticalGraphic(strSymbolID))
2847            {
2848                SymbolDefTable symDefTable = SymbolDefTable.getInstance();
2849                SymbolDef sd = symDefTable.getSymbolDef(basicID, symStd);
2850                /*if (sd.getGeometry().equals("point"))
2851                {
2852                    blIsSinglePointTG = true;
2853                }//*/
2854                if(sd.getDrawCategory() == SymbolDef.DRAW_CATEGORY_POINT)
2855                {
2856                        blIsSinglePointTG = true;
2857                }
2858            }
2859            boolean blRetVal = (((isUnit(strSymbolID))/* || (isMOOTW(strSymbolID))*/
2860                    || (isSOF(strSymbolID))
2861                    || (isMOOTW(strSymbolID))
2862                    || ((SymbolUtilities.isObstacle(strSymbolID)) && (!blIsSinglePointTG))
2863                    || (basicID.equals("G*G*GLB---****X"))
2864                    || (basicID.equals("G*G*DAB---****X"))
2865                    || (basicID.equals("G*G*DABP--****X"))
2866                    || (basicID.equals("G*M*SP----****X"))));
2867
2868            return blRetVal;
2869        }
2870        catch (Throwable t)
2871        {
2872            System.out.println(t);
2873        }
2874        return false;
2875    } // End isEchelonGraphic
2876
2877    /**
2878     * Reads the Symbol ID string and returns the text that represents the
2879     * echelon code.
2880     *
2881     * @param echelon
2882     * @return
2883     */
2884    public static
2885            String getEchelonText(String echelon)
2886    {
2887        char[] dots = new char[3];
2888        dots[0] = (char) 8226;
2889        dots[1] = (char) 8226;
2890        dots[2] = (char) 8226;
2891        String dot = new String(dots);
2892        String text = null;
2893        if (echelon != null)
2894        {
2895            if (echelon.equals("A"))
2896            {
2897                text = "0";
2898            }
2899            else if (echelon.equals("B"))
2900            {
2901                text = dot.substring(0, 1);
2902            }
2903            else if (echelon.equals("C"))
2904            {
2905                text = dot.substring(0, 2);
2906            }
2907            else if (echelon.equals("D"))
2908            {
2909                text = dot;
2910            }
2911            else if (echelon.equals("E"))
2912            {
2913                text = "|";
2914            }
2915            else if (echelon.equals("F"))
2916            {
2917                text = "||";
2918            }
2919            else if (echelon.equals("G"))
2920            {
2921                text = "|||";
2922            }
2923            else if (echelon.equals("H"))
2924            {
2925                text = "X";
2926            }
2927            else if (echelon.equals("I"))
2928            {
2929                text = "XX";
2930            }
2931            else if (echelon.equals("J"))
2932            {
2933                text = "XXX";
2934            }
2935            else if (echelon.equals("K"))
2936            {
2937                text = "XXXX";
2938            }
2939            else if (echelon.equals("L"))
2940            {
2941                text = "XXXXX";
2942            }
2943            else if (echelon.equals("M"))
2944            {
2945                text = "XXXXXX";
2946            }
2947            else if (echelon.equals("N"))
2948            {
2949                text = "++";
2950            }
2951        }
2952        return text;
2953    }
2954
2955    /**
2956     * @name isUnit
2957     *
2958     * @desc Returns true if the symbolID is a unit.
2959     *
2960     * @param strSymbolID - IN - SymbolID we are checking on
2961     * @return True if the graphic is a unit in the MIL-STD 2525B or is a
2962     * special operation forces unit, false otherwise.
2963     */
2964    public static
2965            boolean isUnit(String strSymbolID)
2966    {
2967        try
2968        {
2969            boolean blRetVal = (((strSymbolID.charAt(0) == 'S')
2970                    && (strSymbolID.charAt(2) == 'G')
2971                    && (strSymbolID.charAt(4) == 'U')) ||
2972                    isSOF(strSymbolID));
2973            return blRetVal;
2974        }
2975        catch (Throwable t)
2976        {
2977            System.out.println(t);
2978        }
2979        return false;
2980    } // End isUnit
2981
2982    /**
2983     * @name isNBC
2984     *
2985     * @desc Returns true if the symbol id passed in is a NBC symbol code.
2986     *
2987     * @param strSymbolID - IN - SymbolID we are checking on
2988     * @return True if the graphic is a NBC in the MIL-STD 2525B, false
2989     * otherwise.
2990     */
2991    public static
2992            boolean isNBC(String strSymbolID)
2993    {
2994        try
2995        {
2996            String temp = getBasicSymbolID(strSymbolID);
2997            boolean blRetVal = ((isTacticalGraphic(strSymbolID)) && (temp.substring(0, 5).equals("G*M*N")));
2998            return blRetVal;
2999        }
3000        catch (Throwable t)
3001        {
3002            System.out.println(t);
3003        }
3004        return false;
3005    } // End isNBC
3006
3007    /**
3008     * returns true if the symbol code represents a symbol that has control
3009     * points
3010     *
3011     * @param symStd RendererSettings.Symbology_2525C
3012     * @param strSymbolID
3013     * @return
3014     */
3015    public static
3016            boolean isTGWithControlPoints(String strSymbolID, int symStd)
3017    {
3018        String temp = getBasicSymbolID(strSymbolID);
3019        SymbolDef sd = SymbolDefTable.getInstance().getSymbolDef(temp, symStd);
3020
3021        if (sd != null && sd.getDrawCategory() == SymbolDef.DRAW_CATEGORY_ROUTE)
3022        {
3023            return true;
3024        }
3025        else
3026        {
3027            return false;//blRetVal;
3028        }
3029    }
3030
3031    /**
3032     * There's a handful of single point tactical graphics with unique modifier
3033     * positions.
3034     *
3035     * @param strSymbolID
3036     * @return
3037     */
3038    public static
3039            boolean isTGSPWithSpecialModifierLayout(String strSymbolID)
3040    {
3041        String temp = getBasicSymbolID(strSymbolID);
3042
3043        boolean blRetVal = (temp.equals("G*G*GPH---****X"))//Harbor(General) - center
3044                || (temp.equals("G*G*GPPC--****X")) //Contact Point - center
3045                || (temp.equals("G*G*GPPD--****X"))//Decisions Point - center
3046                || (temp.equals("G*G*GPPW--****X")) //Waypoint - right of center
3047                || (temp.equals("G*G*APP---****X"))//ACP - circle, just below center
3048                || (temp.equals("G*G*APC---****X"))//CCP - circle, just below center
3049                || (temp.equals("G*G*DPT---****X")) //Target Reference - target special
3050                || (temp.equals("G*F*PTS---****X"))//Point/Single Target - target special
3051                || (temp.equals("G*F*PTN---****X"))//Nuclear Target - target special
3052                || (temp.equals("G*F*PCF---****X")) //Fire Support Station - right of center
3053                || (temp.equals("G*M*NZ----****X")) //NUCLEAR DETINATIONS GROUND ZERO
3054                || (temp.equals("G*M*NEB---****X"))//BIOLOGICAL
3055                || (temp.equals("G*M*NEC---****X"))//CHEMICAL
3056                || (temp.equals("G*G*GPRI--****X"))//Point of Interest
3057                || (temp.equals("G*M*OFS---****X"))//Minefield
3058                || (temp.equals("WAS-WSF-LVP----"))//Freezing Level
3059                || (temp.equals("WAS-PLT---P----"))//Tropopause Low
3060                || (temp.equals("WAS-PHT---P----"))//Tropopause High
3061                || (temp.equals("WAS-WST-LVP----"));//Tropopause Level
3062        return blRetVal;//blRetVal;
3063    }
3064
3065    /**
3066     * Is a single point tactical graphic that has integral text (like the NBC
3067     * single points)
3068     *
3069     * @param strSymbolID
3070     * @return
3071     */
3072    public static
3073            boolean isTGSPWithIntegralText(String strSymbolID)
3074    {
3075        String temp = getBasicSymbolID(strSymbolID);
3076
3077        // ErrorLogger.LogMessage("SU", "integraltext?", temp);
3078        boolean blRetVal = (temp.equals("G*G*GPRD--****X"))//DLRP (D)
3079                || (temp.equals("G*G*APU---****X")) //pull-up point (PUP)
3080                || (temp.equals("G*M*NZ----****X")) //Nuclear Detonation Ground Zero (N)
3081                || (temp.equals("G*M*NF----****X"))//Fallout Producing (N)
3082                || (temp.equals("G*M*NEB---****X"))//Release Events Chemical (BIO, B)
3083                || (temp.equals("G*M*NEC---****X"));//Release Events Chemical (CML, C)
3084
3085        //if(temp.equals("G*G*GPRD--****X"))
3086        //    ErrorLogger.LogMessage("DLRP");
3087        return blRetVal;//blRetVal;
3088    }
3089
3090    /**
3091     * Is tactical graphic with fill
3092     *
3093     * @param strSymbolID
3094     * @return
3095     */
3096    public static
3097            boolean isTGSPWithFill(String strSymbolID)
3098    {
3099        String temp = getBasicSymbolID(strSymbolID);
3100        boolean blRetVal = isDeconPoint(temp)//Decon Points
3101                || temp.startsWith("G*S*P")//TG/combat service support/points
3102                || (temp.equals("G*G*GPP---****X"))//Action points (general)
3103                || (temp.equals("G*G*GPPK--****X"))//Check Point
3104                || (temp.equals("G*G*GPPL--****X"))//Linkup Point
3105                || (temp.equals("G*G*GPPP--****X"))//Passage Point
3106                || (temp.equals("G*G*GPPR--****X"))//Rally Point
3107                || (temp.equals("G*G*GPPE--****X"))//Release Point
3108                || (temp.equals("G*G*GPPS--****X"))//Start Point
3109                || (temp.equals("G*G*GPPA--****X"))//Amnesty Point
3110                || (temp.equals("G*G*GPPN--****X"))//Entry Control Point
3111                || (temp.equals("G*G*APD---****X"))//Down Aircrew Pickup Point
3112                || (temp.equals("G*G*OPP---****X"))//Point of Departure
3113                || (temp.equals("G*F*PCS---****X"))//Survey Control Point
3114                || (temp.equals("G*F*PCB---****X"))//Firing Point
3115                || (temp.equals("G*F*PCR---****X"))//Reload Point
3116                || (temp.equals("G*F*PCH---****X"))//Hide Point
3117                || (temp.equals("G*F*PCL---****X"))//Launch Point
3118                || (temp.equals("G*M*BCP---****X"))//Engineer Regulating Point
3119                || (temp.equals("G*O*ES----****X"))//Emergency Distress Call
3120
3121                //star
3122                || (temp.startsWith("G*G*GPPD-"))//Decision Point    
3123
3124                //circle
3125                || (temp.equals("G*G*GPPO--****X"))//Coordination Point
3126                || (temp.equals("G*G*APP---****X"))//ACP
3127                || (temp.equals("G*G*APC---****X"))//CCP
3128                || (temp.equals("G*G*APU---****X"))//PUP
3129
3130                //circle with squiggly
3131                || (temp.startsWith("G*G*GPUY"))//SONOBUOY and those that fall under it
3132
3133                //reference point
3134                || ((temp.startsWith("G*G*GPR") && temp.charAt(7) != 'I'))
3135                //NBC
3136                || (temp.equals("G*M*NEB---****X"))//BIO
3137                || (temp.equals("G*M*NEC---****X")) //CHEM
3138                || (temp.equals("G*M*NF----****X")) //fallout producing
3139                || (temp.equals("G*M*NZ----****X"));//NUC
3140
3141        return blRetVal;
3142    }
3143
3144    public static
3145            boolean hasDefaultFill(String strSymbolID)
3146    {
3147        if (SymbolUtilities.isTacticalGraphic(strSymbolID))
3148        {
3149            String temp = SymbolUtilities.getBasicSymbolID(strSymbolID);
3150            //SymbolDef sd = SymbolDefTable.getInstance().getSymbolDef(temp);
3151            if ((temp.equals("G*M*NEB---****X"))//BIO
3152                    || (temp.equals("G*M*NEC---****X")) //CHEM
3153                    // || (temp.equals("G*M*NF----****X")) //fallout producing
3154                    || (temp.equals("G*M*NZ----****X")))//NUC)
3155            {
3156                return true;
3157            }
3158            else
3159            {
3160                return false;
3161            }
3162        }
3163        else
3164        {
3165            return true;
3166        }
3167    }
3168
3169    /**
3170     *
3171     * @param strSymbolID
3172     * @return
3173     */
3174    public static
3175            String getTGFillSymbolCode(String strSymbolID)
3176    {
3177        String temp = getBasicSymbolID(strSymbolID);
3178        if (temp.equals("G*M*NEB---****X"))
3179        {
3180            return "NBCBIOFILL****X";
3181        }
3182        if (temp.equals("G*M*NEC---****X"))
3183        {
3184            return "NBCCMLFILL****X";
3185        }
3186        if (temp.equals("G*M*NZ----****X") || temp.equals("G*M*NF----****X"))
3187        {
3188            return "NBCNUCFILL****X";
3189        }
3190        if (temp.startsWith("G*G*GPUY"))
3191        {
3192            return "SONOBYFILL****X";
3193        }
3194        if ((temp.equals("G*G*GPPO--****X"))//Coordination Point
3195                || (temp.equals("G*G*APP---****X"))//ACP
3196                || (temp.equals("G*G*APC---****X"))//CCP
3197                || (temp.equals("G*G*APU---****X")))//PUP)
3198        {
3199            return "CPOINTFILL****X";
3200        }
3201        if (isDeconPoint(temp)//Decon Points
3202                || temp.startsWith("G*S*P")//TG/combat service support/points
3203                || (temp.equals("G*G*GPP---****X"))//Action points (general)
3204                || (temp.equals("G*G*GPPK--****X"))//Check Point
3205                || (temp.equals("G*G*GPPL--****X"))//Linkup Point
3206                || (temp.equals("G*G*GPPP--****X"))//Passage Point
3207                || (temp.equals("G*G*GPPR--****X"))//Rally Point
3208                || (temp.equals("G*G*GPPE--****X"))//Release Point
3209                || (temp.equals("G*G*GPPS--****X"))//Start Point
3210                || (temp.equals("G*G*GPPA--****X"))//Amnesty Point
3211                || (temp.equals("G*G*APD---****X"))//Down Aircrew Pickup Point
3212                || (temp.equals("G*G*OPP---****X"))//Point of Departure
3213                || (temp.equals("G*F*PCS---****X"))//Survey Control Point
3214                || (temp.equals("G*F*PCB---****X"))//Firing Point
3215                || (temp.equals("G*F*PCR---****X"))//Reload Point
3216                || (temp.equals("G*F*PCH---****X"))//Hide Point
3217                || (temp.equals("G*F*PCL---****X"))//Launch Point
3218                || (temp.equals("G*G*GPPN--****X"))//Entry Control Point
3219                || (temp.equals("G*O*ES----****X"))//Emergency Distress Call
3220                || (temp.equals("G*M*BCP---****X")))//Engineer Regulating Point
3221        {
3222            return "CHKPNTFILL****X";
3223        }
3224        if (temp.startsWith("G*G*GPR") && temp.charAt(7) != 'I')
3225        {
3226            return "REFPNTFILL****X";
3227        }
3228        if (temp.startsWith("G*G*GPPD"))
3229        {
3230            return "DECPNTFILL****X";
3231        }
3232
3233        return null;
3234    }
3235
3236    public static
3237            boolean isWeatherSPWithFill(String symbolID)
3238    {
3239        if (symbolID.equals("WOS-HPM-R-P----") ||//landing ring - brown 148,48,0
3240                symbolID.equals("WOS-HPD---P----") ||//dolphin facilities - brown
3241                symbolID.equals("WOS-HABB--P----") ||//buoy default - 255,0,255
3242                symbolID.equals("WOS-HHRS--P----") ||//rock submerged - 0,204,255
3243                symbolID.equals("WOS-HHDS--P----") ||//snags/stumps - 0,204,255
3244                symbolID.equals("WOS-HHDWB-P----") ||//wreck - 0,204,255
3245                symbolID.equals("WOS-TCCTG-P----"))//tide gauge - 210, 176, 106
3246        {
3247            return true;
3248        }
3249        else
3250        {
3251            return false;
3252        }
3253    }
3254
3255    /**
3256     * @name isSOF
3257     *
3258     * @desc Returns true if the symbolID is an SOF (special operations forces)
3259     * graphic
3260     *
3261     * @param strSymbolID - IN - SymbolID we are checking on
3262     * @return True if the graphic is a SOF in the MIL-STD 2525B, false
3263     * otherwise.
3264     */
3265    public static
3266            boolean isSOF(String strSymbolID)
3267    {
3268        try
3269        {
3270            boolean blRetVal = ((strSymbolID.charAt(0) == 'S') && (strSymbolID.charAt(2) == 'F'));
3271            return blRetVal;
3272        }
3273        catch (Throwable t)
3274        {
3275            System.out.println(t);
3276        }
3277        return false;
3278    } // End isSOF
3279
3280    /**
3281     * @desc Returns true if the symbol id is a Sonobuoy point symbol.
3282     *
3283     * @param strSymbolID - IN - Symbol Id we are checking to see if it is a
3284     * Sonobuoy Point
3285     * @return True if the graphic is a Decon Point in the MIL-STD 2525B, false
3286     * otherwise.
3287     */
3288    public static
3289            boolean isSonobuoy(String strSymbolID)
3290    {
3291        try
3292        {
3293            String basic = getBasicSymbolID(strSymbolID);
3294            boolean blRetVal = (basic.substring(0, 8).equals("G*G*GPUY"));
3295            return blRetVal;
3296        }
3297        catch (Throwable t)
3298        {
3299            System.out.println(t);
3300        }
3301        return false;
3302    } // End isSOF
3303
3304    /**
3305     * @name isSeaSurface
3306     *
3307     * @desc Returns true if the symbolID is an warfighting/seasurface graphic
3308     *
3309     * @param strSymbolID - IN - SymbolID we are checking on
3310     * @return True if the graphic is a seasurface in the MIL-STD 2525B, false
3311     * otherwise.
3312     */
3313    public static
3314            boolean isSeaSurface(String strSymbolID)
3315    {
3316        try
3317        {
3318            boolean blRetVal = ((strSymbolID.charAt(0) == 'S') && (strSymbolID.charAt(2) == 'S'));
3319            return blRetVal;
3320        }
3321        catch (Throwable t)
3322        {
3323            System.out.println(t);
3324        }
3325        return false;
3326    } // End isSOF
3327
3328    /**
3329     * @name isSubSurface
3330     *
3331     * @desc Returns true if the symbolID is an warfighting/subsurface graphic
3332     *
3333     * @param strSymbolID - IN - SymbolID we are checking on
3334     * @return True if the graphic is a subsurface in the MIL-STD 2525B, false
3335     * otherwise.
3336     */
3337    public static
3338            boolean isSubSurface(String strSymbolID)
3339    {
3340        try
3341        {
3342            boolean blRetVal = ((strSymbolID.charAt(0) == 'S') && (strSymbolID.charAt(2) == 'U'));
3343            return blRetVal;
3344        }
3345        catch (Throwable t)
3346        {
3347            System.out.println(t);
3348        }
3349        return false;
3350    } // End isSOF
3351
3352
3353    /**
3354     * @name isEquipment
3355     *
3356     * @desc Returns true if the symbol id is an Equipment Id (S*G*E).
3357     *
3358     * @param strSymbolID - IN - A MilStd2525B symbolID
3359     * @return True if symbol is Equipment, false otherwise.
3360     */
3361    public static
3362            boolean isEquipment(String strSymbolID)
3363    {
3364        try
3365        {
3366            boolean blRetVal = ((strSymbolID.charAt(0) == 'S')
3367                    && (strSymbolID.charAt(2) == 'G')
3368                    && (strSymbolID.charAt(4) == 'E'));
3369            // || isEMSEquipment(strSymbolID); //uncomment when supporting 2525C
3370            return blRetVal;
3371        }
3372        catch (Throwable t)
3373        {
3374            System.out.println(t);
3375        }
3376        return false;
3377    } // End IsEquipment
3378
3379    /**
3380     * determines if an EMS symbol (a symbol code that starts with 'E') Is an
3381     * equipment type. There is no logical pattern to EMS equipment symbol codes
3382     * so all we can do is check against a list of codes.
3383     *
3384     * @param strSymbolID
3385     * @return
3386     */
3387    public static
3388            boolean isEMSEquipment(String strSymbolID)
3389    {
3390        String basicCode = getBasicSymbolID(strSymbolID);
3391        boolean blRetVal = false;
3392        try
3393        {
3394            if (strSymbolID.startsWith("E"))
3395            {
3396                if (basicCode.equals("E*O*AB----*****") || //equipment
3397                        basicCode.equals("E*O*AE----*****") ||//ambulance
3398                        basicCode.equals("E*O*AF----*****") ||//medivac helicopter
3399                        basicCode.equals("E*O*BB----*****") ||//emergency operation equipment
3400                        basicCode.equals("E*O*CB----*****") ||//fire fighting operation equipment
3401                        basicCode.equals("E*O*CC----*****") ||//fire hydrant
3402                        basicCode.equals("E*O*DB----*****") ||//law enforcement operation equipment
3403                        //equipment for different service departments
3404                        (basicCode.startsWith("E*O*D") && basicCode.endsWith("B---*****"))
3405                        || //different sensor types
3406                        (basicCode.startsWith("E*O*E") && basicCode.endsWith("----*****"))
3407                        || basicCode.equals("E*F*BA----*****") ||//ATM
3408                        basicCode.equals("E*F*LF----*****") ||//Heli Landing site
3409                        basicCode.equals("E*F*MA----*****") ||//control valve
3410                        basicCode.equals("E*F*MC----*****"))// ||//discharge outfall
3411                {
3412                    blRetVal = true;
3413                }
3414            }
3415        }
3416        catch (Throwable t)
3417        {
3418            System.out.println(t);
3419        }
3420        return blRetVal;
3421    } // End IsEquipment
3422
3423    /**
3424     * determines if an symbol code represents an EMS (Emergency Management
3425     * Symbol). Returns true only for those that start with 'E'
3426     *
3427     * @return
3428     */
3429    public static
3430            boolean isEMS(String strSymbolID)
3431    {
3432        //String basicCode = getBasicSymbolID(strSymbolID);
3433        boolean blRetVal = false;
3434        try
3435        {
3436            if (strSymbolID.startsWith("E"))
3437            {
3438                blRetVal = true;
3439            }
3440        }
3441        catch (Throwable t)
3442        {
3443            System.out.println(t);
3444        }
3445        return blRetVal;
3446    }
3447
3448    /**
3449     * Determines if a symbol is an EMS Natural Event
3450     *
3451     * @param strSymbolID
3452     * @return
3453     */
3454    public static
3455            boolean isEMSNaturalEvent(String strSymbolID)
3456    {
3457        boolean blRetVal = false;
3458        try
3459        {
3460            if (strSymbolID.charAt(0) == 'E' && strSymbolID.charAt(2) == 'N')
3461            {
3462                blRetVal = true;
3463            }
3464        }
3465        catch (Throwable t)
3466        {
3467            System.out.println(t);
3468        }
3469        return blRetVal;
3470    }
3471
3472    /**
3473     * Determines if a symbol is an EMS Incident
3474     *
3475     * @param strSymbolID
3476     * @return
3477     */
3478    public static
3479            boolean isEMSIncident(String strSymbolID)
3480    {
3481        boolean blRetVal = false;
3482        try
3483        {
3484            if (strSymbolID.charAt(0) == 'E' && strSymbolID.charAt(2) == 'I')
3485            {
3486                blRetVal = true;
3487            }
3488        }
3489        catch (Throwable t)
3490        {
3491            System.out.println(t);
3492        }
3493        return blRetVal;
3494    }
3495
3496    /**
3497     * Determines if a symbol is an EMS Installation
3498     * @param strSymbolID
3499     * @return
3500     */
3501    public static boolean isEMSInstallation(String strSymbolID)
3502    {
3503        boolean blRetVal = false;
3504        try
3505        {
3506            if(strSymbolID.charAt(0)=='E')
3507            {
3508                if(strSymbolID.charAt(2)=='O' &&
3509                        strSymbolID.charAt(4)=='D' && (strSymbolID.charAt(6)=='C' || strSymbolID.charAt(5)=='K'))
3510                {
3511                    blRetVal = true;
3512                }
3513                else if(strSymbolID.charAt(2)=='F' &&
3514                        strSymbolID.substring(4, 6).equals("BA")==false)
3515                {
3516                    blRetVal = true;
3517                }
3518                else if(strSymbolID.charAt(2)=='O')
3519                {
3520                    if(strSymbolID.charAt(4)=='A')
3521                    {
3522                        switch(strSymbolID.charAt(5))
3523                        {
3524                            case 'C':
3525                            case 'D':
3526                            case 'G':
3527                            case 'J':
3528                            case 'K':
3529                            case 'L':
3530                            case 'M':
3531                                blRetVal = true;
3532                                break;
3533                            default:
3534                                break;
3535                        }
3536                    }
3537                    else if(strSymbolID.charAt(4)=='B')
3538                    {
3539                        switch(strSymbolID.charAt(5))
3540                        {
3541                            case 'C':
3542                            case 'E':
3543                            case 'F':
3544                            case 'G':
3545                            case 'H':
3546                            case 'I':
3547                            case 'K':
3548                            case 'L':
3549                                blRetVal = true;
3550                                break;
3551                            default:
3552                                break;
3553                        }
3554                    }
3555                    else if(strSymbolID.charAt(4)=='C')
3556                    {
3557                        switch(strSymbolID.charAt(5))
3558                        {
3559                            case 'D':
3560                            case 'E':
3561                                blRetVal = true;
3562                                break;
3563                            default:
3564                                break;
3565                        }
3566                    }
3567                }
3568            }
3569        }
3570        catch(Throwable t)
3571        {
3572            System.out.println(t);
3573        }
3574        return blRetVal;
3575    }
3576
3577    /**
3578     * @name isInstallation Warfighting ground installations. They are always
3579     * installations.
3580     * @desc Returns true if the symbol id is an installation (S*G*I).
3581     *
3582     * @param strSymbolID - IN - A MilStd2525B symbolID
3583     * @return True if symbol is an Installation, false otherwise.
3584     */
3585    public static boolean isInstallation(String strSymbolID)
3586    {
3587        try
3588        {
3589            boolean blRetVal = false;
3590            if(strSymbolID.charAt(0)=='S')
3591                blRetVal = ((strSymbolID.charAt(2) == 'G') && (strSymbolID.charAt(4) == 'I'));
3592            else if((strSymbolID.charAt(0)=='E'))
3593                blRetVal = isEMSInstallation(strSymbolID);
3594            return blRetVal;
3595        }
3596        catch (Throwable t)
3597        {
3598            System.out.println(t);
3599        }
3600        return false;
3601    } // End IsInstallation
3602
3603    /**
3604     * @name isSIGINT
3605     *
3606     * @desc Returns true if the symbol id is Signals Intelligence (SIGINT)
3607     * (starts with 'I').
3608     *
3609     * @param strSymbolID - IN - A MilStd2525B symbolID
3610     * @return True if symbol is a Signals Intelligence, false otherwise.
3611     */
3612    public static
3613            boolean isSIGINT(String strSymbolID)
3614    {
3615        try
3616        {
3617            boolean blRetVal = (strSymbolID.charAt(0) == 'I');
3618            return blRetVal;
3619        }
3620        catch (Throwable t)
3621        {
3622            System.out.println(t);
3623        }
3624        return false;
3625    } // End IsInstallation
3626
3627    /**
3628     * @name isFeintDummyInstallation
3629     *
3630     * @desc Returns true if the symbol id has a feint dummy installation
3631     * modifier
3632     *
3633     * @param strSymbolID - IN - A MilStd2525B symbolID
3634     * @return True if symbol has a feint dummy installation modifier, false
3635     * otherwise.
3636     */
3637    public static
3638            boolean isFeintDummyInstallation(String strSymbolID)
3639    {
3640        boolean feintDummyInstallationIsOn = false;
3641        try
3642        {
3643            // See if the feint dummy installation is on.
3644            feintDummyInstallationIsOn = (strSymbolID.charAt(10) == 'H' && strSymbolID.charAt(11) == 'B');
3645        }
3646        catch (Throwable t)
3647        {
3648            System.out.println(t);
3649        }
3650        // Return whether or not the feint dummy installation is on.
3651        return feintDummyInstallationIsOn;
3652    }
3653
3654
3655    /**
3656     * has an 'H' in the 11th position Any symbol can have this character added
3657     * to make it an installation.
3658     *
3659     * @param strSymbolID
3660     * @return
3661     */
3662    public static
3663            boolean hasInstallationModifier(String strSymbolID)
3664    {
3665        boolean hasInstallationModifier = false;
3666        try
3667        {
3668            // See if the feint dummy installation is on.
3669            hasInstallationModifier = (strSymbolID.charAt(10) == ('H'));
3670        }
3671        catch (Throwable t)
3672        {
3673            System.out.println(t);
3674        }
3675        // Return whether or not the feint dummy installation is on.
3676        return hasInstallationModifier;
3677    }
3678
3679    /**
3680     * @name getAffiliation
3681     *
3682     * @desc This operation will return the affiliation enumeration for the
3683     * given symbol id. If the symbol has an unknown or offbeat affiliation, the
3684     * affiliation of "U" will be returned.
3685     *
3686     * @param strSymbolID - IN - Symbol Id we want the affiliation of
3687     * @return The affiliation of the Symbol Id that was passed in.
3688     */
3689    public static
3690            char getAffiliation(String strSymbolID)
3691    {
3692        try
3693        {
3694            return strSymbolID.charAt(1);
3695        } // End try
3696        catch (Throwable t)
3697        {
3698            System.out.println(t);
3699        }
3700        return 'U';
3701    } // End GetAffiliation
3702
3703    /**
3704     * @name getStatus
3705     *
3706     * @desc Returns the status (present / planned) for the symbol id provided.
3707     * If the symbol contains some other status than planned or present, present
3708     * is returned by default (no unknown available).
3709     *
3710     * @param strSymbolID - IN - 15 char symbol code.
3711     * @return The status of the Symbol Id that was passed in.
3712     */
3713    public static
3714            String getStatus(String strSymbolID)
3715    {
3716        try
3717        {
3718            String strStatus = strSymbolID.substring(3, 4);
3719            return strStatus;
3720        }
3721        catch (Throwable t)
3722        {
3723            System.out.println(t);
3724        }
3725        return "P";
3726    } // End getStatus
3727
3728    /**
3729     * @name getEchelon
3730     *
3731     * @desc Returns the echelon enumeration for the symbol id provided. Note;
3732     * this works only with the sub-set of echelon codes tracked in the SymbolID
3733     * class. 2525 contains more codes than are tracked here. The 11th char of
3734     * the symbol id is used to determine the echelon. If we are unable to
3735     * determine the echelon, we return "NULL".
3736     *
3737     * @param strSymbolID - IN - 15 char symbol code.
3738     * @return The echelon of the Symbol Id that was passed in.
3739     */
3740    public static
3741            String getEchelon(String strSymbolID)
3742    {
3743        try
3744        {
3745            char tenth = strSymbolID.charAt(10);
3746            String strSubEch = null;
3747            if (tenth != 'H' && tenth != 'M' && tenth != 'N')
3748            {
3749                strSubEch = strSymbolID.substring(11, 12);
3750            }
3751            return strSubEch;
3752        } // End try
3753        catch (Throwable t)
3754        {
3755            System.out.println(t);
3756        }
3757        return "-";
3758    } // End getEchelon
3759
3760    /**
3761     * @name getSymbolModifier
3762     *
3763     * @desc Returns the enumeration belonging to the type of symbol modifier
3764     * used for this symbol ID.
3765     *
3766     * @param strSymbolID - IN - A valid 15 char MilStd2525B code.
3767     * @return The enumeration indicating which symbol modifier is turned on.
3768     * @deprecated 9/6/2013
3769     */
3770    public static
3771            String getSymbolModifier(String strSymbolID)
3772    {
3773        try
3774        {
3775            String strModifiers = strSymbolID.substring(10, 11);
3776            String subModifier;
3777            if (strModifiers.equals("A"))
3778            {
3779                return "A";
3780            }
3781            else if (strModifiers.equals("B"))
3782            {
3783                return "B";
3784            }
3785            else if (strModifiers.equals("C"))
3786            {
3787                return "C";
3788            }
3789            else if (strModifiers.equals("D"))
3790            {
3791                return "D";
3792            }
3793            else if (strModifiers.equals("E"))
3794            {
3795                return "E";
3796            }
3797            else if (strModifiers.equals("F"))
3798            {
3799                return "F";
3800            }
3801            else if (strModifiers.equals("G"))
3802            {
3803                return "G";
3804            }
3805            else if (strModifiers.equals("H"))
3806            {
3807                subModifier = strSymbolID.substring(11, 12);
3808                if (subModifier.equals("B"))
3809                {
3810                    return "HB";
3811                }
3812                else
3813                {
3814                    return "H";
3815                }
3816            }
3817            else if (strModifiers.equals("M"))
3818            {
3819                subModifier = strSymbolID.substring(11, 12);
3820                if (subModifier.equals("O"))
3821                {
3822                    return "MO";
3823                }
3824                else
3825                {
3826                    return "M";
3827                }
3828            }
3829        } // End try
3830        catch (Throwable t)
3831        {
3832            System.out.println(t);
3833        }
3834        return "-";
3835    } // End GetSymbolModifier
3836
3837
3838    public static String getUnitAffiliationModifier(String symbolID, int symStd)
3839    {
3840        String textChar = null;
3841        char affiliation;
3842
3843        try
3844        {
3845            affiliation = symbolID.charAt(1);
3846
3847            if (affiliation == ('F')
3848                    || affiliation == ('H')
3849                    || affiliation == ('U')
3850                    || affiliation == ('N')
3851                    || affiliation == ('P'))
3852            {
3853                textChar = null;
3854            }
3855            else if (affiliation == ('A')
3856                    || affiliation == ('S'))
3857            {
3858                if (symStd == RendererSettings.Symbology_2525B)
3859                {
3860                    textChar = "?";
3861                }
3862                else
3863                {
3864                    textChar = null;
3865                }
3866            }
3867            else if (affiliation == ('J'))
3868            {
3869                textChar = "J";
3870            }
3871            else if (affiliation == ('K'))
3872            {
3873                textChar = "K";
3874            }
3875            else if (affiliation == ('D')
3876                    || affiliation == ('L')
3877                    || affiliation == ('G')
3878                    || affiliation == ('W'))
3879            {
3880                textChar = "X";
3881            }
3882            else if (affiliation == ('M'))
3883            {
3884                if (symStd == RendererSettings.Symbology_2525B)
3885                {
3886                    textChar = "X?";
3887                }
3888                else
3889                {
3890                    textChar = "X";
3891                }
3892            }
3893
3894            //check sea mine symbols
3895            if (symStd == RendererSettings.Symbology_2525C)
3896            {
3897                if (symbolID.charAt(0) == 'S' && symbolID.indexOf("WM") == 4)
3898                {//variuos sea mine exercises
3899                    if (symbolID.indexOf("GX") == 6
3900                            || symbolID.indexOf("MX") == 6
3901                            || symbolID.indexOf("FX") == 6
3902                            || symbolID.indexOf("X") == 6
3903                            || symbolID.indexOf("SX") == 6)
3904                    {
3905                        textChar = "X";
3906                    }
3907                    else
3908                    {
3909                        textChar = null;
3910                    }
3911                }
3912            }
3913        }
3914        catch (Exception exc)
3915        {
3916            ErrorLogger.LogException("SymbolUtilities",
3917                    "getUnitAffiliationModifier", exc, Level.WARNING);
3918            return null;
3919        }
3920        return textChar;
3921    }
3922
3923    /**
3924     * checks symbol code to see if graphic has a DOM (Q) modifier
3925     *
3926     * @param symbolID
3927     * @param symStd RendererSettings.Symbology_2525C
3928     * @return
3929     */
3930    public static
3931            boolean hasDirectionOfMovement(String symbolID, int symStd)
3932    {
3933        SymbolDef temp = null;
3934        if (isNBC(symbolID))//just 3 NBCs have DOM
3935        {
3936            temp = SymbolDefTable.getInstance().getSymbolDef(getBasicSymbolID(symbolID), symStd);
3937            if (temp != null)
3938            {
3939                if (temp.getModifiers().indexOf("Q.") != -1)
3940                {
3941                    return true;
3942                }
3943                else
3944                {
3945                    return false;
3946                }
3947
3948            }
3949            else
3950            {
3951                return false;
3952            }
3953        }
3954        else if (isWarfighting(symbolID))//all warfighting has DOM
3955        {
3956            if (SymbolUtilities.isSIGINT(symbolID) == false)
3957            {
3958                return true;
3959            }
3960            else
3961            {
3962                return false;
3963            }
3964        }
3965        else
3966        {
3967            return false;
3968        }
3969    }
3970
3971    public static
3972            Boolean hasAMmodifierWidth(String symbolID)
3973    {
3974        return hasAMmodifierWidth(symbolID, rendererSettings.getSymbologyStandard());
3975    }
3976
3977    public static Boolean hasAMmodifierWidth(String symbolID, int symStd)
3978    {
3979        SymbolDef sd = null;
3980        Boolean returnVal = false;
3981        String basic = SymbolUtilities.getBasicSymbolID(symbolID);
3982
3983        sd = SymbolDefTable.getInstance().getSymbolDef(basic, symStd);
3984        if (sd != null)
3985        {
3986            int dc = sd.getDrawCategory();
3987
3988            switch (dc)
3989            {
3990                case SymbolDef.DRAW_CATEGORY_RECTANGULAR_PARAMETERED_AUTOSHAPE://width
3991                case SymbolDef.DRAW_CATEGORY_SECTOR_PARAMETERED_AUTOSHAPE:
3992                case SymbolDef.DRAW_CATEGORY_TWO_POINT_RECT_PARAMETERED_AUTOSHAPE:
3993                    returnVal = true;
3994                    break;
3995                default:
3996                    returnVal = false;
3997            }
3998        }
3999
4000        return returnVal;
4001    }
4002
4003    public static Boolean hasANmodifier(String symbolID)
4004    {
4005        return hasANmodifier(symbolID, rendererSettings.getSymbologyStandard());
4006    }
4007
4008    public static Boolean hasANmodifier(String symbolID, int symStd)
4009    {
4010        SymbolDef sd = null;
4011        Boolean returnVal = false;
4012        String basic = SymbolUtilities.getBasicSymbolID(symbolID);
4013
4014        sd = SymbolDefTable.getInstance().getSymbolDef(basic, symStd);
4015        if (sd != null)
4016        {
4017            int dc = sd.getDrawCategory();
4018
4019            switch (dc)
4020            {
4021                case SymbolDef.DRAW_CATEGORY_RECTANGULAR_PARAMETERED_AUTOSHAPE://width
4022                case SymbolDef.DRAW_CATEGORY_SECTOR_PARAMETERED_AUTOSHAPE:
4023                    returnVal = true;
4024                    break;
4025                /*case SymbolDef.DRAW_CATEGORY_LINE://air corridor
4026                        if(sd.getModifiers().indexOf(ModifiersTG.AN_AZIMUTH + ".") > -1)
4027                                returnVal = true;
4028                        break;//*/
4029                default:
4030                    returnVal = false;
4031            }
4032        }
4033
4034        return returnVal;
4035    }
4036
4037    public static Boolean hasAMmodifierRadius(String symbolID)
4038    {
4039        return hasAMmodifierRadius(symbolID, rendererSettings.getSymbologyStandard());
4040    }
4041
4042    public static Boolean hasAMmodifierRadius(String symbolID, int symStd)
4043    {
4044        SymbolDef sd = null;
4045        Boolean returnVal = false;
4046        String basic = SymbolUtilities.getBasicSymbolID(symbolID);
4047
4048        sd = SymbolDefTable.getInstance().getSymbolDef(basic, symStd);
4049        if (sd != null)
4050        {
4051            int dc = sd.getDrawCategory();
4052
4053            switch (dc)
4054            {
4055                case SymbolDef.DRAW_CATEGORY_CIRCULAR_PARAMETERED_AUTOSHAPE://radius
4056                case SymbolDef.DRAW_CATEGORY_CIRCULAR_RANGEFAN_AUTOSHAPE:
4057                    returnVal = true;
4058                    break;
4059                default:
4060                    returnVal = false;
4061            }
4062        }
4063
4064        return returnVal;
4065    }
4066
4067    /**
4068     * @name setAffiliation
4069     *
4070     * @desc Sets the affiliation for a Mil-Std 2525B symbol ID.
4071     *
4072     * @param strSymbolID - IN - A 15 character symbol ID
4073     * @param strSymbolID - IN - The affiliation we want to change the ID to.
4074     * @return A string with the affiliation changed to affiliationID
4075     */
4076    public static String setAffiliation(String strSymbolID, String strAffiliationID)
4077    {
4078        try
4079        {
4080            if (strSymbolID != null && strSymbolID.length() == 15 && isWeather(strSymbolID)==false
4081                    && strAffiliationID != null && strAffiliationID.length() == 1)
4082            {
4083                String strChangedID = strSymbolID.substring(0, 1) + strAffiliationID.toUpperCase() + strSymbolID.substring(2, 15);
4084                if (hasValidAffiliation(strChangedID))
4085                {
4086                    return strChangedID;
4087                }
4088                else
4089                {
4090                    return strSymbolID;
4091                }
4092            }
4093            else
4094            {
4095                return strSymbolID;
4096            }
4097        } // End try
4098        catch (Throwable t)
4099        {
4100            System.out.println(t);
4101        }
4102        return "";
4103    } // End SetAffiliation }
4104
4105    /**
4106     * @name setEchelon
4107     *
4108     * @desc Sets the echelon for a Mil-Std 2525B symbol ID.
4109     *
4110     * @param strSymbolID - IN - A 15 character symbol ID
4111     * @param strSymbolID - IN - A string representing the echelon we want to
4112     * change the ID to. The case of the string does not matter, it can be upper
4113     * or lower. The string is the name of the echelon and can be of the
4114     * following choices:
4115     *
4116     * Null, //- Team, Crew, //A Squad, //B Section, //C Platoon, Detachment //D
4117     * Company, Battery, Troop //E Battalion, Squadron, //F Regiment, Group, //G
4118     * Brigade, //H Division, //I Corps, Mef, //J Army, //K Army Group, Front,
4119     * //L Region //M
4120     * @return A symbol ID with the echelon changed to echelonID
4121     */
4122    public static
4123            String setEchelon(String strSymbolID, String strEchelon)
4124    {
4125        String strChangedID = strSymbolID;
4126        try
4127        {
4128            if (strSymbolID.length() == 15)
4129            {
4130                String strUppercaseEchelon = strEchelon.toUpperCase();
4131                strChangedID = strSymbolID.substring(0, 11) + strUppercaseEchelon + strSymbolID.substring(12, 15);
4132            } // End if (strSymbolID.Length == 15 &&
4133            // !SymbolUtilities.IsDrawingPrimitive(strSymbolID))
4134        } // End try
4135        catch (Throwable t)
4136        {
4137            System.out.println(t);
4138        }
4139        return strChangedID;
4140    } // End SetEchelon }}}}
4141
4142    /**
4143     * @name setStatus
4144     *
4145     * @desc Sets the status for a Mil-Std 2525B symbol ID.
4146     *
4147     * @param strSymbolID - IN - A 15 character symbol ID
4148     * @param strStatusID - IN - The status we want to change the ID to.
4149     * "present", "planned", "anticipated", "plannedanticipated"
4150     * @return A string with the status changed to statusID
4151     * @deprecated
4152     */
4153    public static String setStatus(String strSymbolID, String strStatusID)
4154    {
4155        // PlannedAnticipated, //A
4156        // Present //P
4157        String changedID = strSymbolID;
4158        try
4159        {
4160            if ((strSymbolID.length() == 15)
4161                    && (!isWeather(strSymbolID)) && (!isBasicShape(strSymbolID)))
4162            {
4163                if (strStatusID.toLowerCase().equals("present"))
4164                {
4165                    changedID = strSymbolID.substring(0, 3) + "P" + strSymbolID.substring(4, 15);
4166                }
4167                else if (strStatusID.equalsIgnoreCase("planned")
4168                        || strStatusID.equalsIgnoreCase("anticipated")
4169                        || strStatusID.equalsIgnoreCase("plannedanticipated"))
4170                {
4171                    changedID = strSymbolID.substring(0, 3) + "A" + strSymbolID.substring(4, 15);
4172                }
4173            } // End if((strSymbolID.Length == 15) && (!
4174            // SymbolUtilities.IsDrawingPrimitive(strSymbolID)))
4175        }
4176        catch (Throwable t)
4177        {
4178            System.out.println(t);
4179        }
4180        return changedID;
4181    } // End SetStatus
4182
4183    /**
4184     * @name setSymbolModifier
4185     *
4186     * @desc Sets the symbol modifier for a Mil-Std 2525B symbol ID.
4187     *
4188     * @param strSymbolID - IN - A 15 character symbol ID
4189     * @param symbolModifierID - IN - The symbolModifier we want to change the
4190     * ID to.
4191     * @return A symbol ID with the symbolModifier changed to symbolModifierID
4192     * @deprecated
4193     */
4194    public static
4195            String setSymbolModifier(String strSymbolID, String symbolModifierID)
4196    {
4197        String strChangedID = strSymbolID;
4198        if (strSymbolID.length() == 15)
4199        {
4200            if (symbolModifierID.equals("-"))
4201            {
4202                if (isMobilityWheeled(strSymbolID) || isFeintDummyInstallation(strSymbolID))
4203                {
4204                    strChangedID = strSymbolID.substring(0, 10) + "--" + strSymbolID.substring(12, 15);
4205                }
4206                else
4207                {
4208                    strChangedID = strSymbolID.substring(0, 10) + "-" + strSymbolID.substring(11, 15);
4209                }
4210            }
4211            else if (symbolModifierID.equals("A"))
4212            {
4213                strChangedID = strSymbolID.substring(0, 10) + "A" + strSymbolID.substring(11, 15);
4214            }
4215            else if (symbolModifierID.equals("B"))
4216            {
4217                strChangedID = strSymbolID.substring(0, 10) + "B" + strSymbolID.substring(11, 15);
4218            }
4219            else if (symbolModifierID.equals("C"))
4220            {
4221                strChangedID = strSymbolID.substring(0, 10) + "C" + strSymbolID.substring(11, 15);
4222            }
4223            else if (symbolModifierID.equals("D"))
4224            {
4225                strChangedID = strSymbolID.substring(0, 10) + "D" + strSymbolID.substring(11, 15);
4226            }
4227            else if (symbolModifierID.equals("E"))
4228            {
4229                strChangedID = strSymbolID.substring(0, 10) + "E" + strSymbolID.substring(11, 15);
4230            }
4231            else if (symbolModifierID.equals("F"))
4232            {
4233                strChangedID = strSymbolID.substring(0, 10) + "F" + strSymbolID.substring(11, 15);
4234            }
4235            else if (symbolModifierID.equals("G"))
4236            {
4237                strChangedID = strSymbolID.substring(0, 10) + "G" + strSymbolID.substring(11, 15);
4238            }
4239            else if (symbolModifierID.equals("HB"))
4240            {
4241                strChangedID = strSymbolID.substring(0, 10) + "HB" + strSymbolID.substring(12, 15);
4242            }
4243            else if (symbolModifierID.equals("HH"))
4244            {
4245                strChangedID = strSymbolID.substring(0, 10) + "H" + strSymbolID.substring(11, 15);
4246            }
4247            else if (symbolModifierID.equals("M"))
4248            {
4249                strChangedID = strSymbolID.substring(0, 10) + "M" + strSymbolID.substring(11, 15);
4250            }
4251            else if (symbolModifierID.equals("MO"))
4252            {
4253                strChangedID = strSymbolID.substring(0, 10) + "MO" + strSymbolID.substring(12, 15);
4254            }
4255        } // End if
4256        return strChangedID;
4257    } // End SetSymbolModifier
4258
4259}