/// <summary> /// Generic implementation of the get methods for the particular /// <see cref="IFilter"/> provided. /// </summary> /// <param name="cache"> /// The <see cref="ICache"/> to be queried. /// </param> /// <param name="dictIndex"> /// The <see cref="IDictionary"/> of indexes. /// </param> /// <param name="filter"> /// The <see cref="IFilter"/> object representing the criteria that /// the entries of this cache should satisfy. /// </param> /// <param name="queryType"> /// An enum value that defines whether return array should be values, /// keys or entries. /// </param> /// <param name="sort"> /// If <b>true</b>, sort the result-set before returning. /// </param> /// <param name="comparer"> /// The <see cref="IComparer"/> to use for sorting (optional). /// </param> /// <returns> /// A collection of the keys/values for entries that satisfy the /// specified criteria. /// </returns> public static object[] Query(ICache cache, IDictionary dictIndex, IFilter filter, QueryType queryType, bool sort, IComparer comparer) { IFilter filterOrig = filter; if (AlwaysFilter.Instance.Equals(filter)) { filter = null; } object[] results; // may contain keys, values, or entries // try to apply an index (if available) if (dictIndex != null && filter is IIndexAwareFilter) { // take a thread-safe snapshot of the cache key set; this // differs a from the Java version in which the Set interface, // SubSet class, and thread-safe Collection.toArray() methods // are at our disposal ICollection keys; CollectionUtils.AcquireReadLock(cache); try { keys = new HashSet(cache.Keys); } finally { CollectionUtils.ReleaseReadLock(cache); } filter = ((IIndexAwareFilter)filter).ApplyIndex(dictIndex, keys); results = CollectionUtils.ToArray(keys); } else { // perform a thread-safe conversion of the cache key set into // an object array; again, this differs a bit from the Java // version CollectionUtils.AcquireReadLock(cache); try { results = CollectionUtils.ToArray(cache.Keys); } finally { CollectionUtils.ReleaseReadLock(cache); } } int resultCount = 0; if (filter == null && queryType == QueryType.Keys) { resultCount = results.Length; } else { // we still have a filter to evaluate or we need an entry set // or values collection for (int i = 0, c = results.Length; i < c; i++) { var key = results[i]; var value = cache[key]; if (value != null || cache.Contains(key)) { ICacheEntry entry = new CacheEntry(key, value); if (filter == null || EvaluateEntry(filter, entry)) { object result; switch (queryType) { case QueryType.Entries: result = entry; break; case QueryType.Keys: result = key; break; default: result = value; break; } results[resultCount++] = result; } } } } // convert the result array into an array of the appropriate // type and length; this differs from the Java version in which // this method returns a Set and not an array if (queryType == QueryType.Entries) { var entries = new ICacheEntry[resultCount]; Array.Copy(results, 0, entries, 0, resultCount); results = entries; } else if (resultCount < results.Length) { var newResults = new object[resultCount]; Array.Copy(results, 0, newResults, 0, resultCount); results = newResults; } // sort the results; this differs from the Java version in which // this method only can return keys or entries (and not values) if (sort) { if (comparer == null) { comparer = SafeComparer.Instance; } if (queryType == QueryType.Entries) { comparer = new EntryComparer(comparer); } Array.Sort(results, 0, resultCount, comparer); } // if the original filter is a LimitFilter then we can only return // a page at a time if (filterOrig is LimitFilter) { var filterLimit = filterOrig as LimitFilter; filterLimit.Comparer = null; results = filterLimit.ExtractPage(results); resultCount = results.Length; filterLimit.Comparer = comparer; // for debug output only } // convert the result array into an array of the appropriate // type and length; this differs from the Java version in which // this method returns a Set and not an array if (queryType == QueryType.Entries) { var entries = new ICacheEntry[resultCount]; Array.Copy(results, 0, entries, 0, resultCount); results = entries; } else if (resultCount < results.Length) { var newResults = new object[resultCount]; Array.Copy(results, 0, newResults, 0, resultCount); results = newResults; } return(results); }