/// <summary>
        /// Internal helper method used by check that iterates over
        /// the keys of readerFieldToValIds and generates a Collection
        /// of Insanity instances whenever two (or more) ReaderField instances are
        /// found that have an ancestry relationships.
        /// </summary>
        /// <seealso cref= InsanityType#SUBREADER </seealso>
        private ICollection<Insanity> CheckSubreaders(MapOfSets<int, FieldCache_Fields.CacheEntry> valIdToItems, MapOfSets<ReaderField, int> readerFieldToValIds)
        {
            List<Insanity> insanity = new List<Insanity>(23);

            Dictionary<ReaderField, HashSet<ReaderField>> badChildren = new Dictionary<ReaderField, HashSet<ReaderField>>(17);
            MapOfSets<ReaderField, ReaderField> badKids = new MapOfSets<ReaderField, ReaderField>(badChildren); // wrapper

            IDictionary<int, HashSet<FieldCache_Fields.CacheEntry>> viToItemSets = valIdToItems.Map;
            IDictionary<ReaderField, HashSet<int>> rfToValIdSets = readerFieldToValIds.Map;

            HashSet<ReaderField> seen = new HashSet<ReaderField>();

            //IDictionary<ReaderField, ISet<int>>.KeyCollection readerFields = rfToValIdSets.Keys;
            foreach (ReaderField rf in rfToValIdSets.Keys)
            {
                if (seen.Contains(rf))
                {
                    continue;
                }

                IList<object> kids = GetAllDescendantReaderKeys(rf.ReaderKey);
                foreach (object kidKey in kids)
                {
                    ReaderField kid = new ReaderField(kidKey, rf.FieldName);

                    if (badChildren.ContainsKey(kid))
                    {
                        // we've already process this kid as RF and found other problems
                        // track those problems as our own
                        badKids.Put(rf, kid);
                        badKids.PutAll(rf, badChildren[kid]);
                        badChildren.Remove(kid);
                    }
                    else if (rfToValIdSets.ContainsKey(kid))
                    {
                        // we have cache entries for the kid
                        badKids.Put(rf, kid);
                    }
                    seen.Add(kid);
                }
                seen.Add(rf);
            }

            // every mapping in badKids represents an Insanity
            foreach (ReaderField parent in badChildren.Keys)
            {
                HashSet<ReaderField> kids = badChildren[parent];

                List<FieldCache_Fields.CacheEntry> badEntries = new List<FieldCache_Fields.CacheEntry>(kids.Count * 2);

                // put parent entr(ies) in first
                {
                    foreach (int value in rfToValIdSets[parent])
                    {
                        badEntries.AddRange(viToItemSets[value]);
                    }
                }

                // now the entries for the descendants
                foreach (ReaderField kid in kids)
                {
                    foreach (int value in rfToValIdSets[kid])
                    {
                        badEntries.AddRange(viToItemSets[value]);
                    }
                }

                FieldCache_Fields.CacheEntry[] badness = new FieldCache_Fields.CacheEntry[badEntries.Count];
                badness = badEntries.ToArray();//LUCENE TO-DO had param of badness first

                insanity.Add(new Insanity(InsanityType.SUBREADER, "Found caches for descendants of " + parent.ToString(), badness));
            }

            return insanity;
        }
        /// <summary>
        /// Internal helper method used by check that iterates over
        /// valMismatchKeys and generates a Collection of Insanity
        /// instances accordingly.  The MapOfSets are used to populate
        /// the Insanity objects. </summary>
        /// <seealso cref= InsanityType#VALUEMISMATCH </seealso>
        private ICollection<Insanity> CheckValueMismatch(MapOfSets<int, FieldCache_Fields.CacheEntry> valIdToItems, MapOfSets<ReaderField, int> readerFieldToValIds, ISet<ReaderField> valMismatchKeys)
        {
            List<Insanity> insanity = new List<Insanity>(valMismatchKeys.Count * 3);

            if (valMismatchKeys.Count != 0)
            {
                // we have multiple values for some ReaderFields

                IDictionary<ReaderField, HashSet<int>> rfMap = readerFieldToValIds.Map;
                IDictionary<int, HashSet<FieldCache_Fields.CacheEntry>> valMap = valIdToItems.Map;
                foreach (ReaderField rf in valMismatchKeys)
                {
                    IList<FieldCache_Fields.CacheEntry> badEntries = new List<FieldCache_Fields.CacheEntry>(valMismatchKeys.Count * 2);
                    foreach (int value in rfMap[rf])
                    {
                        foreach (FieldCache_Fields.CacheEntry cacheEntry in valMap[value])
                        {
                            badEntries.Add(cacheEntry);
                        }
                    }

                    FieldCache_Fields.CacheEntry[] badness = new FieldCache_Fields.CacheEntry[badEntries.Count];
                    badness = badEntries.ToArray(); //LUCENE TO-DO had param of badness before

                    insanity.Add(new Insanity(InsanityType.VALUEMISMATCH, "Multiple distinct value objects for " + rf.ToString(), badness));
                }
            }
            return insanity;
        }