/// <summary>
        /// Rewrite an <see cref="AndCriteria" /> as a <see cref="BoolCriteria" />.
        /// </summary>
        /// <param name="and"><see cref="AndCriteria" /> to rewrite.</param>
        /// <returns><see cref="BoolCriteria" /> with the criteria from the And mapped into Must.</returns>
        static BoolCriteria Rewrite(AndCriteria and)
        {
            var should  = and.Criteria.OfType <OrCriteria>().ToList();
            var mustNot = and.Criteria.OfType <NotCriteria>().ToList();
            var must    = and.Criteria.Except(should).Except(mustNot);

            return(new BoolCriteria(must.Select(Compensate),
                                    should.SelectMany(c => c.Criteria).Select(Compensate),
                                    mustNot.Select(c => c.Criteria).Select(Compensate)));
        }
        /// <summary>
        /// Reduce a <see cref="AndCriteria" /> that might contain a <see cref="ConstantCriteria" />.
        /// </summary>
        /// <param name="andCriteria"><see cref="AndCriteria" /> to be reduced.</param>
        /// <returns>Reduced criteria.</returns>
        /// <remarks>
        /// Trues will be removed, falses will replace the entire And with a false.
        /// </remarks>
        static ICriteria Reduce(AndCriteria andCriteria)
        {
            if (andCriteria.Criteria.Contains(ConstantCriteria.False))
            {
                return(ConstantCriteria.False);
            }

            return(AndCriteria
                   .Combine(andCriteria
                            .Criteria
                            .Select(Reduce)
                            .Where(c => c != ConstantCriteria.True && c != null)
                            .ToArray()));
        }