/// <summary>
        /// Performs the data indexing.
        /// </summary>
        protected override void PerformIndexing()
        {
            Display("Indexing events using cutoff of " + Cutoff);
            Display("\tComputing event counts...");

            var fileName       = Path.GetTempFileName();
            var predicateIndex = new Dictionary <string, int>();

            using (var file = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose)) {
                var writer    = new StreamWriter(new UnclosableStream(file), Encoding.UTF8);
                int numEvents = ComputeEventCounts(writer, predicateIndex);

                Display("done. " + numEvents + " events");

                file.Seek(0, SeekOrigin.Begin);

                Display("\tIndexing...");
                var fes = new FileEventStream(file);

                var eventsToCompare = Index(fes, predicateIndex);

                file.Close();

                Display("done.");

                Display(Sort ? "Sorting and merging events..." : "Collecting events...");

                SortAndMerge(eventsToCompare, Sort);

                Display("Done indexing.");
            }
        }
        /// <summary>
        /// Reads events into a linked list. The predicates associated with each event are
        /// counted and any which occur at least N times (cutoff) are added to the
        /// <paramref name="predicatesInOut"/> map along with a unique integer index.
        /// </summary>
        /// <param name="eventStore">A writer to which the events are written to for later processing.</param>
        /// <param name="predicatesInOut">The predicates in out.</param>
        /// <returns>The number of events readed from the event stream.</returns>
        private int ComputeEventCounts(StreamWriter eventStore, Dictionary <string, int> predicatesInOut)
        {
            int eventCount = 0;
            var counter    = new Dictionary <string, int>();
            //var predicateSet = new Java.HashSet<string>();

            var predicateSet = new HashSet <string>();

            Event ev;

            while ((ev = EventStream.Read()) != null)
            {
                if (Monitor != null && Monitor.Token.CanBeCanceled)
                {
                    Monitor.Token.ThrowIfCancellationRequested();
                }

                eventCount++;

                eventStore.Write(FileEventStream.ToLine(ev));

                Update(ev.Context, predicateSet, counter, Cutoff);
            }

            predCounts = new int[predicateSet.Count];
            int index = 0;

            for (var e = predicateSet.GetEnumerator(); e.MoveNext(); index++)
            {
                if (e.Current != null)
                {
                    predCounts[index] = counter[e.Current];
                    predicatesInOut.Add(e.Current, index);
                }
            }
            eventStore.Flush();
            eventStore.Close();

            return(eventCount);
        }