/// <summary>
        /// Add the given record to the database with the given XRef
        /// </summary>
        /// <param name="xrefID">
        /// A <see cref="string"/>
        /// </param>
        /// <param name="record">
        /// A <see cref="GedcomRecord"/>
        /// </param>
        public virtual void Add(string xrefID, GedcomRecord record)
        {
            Table.Add(xrefID, record);

            if (record is GedcomIndividualRecord)
            {
                GedcomIndividualRecord indi = (GedcomIndividualRecord)record;

                int pos = individuals.BinarySearch(indi);
                if (pos < 0)
                {
                    pos = ~pos;
                }

                individuals.Insert(pos, indi);
            }
            else if (record is GedcomFamilyRecord)
            {
                families.Add((GedcomFamilyRecord)record);
            }
            else if (record is GedcomSourceRecord)
            {
                GedcomSourceRecord source = (GedcomSourceRecord)record;

                int pos = sources.BinarySearch(source);
                if (pos < 0)
                {
                    pos = ~pos;
                }

                sources.Insert(pos, source);
            }
            else if (record is GedcomRepositoryRecord)
            {
                GedcomRepositoryRecord repo = (GedcomRepositoryRecord)record;

                int pos = repositories.BinarySearch(repo);
                if (pos < 0)
                {
                    pos = ~pos;
                }

                repositories.Insert(pos, repo);
            }
            else if (record is GedcomMultimediaRecord)
            {
                media.Add((GedcomMultimediaRecord)record);
            }
            else if (record is GedcomNoteRecord)
            {
                notes.Add((GedcomNoteRecord)record);
            }
            else if (record is GedcomSubmitterRecord)
            {
                submitters.Add((GedcomSubmitterRecord)record);
            }

            record.Database = this;
        }
        /// <summary>
        /// Compares the inheriting instance user entered data against the passed GedcomRecord.
        /// If that matches, will then compare the common elements of the passed GedcomRecord
        /// against this instance (Source etc. which are common to all inheritors).
        /// </summary>
        /// <param name="obj">The GedcomRecord to compare against.</param>
        /// <returns>True if the core base properties match, otherwise False.</returns>
        public bool Equals(GedcomRecord obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return(false);
            }

            // Ask the inheriting object if its user entered data is the same.
            if (!IsEquivalentTo(obj))
            {
                return(false);
            }

            var record = obj as GedcomRecord;

            if (!Equals(ChangeDate, record.ChangeDate))
            {
                return(false);
            }

            if (!Equals(Level, record.Level))
            {
                return(false);
            }

            if (!Equals(RestrictionNotice, record.RestrictionNotice))
            {
                return(false);
            }

            if (!GedcomGenericListComparer.CompareGedcomRecordLists(Sources, record.Sources))
            {
                return(false);
            }

            if (!GedcomGenericListComparer.CompareLists(Multimedia, record.Multimedia))
            {
                return(false);
            }

            /* TODO: Notes are hard work, we need to do lookups by xref instead of just having a list of GedcomNote records attached. Need to fix this as a pain to test and use as well.
             * //if (!GedcomGenericListComparer.CompareLists(Notes, record.Notes))
             * //{
             * //    return false;
             * //}
             */

            return(true);
        }
        /// <summary>
        /// Remove the given record with the given XRef from the database
        /// </summary>
        /// <param name="xrefID">
        /// A <see cref="string"/>
        /// </param>
        /// <param name="record">
        /// A <see cref="GedcomRecord"/>
        /// </param>
        public virtual void Remove(string xrefID, GedcomRecord record)
        {
            if (Table.Contains(xrefID))
            {
                Table.Remove(xrefID);

                if (record is GedcomIndividualRecord)
                {
                    GedcomIndividualRecord indi = (GedcomIndividualRecord)record;

                    individuals.Remove(indi);

                    // remove names from surname cache
                    foreach (GedcomName name in indi.Names)
                    {
                        // TODO: not right, need to include prefix + suffix
                        string surname = name.Surname;

                        if (surnames.ContainsKey(surname))
                        {
                            int count = surnames[surname];
                            count--;
                            if (count > 0)
                            {
                                surnames[surname] = count;
                            }
                            else
                            {
                                surnames.Remove(surname);
                            }
                        }
                    }
                }
                else if (record is GedcomFamilyRecord)
                {
                    families.Remove((GedcomFamilyRecord)record);
                }
                else if (record is GedcomSourceRecord)
                {
                    sources.Remove((GedcomSourceRecord)record);
                }
                else if (record is GedcomRepositoryRecord)
                {
                    repositories.Remove((GedcomRepositoryRecord)record);
                }
                else if (record is GedcomMultimediaRecord)
                {
                    media.Remove((GedcomMultimediaRecord)record);
                }
                else if (record is GedcomNoteRecord)
                {
                    notes.Remove((GedcomNoteRecord)record);
                }
                else if (record is GedcomSubmitterRecord)
                {
                    submitters.Remove((GedcomSubmitterRecord)record);
                }

                // TODO: should we set this to null? part of the deletion
                // methods may still want to access the database
                // record.Database = null;
            }
        }