/// <summary>
        /// After data has been read, extract operator records from the collected data.
        /// </summary>
        private void ExtractOperatorRecords()
        {
            foreach (String key in HD.Keys)
            {
                OperatorRecord rec = new OperatorRecord();
                List <String>  hd  = HD[key].Fields;

                Tuple <RadioService, String> serviceType = GetRadioServiceType(hd[6]);

                rec.CallSign                = key;
                rec.RadioService            = serviceType.Item1;
                rec.RadioServiceDescription = serviceType.Item2;
                rec.LicenseKey              = hd[1];
                rec.Frequency               = hd[2];
                rec.Granted    = ParseNullableDate(hd[7]);
                rec.Expiration = ParseNullableDate(hd[8]);
                rec.Cancelled  = ParseNullableDate(hd[9]);
                rec.Effective  = ParseNullableDate(hd[42]);

                if (EN.ContainsKey(key))
                {
                    List <String> en = EN[key].Fields;
                    rec.Organization  = Util.ToTitleCase(en[7]);
                    rec.FirstName     = Util.ToTitleCase(en[8]);
                    rec.MiddleInitial = Util.ToTitleCase(en[9]);
                    rec.LastName      = Util.ToTitleCase(en[10]);
                    rec.Suffix        = Util.ToTitleCase(en[11]);
                    rec.Address       = Util.ToTitleCase(en[15])?.Replace("Th ", "th ");
                }

                if (AM.ContainsKey(key))
                {
                    List <String> am = AM[key].Fields;
                    Tuple <OperatorClass, String> ocType = GetOperatorClassType(am[5]);
                    rec.OperatorClass            = ocType.Item1;
                    rec.OperatorClassDescription = ocType.Item2;
                    rec.Group = am[6];
                }

                if (LM.ContainsKey(key))
                {
                    List <String> lm = LM[key].Fields;
                    rec.LicenseEligibility = lm[6];
                }

                if (HS.ContainsKey(key))
                {
                    rec.History.AddRange(HS[key].OrderBy(x => x.Date).ToList());
                }

                Operators.Add(rec);
            }
        }
        /// <summary>
        /// Read a data file downloaded from the FCC Univeral License System advanced search and fill the collection with its data.
        /// </summary>
        /// <param name="filename">Path to downloaded file.</param>
        public void ReadFile(String filename)
        {
            var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);

            using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
            {
                string line;
                while ((line = streamReader.ReadLine()) != null)
                {
                    if (!String.IsNullOrEmpty(line))
                    {
                        string[] tokens = line.Split(new char[] { '|' }, StringSplitOptions.None);
                        if (tokens != null && tokens.Length > 4)
                        {
                            string typeToken = tokens[0];
                            string callSign  = "";
                            if (!String.IsNullOrEmpty(typeToken))
                            {
                                if (typeToken.Equals("HD"))
                                {
                                    callSign = tokens[4];
                                    if (!HD.ContainsKey(callSign))
                                    {
                                        HD.Add(callSign, new TokenCollection(tokens));
                                    }
                                }
                                else if (typeToken.Equals("EN"))
                                {
                                    callSign = tokens[4];
                                    if (!EN.ContainsKey(callSign))
                                    {
                                        EN.Add(callSign, new TokenCollection(tokens));
                                    }
                                }
                                else if (typeToken.Equals("HS"))
                                {
                                    callSign = tokens[3];
                                    Tuple <HistoryRecordAction, String> actionType = GetHistoryActionType(tokens[5]);
                                    HistoryRecord rec = new HistoryRecord()
                                    {
                                        CallSign          = callSign,
                                        LicenseKey        = tokens[1],
                                        Date              = DateTime.ParseExact(tokens[4], "MM/dd/yyyy", CultureInfo.InvariantCulture),
                                        Action            = actionType.Item1,
                                        ActionDescription = actionType.Item2
                                    };
                                    if (!HS.ContainsKey(callSign))
                                    {
                                        List <HistoryRecord> recList = new List <HistoryRecord>();
                                        recList.Add(rec);
                                        HS.Add(callSign, recList);
                                    }
                                    else
                                    {
                                        HS[callSign].Add(rec);
                                    }
                                }
                                else if (typeToken.Equals("AM"))
                                {
                                    callSign = tokens[4];
                                    if (!AM.ContainsKey(callSign))
                                    {
                                        AM.Add(callSign, new TokenCollection(tokens));
                                    }
                                }
                                else if (typeToken.Equals("SC"))
                                {
                                    callSign = tokens[4];
                                    if (!SC.ContainsKey(callSign))
                                    {
                                        SC.Add(callSign, new TokenCollection(tokens));
                                    }
                                }
                                else if (typeToken.Equals("CO"))
                                {
                                    callSign = tokens[4];
                                    if (!CO.ContainsKey(callSign))
                                    {
                                        CO.Add(callSign, new TokenCollection(tokens));
                                    }
                                }
                                else if (typeToken.Equals("LM"))
                                {
                                    callSign = tokens[4];
                                    if (!LM.ContainsKey(callSign))
                                    {
                                        LM.Add(callSign, new TokenCollection(tokens));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            ExtractOperatorRecords();
        }