public void TestCompositeAggregator() { IEntryAggregator agg1 = CompositeAggregator.CreateInstance( new IEntryAggregator[] { GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count()), new LongMax((IdentityExtractor.Instance)) }); ArrayList al = new ArrayList(); al.Add(new TestInvocableCacheEntry("key1", 173)); al.Add(new TestInvocableCacheEntry("key2", 173)); al.Add(new TestInvocableCacheEntry("key3", 185)); al.Add(new TestInvocableCacheEntry("key4", 164)); al.Add(new TestInvocableCacheEntry("key5", 164)); al.Add(new TestInvocableCacheEntry("key6", 164)); object result = agg1.Aggregate(al); if (result is IList) { IDictionary results = (IDictionary)((IList)result)[0]; Assert.AreEqual(results[185], 1); Assert.AreEqual(results[164], 3); Assert.AreEqual(((IList)result)[1], 185); } // aggragation on remote cache INamedCache cache = CacheFactory.GetCache(CacheName); cache.Clear(); HashDictionary hd = new HashDictionary(); hd.Add("Key1", 435); hd.Add("Key2", 253); hd.Add("Key3", 435); hd.Add("Key4", 435); hd.Add(null, -3); cache.InsertAll(hd); IEntryAggregator aggregator = CompositeAggregator.CreateInstance( new IEntryAggregator[] { GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count()), new LongMax((IdentityExtractor.Instance)) }); result = cache.Aggregate(cache.Keys, aggregator); if (result is IList) { IDictionary results = (IDictionary)((IList)result)[0]; Assert.AreEqual(results[435], 3); Assert.AreEqual(results[-3], 1); Assert.AreEqual(((IList)result)[1], 435); } CacheFactory.Shutdown(); }
/// <summary> /// Construct a GroupAggregator based on a specified /// <see cref="IValueExtractor"/> and underlying /// <see cref="IEntryAggregator"/>. /// </summary> /// <param name="extractor"> /// An <b>IValueExtractor</b> object that is used to split /// <see cref="IInvocableCache"/> entries into /// non-intersecting subsets; may not be <c>null</c>. /// </param> /// <param name="aggregator"> /// An <b>IEntryAggregator</b> object; may not be <c>null</c>. /// </param> /// <param name="filter"> /// An optional <see cref="IFilter"/> object used to filter out /// results of individual group aggregation results. /// </param> protected GroupAggregator(IValueExtractor extractor, IEntryAggregator aggregator, IFilter filter) { Debug.Assert(extractor != null && aggregator != null); m_extractor = extractor; m_aggregator = aggregator; m_filter = filter; }
/// <summary> /// Create an instance of GroupAggregator based on a specified member /// name(s), an <see cref="IEntryAggregator"/> and a result /// evaluation filter. /// </summary> /// <remarks> /// If the specified underlying aggregator is an instance of /// <see cref="IParallelAwareAggregator"/>, then a parallel-aware /// instance of the GroupAggregator will be created. Otherwise, the /// resulting GroupAggregator will not be parallel-aware and could be /// ill-suited for aggregations run against large partitioned caches. /// </remarks> /// <param name="member"> /// A member name or a comma-delimited sequence of names that results /// in a <see cref="ReflectionExtractor"/> or a /// <see cref="MultiExtractor"/> that will be used to split /// <see cref="IInvocableCache"/> entries into distinct groups. /// </param> /// <param name="aggregator"> /// An underlying <b>IEntryAggregator</b>. /// </param> /// <param name="filter"> /// An optional <b>IFilter</b> object that will be used to evaluate /// results of each individual group aggregation. /// </param> /// <returns> /// An instance of GroupAggregator based on a specified member /// name(s), an <see cref="IEntryAggregator"/> and a result /// evaluation filter. /// </returns> public static GroupAggregator CreateInstance(string member, IEntryAggregator aggregator, IFilter filter) { IValueExtractor extractor = member.IndexOf(',') >= 0 ? new MultiExtractor(member) : member.IndexOf('.') >= 0 ? new ChainedExtractor(member) : (IValueExtractor) new ReflectionExtractor(member); return(CreateInstance(extractor, aggregator, filter)); }
/// <summary> /// Process a collection of <see cref="IInvocableCacheEntry"/> /// objects using the underlying extractor to split the entries /// into non-intersecting (distinct) groups and then apply the /// underlying aggregator separately to each group. /// </summary> /// <param name="entries"> /// A collection of read-only <b>IInvocableCacheEntry</b> /// objects to aggregate. /// </param> /// <returns> /// A dictionary that has the unique tuples as keys and results of /// the corresponding subset aggregation as values. /// </returns> public virtual object Aggregate(ICollection entries) { IValueExtractor extractor = m_extractor; IEntryAggregator aggregator = m_aggregator; IFilter filter = m_filter; // create non-intersecting groups of entry sets IDictionary result = new HashDictionary(); foreach (IInvocableCacheEntry entry in entries) { if (entry.IsPresent) { // extract a distinct value (or a tuple) object distinct = entry.Extract(extractor); // add the entry to the corresponding group ICollection group = (ICollection)result[distinct]; if (group == null) { result.Add(distinct, group = new ArrayList()); } CollectionUtils.Add(group, entry); } } // run the aggregation IDictionary newResult = new HashDictionary(result); foreach (DictionaryEntry entry in result) { ICollection group = (ICollection)entry.Value; object res = aggregator.Aggregate(group); if (filter == null || filter.Evaluate(res)) { newResult[entry.Key] = res; } else { newResult.Remove(entry.Key); } } return(newResult); }
/// <summary> /// Perform an aggregating operation against the collection of /// entries that are selected by the given <b>IFilter</b>. /// </summary> /// <param name="filter"> /// an <see cref="IFilter"/> that is used to select entries within /// this cache to aggregate across. /// </param> /// <param name="agent"> /// The <see cref="IEntryAggregator"/> that is used to aggregate /// across the selected entries of this cache. /// </param> /// <returns> /// The result of the aggregation. /// </returns> public virtual object Aggregate(IFilter filter, IEntryAggregator agent) { return(NamedCache.Aggregate(filter, agent)); }
/// <summary> /// Perform an aggregating operation against the entries specified by /// the passed keys. /// </summary> /// <param name="keys"> /// The collection of keys that specify the entries within this cache /// to aggregate across. /// </param> /// <param name="agent"> /// The <see cref="IEntryAggregator"/> that is used to aggregate /// across the specified entries of this cache. /// </param> /// <returns> /// The result of the aggregation. /// </returns> public virtual object Aggregate(ICollection keys, IEntryAggregator agent) { return(NamedCache.Aggregate(keys, agent)); }
public void TestGroupAggregator() { GroupAggregator agg1 = GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count()); Assert.IsNotNull(agg1); Assert.AreSame(IdentityExtractor.Instance, agg1.Extractor); Assert.IsInstanceOf(typeof(Count), agg1.Aggregator); GroupAggregator agg2 = GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count(), new LessFilter( IdentityExtractor.Instance, 3)); Assert.IsNotNull(agg2); Assert.IsInstanceOf(typeof(IdentityExtractor), agg2.Extractor); GroupAggregator agg3 = GroupAggregator.CreateInstance("dummy", new Count()); Assert.IsNotNull(agg3); Assert.IsInstanceOf(typeof(ReflectionExtractor), agg3.Extractor); agg3 = GroupAggregator.CreateInstance("dummy.test", new Count()); Assert.IsNotNull(agg3); Assert.IsInstanceOf(typeof(ChainedExtractor), agg3.Extractor); agg3 = GroupAggregator.CreateInstance("dummy.test1, dummy.test2", new Count()); Assert.IsNotNull(agg3); Assert.IsInstanceOf(typeof(MultiExtractor), agg3.Extractor); ArrayList al = new ArrayList(); al.Add(new TestInvocableCacheEntry("key1", 173)); al.Add(new TestInvocableCacheEntry("key2", 173)); al.Add(new TestInvocableCacheEntry("key3", 185)); al.Add(new TestInvocableCacheEntry("key4", 164)); al.Add(new TestInvocableCacheEntry("key5", 164)); al.Add(new TestInvocableCacheEntry("key6", 164)); object result = agg2.Aggregate(al); if (result is IDictionary) { Assert.AreEqual(((IDictionary)result)[173], 2); Assert.AreEqual(((IDictionary)result)[185], 1); Assert.AreEqual(((IDictionary)result)[164], null); } // aggragation on remote cache INamedCache cache = CacheFactory.GetCache(CacheName); cache.Clear(); Hashtable ht = new Hashtable(); ht.Add("Key1", 435); ht.Add("Key2", 253); ht.Add("Key3", 435); ht.Add("Key4", 435); ht.Add("Key5", -3); cache.InsertAll(ht); IEntryAggregator aggregator = GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count()); result = cache.Aggregate(cache.Keys, aggregator); if (result is IDictionary) { Assert.AreEqual(((IDictionary)result)[435], 3); Assert.AreEqual(((IDictionary)result)[-3], 1); } CacheFactory.Shutdown(); }
/// <summary> /// Create an instance of GroupAggregator based on a specified /// extractor and an <b>IEntryAggregator</b> and a result /// evaluation filter. /// </summary> /// <remarks> /// If the specified aggregator is an instance of /// <b>IParallelAwareAggregator</b>, then a parallel-aware instance /// of the GroupAggregator will be created. Otherwise, the resulting /// GroupAggregator will not be parallel-aware and could be /// ill-suited for aggregations run against large partitioned caches. /// </remarks> /// <param name="extractor"> /// An <b>IValueExtractor</b> that will be used to split a set of /// <b>IInvocableDictionary</b> entries into distinct groups. /// </param> /// <param name="aggregator"> /// An underlying <b>IEntryAggregator</b>. /// </param> /// <param name="filter"> /// An optional <b>IFilter</b> object used to filter out results of /// individual group aggregation results. /// </param> /// <returns> /// An instance of GroupAggregator based on a specified /// extractor and an <b>IEntryAggregator</b> and a result /// evaluation filter. /// </returns> public static GroupAggregator CreateInstance(IValueExtractor extractor, IEntryAggregator aggregator, IFilter filter) { return(new GroupAggregator(extractor, aggregator, filter)); }
/// <summary> /// Create an instance of GroupAggregator based on a specified /// extractor and an <b>IEntryAggregator</b>. /// </summary> /// <remarks> /// If the specified aggregator is an instance of /// <b>IParallelAwareAggregator</b>, then a parallel-aware instance /// of the GroupAggregator will be created. Otherwise, the resulting /// GroupAggregator will not be parallel-aware and could be /// ill-suited for aggregations run against large partitioned caches. /// </remarks> /// <param name="extractor"> /// An <b>IValueExtractor</b> that will be used to split a set of /// <b>IInvocableDictionary</b> entries into distinct groups. /// </param> /// <param name="aggregator"> /// An underlying <b>IEntryAggregator</b>. /// </param> /// <returns> /// An instance of GroupAggregator based on a specified /// extractor and an <b>IEntryAggregator</b>. /// </returns> public static GroupAggregator CreateInstance(IValueExtractor extractor, IEntryAggregator aggregator) { return(CreateInstance(extractor, aggregator, null)); }
/// <summary> /// Create an instance of GroupAggregator based on a specified member /// name(s) and an <see cref="IEntryAggregator"/>. /// </summary> /// <remarks> /// If the specified underlying aggregator is an instance of /// <see cref="IParallelAwareAggregator"/>, then a parallel-aware /// instance of the GroupAggregator will be created. Otherwise, the /// resulting GroupAggregator will not be parallel-aware and could be /// ill-suited for aggregations run against large partitioned caches. /// </remarks> /// <param name="member"> /// A member name or a comma-delimited sequence of names that results /// in a <see cref="ReflectionExtractor"/> or a /// <see cref="MultiExtractor"/> that will be used to split /// <see cref="IInvocableCache"/> entries into distinct groups. /// </param> /// <param name="aggregator"> /// An underlying <b>IEntryAggregator</b>. /// </param> /// <returns> /// An instance of GroupAggregator based on a specified member /// name(s) and an <see cref="IEntryAggregator"/>. /// </returns> public static GroupAggregator CreateInstance(string member, IEntryAggregator aggregator) { return(CreateInstance(member, aggregator, null)); }