001/*
002 * To change this template, choose Tools | Templates and open the template in the editor.
003 */
004package armyc2.c2sd.renderer.utilities;
005
006/*
007 * import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import
008 * javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.*; import org.xml.sax.SAXException;
009 * import java.io.*; import java.util.HashMap; import java.util.Map;
010 */
011
012import armyc2.c2sd.renderer.R;
013
014import android.content.Context;
015import android.util.Log;
016
017import java.io.BufferedInputStream;
018import java.io.BufferedReader;
019import java.io.DataInputStream;
020import java.io.DataOutputStream;
021import java.io.File;
022import java.io.FileNotFoundException;
023import java.io.FileOutputStream;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.InputStreamReader;
027import java.util.ArrayList;
028import java.util.HashMap;
029import java.util.Map;
030
031import org.w3c.dom.Document;
032import org.w3c.dom.Node;
033import org.w3c.dom.NodeList;
034
035/**
036 * Responsible for loading tactical graphic symbol definitions into a hash table.
037 *
038 * @author michael.spinelli
039 */
040@SuppressWarnings("unused")
041public class SymbolDefTable
042{
043
044    private static SymbolDefTable _instance = null;
045    private static Boolean _initCalled = false;
046    // private static SymbolTableThingy
047    private static Map<String, SymbolDef> _SymbolDefinitionsB = null;
048    private static ArrayList<SymbolDef> _SymbolDefDupsB = null;
049    private String TAG = "SymbolDefTable";
050
051    private static Map<String, SymbolDef> _SymbolDefinitionsC = null;
052    private static ArrayList<SymbolDef> _SymbolDefDupsC = null;
053
054    private static String propSymbolID = "SYMBOLID";
055    private static String propGeometry = "GEOMETRY";
056    private static String propDrawCategory = "DRAWCATEGORY";
057    private static String propMaxPoint = "MAXPOINTS";
058    private static String propMinPoints = "MINPOINTS";
059    private static String propHasWidth = "HASWIDTH";
060    private static String propModifiers = "MODIFIERS";
061    private static String propDescription = "DESCRIPTION";
062    private static String propHierarchy = "HIERARCHY";
063
064    /*
065     * Holds SymbolDefs for all symbols. (basicSymbolID, Description, MinPoint, MaxPoints, etc...) Call
066     * getInstance().
067     *
068     */
069    private SymbolDefTable()
070    {
071        // init(null);
072        // _initCalled=true;
073    }
074
075    public static synchronized SymbolDefTable getInstance()
076    {
077        if (_instance == null) {
078            _instance = new SymbolDefTable();
079        }
080
081        return _instance;
082    }
083
084    public final synchronized void init(Context context)
085    {
086        if (_initCalled == false) {
087            _SymbolDefinitionsB = new HashMap<>();
088            _SymbolDefDupsB = new ArrayList<>();
089
090            _SymbolDefinitionsC = new HashMap<>();
091            _SymbolDefDupsC = new ArrayList<>();
092
093            try {
094                DataInputStream dis = new DataInputStream(new BufferedInputStream(context.getResources().openRawResource(R.raw.symbolconstants)));
095                readBinary(dis);
096                dis.close();
097            } catch (IOException e) {
098                Log.e("SymbolDefTable", "Could not load", e);
099            }
100            _initCalled = true;
101        }
102    }
103
104    /**
105     * @name getSymbolDef
106     *
107     * @desc Returns a SymbolDef from the SymbolDefTable that matches the passed in Symbol Id
108     *
109     * @param basicSymbolID - IN - A 15 character MilStd code
110     * @param symStd 0 or 1.
111     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525Bch2_USAS_13_14
112     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525C
113     * @return SymbolDef whose Symbol Id matches what is passed in
114     */
115    public SymbolDef getSymbolDef(String basicSymbolID, int symStd)
116    {
117        SymbolDef returnVal = null;
118        if (symStd == RendererSettings.Symbology_2525B) {
119            returnVal = (SymbolDef) _SymbolDefinitionsB.get(basicSymbolID);
120        } else if (symStd == RendererSettings.Symbology_2525C) {
121            returnVal = (SymbolDef) _SymbolDefinitionsC.get(basicSymbolID);
122        }
123        return returnVal;
124    }
125
126    /**
127     * Returns a Map of all the symbol definitions, keyed on basic symbol code.
128     *
129     * @param symStd 0 or 1.
130     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525Bch2_USAS_13_14
131     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525C
132     * @return
133     */
134    public Map<String, SymbolDef> GetAllSymbolDefs(int symStd)
135    {
136        if (symStd == RendererSettings.Symbology_2525B) {
137            return _SymbolDefinitionsB;
138        } else if (symStd == RendererSettings.Symbology_2525C) {
139            return _SymbolDefinitionsC;
140        } else {
141            return null;
142        }
143    }
144
145    /**
146     * SymbolIDs are no longer unique thanks to 2525C and some EMS symbols.
147     * Here are the EMS symbols that reused symbol IDs.
148     * Like how EMS.INCDNT.CVDIS.DISPOP uses the same symbol code as STBOPS.ITM.RFG (O*I*R-----*****)
149     *
150     * @param symStd 0 or 1.
151     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525Bch2_USAS_13_14
152     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525C
153     * @return
154     */
155    public ArrayList<SymbolDef> GetAllSymbolDefDups(int symStd)
156    {
157        if (symStd == RendererSettings.Symbology_2525B) {
158            return _SymbolDefDupsB;
159        } else if (symStd == RendererSettings.Symbology_2525C) {
160            return _SymbolDefDupsC;
161        } else {
162            return null;
163        }
164    }
165
166    /**
167     *
168     * @param basicSymbolID
169     * @param symStd 0 or 1.
170     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525Bch2_USAS_13_14
171     * @see ArmyC2.C2SD.Utilities.RendererSettings#Symbology_2525C
172     * @return
173     */
174    public Boolean HasSymbolDef(String basicSymbolID, int symStd)
175    {
176        if (basicSymbolID != null && basicSymbolID.length() == 15) {
177            if (symStd == RendererSettings.Symbology_2525B) {
178                return _SymbolDefinitionsB.containsKey(basicSymbolID);
179            } else if (symStd == RendererSettings.Symbology_2525C) {
180                return _SymbolDefinitionsC.containsKey(basicSymbolID);
181            } else {
182                return false;
183            }
184        } else {
185            return false;
186        }
187    }
188
189    /**
190     * Checks if symbol is a multipoint symbol
191     *
192     * @param symbolID
193     * @param symStd
194     * @return
195     */
196    public Boolean isMultiPoint(String symbolID, int symStd)
197    {
198
199        String basicSymbolID;
200
201        char codingScheme = symbolID.charAt(0);
202        Boolean returnVal = false;
203        if (codingScheme == 'G' || codingScheme == 'W') {
204            if (symbolID.charAt(1) != '*') {
205                basicSymbolID = SymbolUtilities.getBasicSymbolID(symbolID);
206            } else {
207                basicSymbolID = symbolID;
208            }
209            SymbolDef sd = this.getSymbolDef(basicSymbolID, symStd);
210            if (sd != null) {
211                if (sd.getMaxPoints() > 1) {
212                    returnVal = true;
213                } else {
214                    switch (sd.getDrawCategory()) {
215                        case 15:// SymbolDef.DRAW_CATEGORY_RECTANGULAR_PARAMETERED_AUTOSHAPE:
216                        case 16:// SymbolDef.DRAW_CATEGORY_SECTOR_PARAMETERED_AUTOSHAPE:
217                        case 17:// SymbolDef.DRAW_CATEGORY_TWO_POINT_RECT_PARAMETERED_AUTOSHAPE:
218                        case 18:// SymbolDef.DRAW_CATEGORY_CIRCULAR_PARAMETERED_AUTOSHAPE:
219                        case 19:// SymbolDef.DRAW_CATEGORY_CIRCULAR_RANGEFAN_AUTOSHAPE:
220                        case 20:// SymbolDef.DRAW_CATEGORY_ROUTE:
221                            returnVal = true;
222                            break;
223                        default:
224                            returnVal = false;
225                    }
226                }
227                return returnVal;
228            } else {
229                return false;
230            }
231        } else if (symbolID.startsWith("BS_") || symbolID.startsWith("BBS_") || symbolID.startsWith("PBS_")) {
232            return true;
233        } else {
234            return false;
235        }
236    }
237
238    private void readBinary(DataInputStream dis) throws IOException
239    {
240        int count = dis.readInt();
241        for (int i = 0; i < count; i++) {
242            SymbolDef def = SymbolDef.readBinary(dis);
243            _SymbolDefinitionsB.put(def._strBasicSymbolId, def);
244        }
245
246        count = dis.readInt();
247        for (int i = 0; i < count; i++) {
248            SymbolDef def = SymbolDef.readBinary(dis);
249            _SymbolDefDupsB.add(def);
250        }
251
252        count = dis.readInt();
253        for (int i = 0; i < count; i++) {
254            SymbolDef def = SymbolDef.readBinary(dis);
255            _SymbolDefinitionsC.put(def._strBasicSymbolId, def);
256        }
257
258        count = dis.readInt();
259        for (int i = 0; i < count; i++) {
260            SymbolDef def = SymbolDef.readBinary(dis);
261            _SymbolDefDupsC.add(def);
262        }
263    }
264}