/// <summary>
        /// Is there an access rule for the specified type(s) that includes the requested permission? E.g. create.
        /// </summary>
        /// <param name="entityTypes">The <see cref="EntityType"/>s to check. This cannot be null or contain null.</param>
        /// <param name="permission">The permission being sought.</param>
        /// <param name="user"> The user requesting access. This cannot be null. </param>
        /// <returns>
        /// A mapping the entity type ID to whether the user can create instances of that
        /// type (true) or not (false).
        /// </returns>
        public IDictionary <long, bool> CheckTypeAccess(IList <EntityType> entityTypes, EntityRef permission, EntityRef user)
        {
            if (entityTypes == null)
            {
                throw new ArgumentNullException(nameof(entityTypes));
            }
            if (permission == null)
            {
                throw new ArgumentNullException(nameof(permission));
            }
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            IDictionary <long, bool> result;
            Stopwatch stopwatch;

            stopwatch = new Stopwatch();
            try
            {
                stopwatch.Start();

                result = Checker.CheckTypeAccess(entityTypes, permission, user);

                if (!EntityAccessControlChecker.SkipCheck(user))
                {
                    // Update counters for permission and the total
                    AccessControlPermissionCounters.GetPerformanceCounter <RatePerSecond32PerformanceCounter>(
                        AccessControlPermissionPerformanceCounters.RateCounterName,
                        permission.Alias).Increment();
                    AccessControlPermissionCounters.GetPerformanceCounter <NumberOfItems64PerformanceCounter>(
                        AccessControlPermissionPerformanceCounters.CountCounterName,
                        permission.Alias).Increment();

                    // Update single instance counters
                    AccessControlCounters.GetPerformanceCounter <RatePerSecond32PerformanceCounter>(
                        AccessControlPerformanceCounters.CheckRateCounterName).Increment();
                    AccessControlCounters.GetPerformanceCounter <NumberOfItems64PerformanceCounter>(
                        AccessControlPerformanceCounters.CheckCountCounterName).Increment();
                }
            }
            finally
            {
                // Update the average timer counter access control checks
                stopwatch.Stop();

                if (!EntityAccessControlChecker.SkipCheck(user))
                {
                    AccessControlCounters.GetPerformanceCounter <AverageTimer32PerformanceCounter>(
                        AccessControlPerformanceCounters.CheckDurationCounterName).AddTiming(stopwatch);
                }
            }

            return(result);
        }
        /// <summary>
        /// Check whether the user has all the specified
        /// <paramref name="permissions">access</paramref> to the specified <paramref name="entities"/>.
        /// </summary>
        /// <param name="entities">
        ///     The entities to check. This cannot be null or contain null.
        /// </param>
        /// <param name="permissions">
        ///     The permissions or operations to check. This cannot be null or contain null.
        /// </param>
        /// <param name="user">
        ///     The user requesting access. This cannot be null.
        /// </param>
        /// <returns>
        /// A mapping of each entity ID to whether the user has access (true) or not (false).
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// No argument can be null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Neither <paramref name="entities"/> nor <paramref name="permissions"/> can contain null.
        /// </exception>
        public IDictionary <long, bool> CheckAccess(IList <EntityRef> entities, IList <EntityRef> permissions, EntityRef user)
        {
            if (entities == null)
            {
                throw new ArgumentNullException("entities");
            }
            if (permissions == null)
            {
                throw new ArgumentNullException("permissions");
            }
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            IDictionary <long, bool> result;

            var stopwatch = new Stopwatch();

            try
            {
                stopwatch.Start();

                result = Checker.CheckAccess(entities, permissions, user);

                if (!EntityAccessControlChecker.SkipCheck(user))
                {
                    // Update counters for each permission and the total
                    foreach (IEntityRef entityRef in permissions)
                    {
                        AccessControlPermissionCounters.GetPerformanceCounter <RatePerSecond32PerformanceCounter>(
                            AccessControlPermissionPerformanceCounters.RateCounterName,
                            entityRef.Alias ?? entityRef.Id.ToString(CultureInfo.InvariantCulture)).Increment();
                        AccessControlPermissionCounters.GetPerformanceCounter <NumberOfItems64PerformanceCounter>(
                            AccessControlPermissionPerformanceCounters.CountCounterName,
                            entityRef.Alias ?? entityRef.Id.ToString(CultureInfo.InvariantCulture)).Increment();
                    }

                    // Update single instance counters
                    AccessControlCounters.GetPerformanceCounter <RatePerSecond32PerformanceCounter>(
                        AccessControlPerformanceCounters.CheckRateCounterName).Increment();
                    AccessControlCounters.GetPerformanceCounter <NumberOfItems64PerformanceCounter>(
                        AccessControlPerformanceCounters.CheckCountCounterName).Increment();

                    // Update cache results
                    var cachingResult = result as ICachingEntityAccessControlCheckerResult;
                    if (cachingResult != null)
                    {
                        AccessControlCounters.GetPerformanceCounter <PercentageRatePerformanceCounter>(
                            AccessControlPerformanceCounters.CacheHitPercentageCounterName)
                        .AddHits(cachingResult.CacheResult.Keys.Count());
                        AccessControlCounters.GetPerformanceCounter <PercentageRatePerformanceCounter>(
                            AccessControlPerformanceCounters.CacheHitPercentageCounterName)
                        .AddMisses(result.Keys.Count() - cachingResult.CacheResult.Keys.Count());
                    }
                }
            }
            finally
            {
                // Update the average timer counter access control checks
                stopwatch.Stop();

                if (!EntityAccessControlChecker.SkipCheck(user))
                {
                    AccessControlCounters.GetPerformanceCounter <AverageTimer32PerformanceCounter>(
                        AccessControlPerformanceCounters.CheckDurationCounterName).AddTiming(stopwatch);
                }
            }

            return(result);
        }