/// <summary> /// Instantiate the inverse index. /// </summary> /// <param name="ordered"> /// <b>true</b> iff the contents of the indexed information should be /// ordered; false otherwise. /// </param> /// <param name="comparer"> /// The IComparator object which imposes an ordering on entries in the /// index; or <tt>null</tt> if the entries' values natural ordering /// should be used. /// </param> /// <returns>The inverse index.</returns> protected virtual IDictionary InstatiateInverseIndex(bool ordered, IComparer comparer) { if (ordered) { if (!(comparer is SafeComparer)) { comparer = new SafeComparer(comparer); } return(new SynchronizedDictionary(new SortedDictionary(comparer))); } return(new SynchronizedDictionary()); }
/// <summary> /// Incorporate one aggregatable value into the result. /// </summary> /// <remarks> /// If the <paramref name="isFinal"/> parameter is <b>true</b>, the /// given object is a partial result (returned by an individual /// parallel aggregator) that should be incorporated into the final /// result; otherwise, the object is a value extracted from an /// <see cref="IInvocableCacheEntry"/>. /// </remarks> /// <param name="o"> /// The value to incorporate into the aggregated result. /// </param> /// <param name="isFinal"> /// <b>true</b> to indicate that the given object is a partial /// result returned by a parallel aggregator. /// </param> protected override void Process(object o, bool isFinal) { if (o != null) { Object result = m_result; if (result == null || SafeComparer.CompareSafe(m_comparer, result, o) < 0) { m_result = o; } m_count++; } }
public void TestUnitComparisonValueExtractor() { IValueExtractor exByte = new ReflectionExtractor("ByteValue"); IValueExtractor exShort = new ReflectionExtractor("ShortValue"); IValueExtractor exInt = new ReflectionExtractor("IntValue"); IValueExtractor exLong = new ReflectionExtractor("LongValue"); IValueExtractor exFloat = new ReflectionExtractor("FloatValue"); IValueExtractor exDouble = new ReflectionExtractor("DoubleValue"); IValueExtractor exDecimal = new ReflectionExtractor("DecimalValue"); IValueExtractor exInt128 = new ReflectionExtractor("RawInt128Value"); IValueExtractor[] extractors = new IValueExtractor[] { exDouble, exInt }; //different ways to instantiate same extractor ComparisonValueExtractor cve1 = new ComparisonValueExtractor(extractors); ComparisonValueExtractor cve2 = new ComparisonValueExtractor(exDouble, exInt); ComparisonValueExtractor cve3 = new ComparisonValueExtractor(exDouble, exInt, null); ComparisonValueExtractor cve4 = new ComparisonValueExtractor("DoubleValue", "IntValue"); ComparisonValueExtractor cve5 = new ComparisonValueExtractor("DoubleValue", "IntValue", null); Assert.IsNotNull(cve1); Assert.IsNotNull(cve2); Assert.IsNotNull(cve3); Assert.IsNotNull(cve4); Assert.IsNotNull(cve5); Assert.IsTrue(cve1.Equals(cve2)); Assert.IsTrue(cve1.Equals(cve3)); Assert.IsTrue(cve1.Equals(cve4)); Assert.IsTrue(cve1.Equals(cve5)); Assert.IsNull(cve1.Comparer); Assert.AreEqual(cve1.Extractors.Length, 2); Score score = new Score(1, 1, 126, 10000L, 1.24f, 1432.55, new decimal(11223344), new RawInt128(new byte[] { 1 }), 1); Assert.AreEqual(cve1.Extract(score), score.DoubleValue - Convert.ToDouble(score.IntValue)); cve1 = new ComparisonValueExtractor(exByte, exShort); Assert.AreEqual(cve1.Extract(score), Convert.ToInt32(score.ByteValue) - Convert.ToInt32(score.ShortValue)); cve1 = new ComparisonValueExtractor(exLong, exInt); Assert.AreEqual(cve1.Extract(score), score.LongValue - Convert.ToInt64(score.IntValue)); cve1 = new ComparisonValueExtractor(exLong, exFloat); Assert.AreEqual(cve1.Extract(score), Convert.ToDouble(score.LongValue) - Convert.ToDouble(score.FloatValue)); cve1 = new ComparisonValueExtractor(exDecimal, exDouble); Assert.AreEqual(cve1.Extract(score), Decimal.Subtract(score.DecimalValue, Convert.ToDecimal(score.DoubleValue))); ComparisonValueExtractor cve6 = new ComparisonValueExtractor("ShortValue", "ShortValue", Comparer.Default); Assert.AreEqual(cve6.Extract(score), SafeComparer.CompareSafe(Comparer.Default, score.ShortValue, score.ShortValue)); }
/// <summary> /// Compare two entries based on the rules specified by /// <b>IComparer</b>. /// </summary> /// <remarks> /// <p> /// If possible, use the <see cref="IQueryCacheEntry.Extract"/> /// method to optimize the value extraction process.</p> /// <p> /// This method is expected to be implemented by <b>IComparer</b> /// wrappers, which simply pass on this invocation to the wrapped /// <b>IComparer</b> objects if they too implement this interface, or /// to invoke their default compare method passing the actual objects /// (not the extracted values) obtained from the extractor using the /// passed entries.</p> /// <p> /// This interface is also expected to be implemented by /// <see cref="IValueExtractor"/> implementations that implement the /// <b>IComparer</b> interface. It is expected that in most cases, /// the <b>IComparer</b> wrappers will eventually terminate at (i.e. /// delegate to) <b>IValueExtractors</b> that also implement this /// interface.</p> /// </remarks> /// <param name="entry1"> /// The first entry to compare values from; read-only. /// </param> /// <param name="entry2"> /// The second entry to compare values from; read-only. /// </param> /// <returns> /// A negative integer, zero, or a positive integer as the first /// entry denotes a value that is is less than, equal to, or greater /// than the value denoted by the second entry. /// </returns> /// <exception cref="InvalidCastException"> /// If the arguments' types prevent them from being compared by this /// <b>IComparer</b>. /// </exception> /// <exception cref="ArgumentException"> /// If the extractor cannot handle the passed objects for any other /// reason; an implementor should include a descriptive message. /// </exception> /// <since>Coherence 3.2</since> public override int CompareEntries(IQueryCacheEntry entry1, IQueryCacheEntry entry2) { IValueExtractor[] extractors = Extractors; for (int i = 0, c = extractors.Length; i < c; i++) { IValueExtractor extractor = extractors[i]; int result = SafeComparer.CompareSafe(null, entry1.Extract(extractor), entry2.Extract(extractor)); if (result != 0) { return(result); } } return(0); }
public void TestNamedCacheIndex() { INamedCache cache = CacheFactory.GetCache(CacheName); IValueExtractor extractor = IdentityExtractor.Instance; cache.Clear(); cache.AddIndex(extractor, false, null); cache.RemoveIndex(extractor); IComparer comparer = new SafeComparer(); extractor = new KeyExtractor(IdentityExtractor.Instance); cache.AddIndex(extractor, true, comparer); cache.RemoveIndex(extractor); CacheFactory.ReleaseCache(cache); CacheFactory.Shutdown(); }
/// <summary> /// Extract the value from the passed object. /// </summary> /// <remarks> /// The returned value may be <c>null</c>. /// </remarks> /// <param name="obj"> /// An object to retrieve the value from. /// </param> /// <returns> /// The extracted value as an object; <c>null</c> is an acceptable /// value. /// </returns> /// <exception cref="InvalidCastException"> /// If this IValueExtractor is incompatible with the passed object to /// extract a value from and the implementation <b>requires</b> the /// passed object to be of a certain type. /// </exception> /// <exception cref="ArgumentException"> /// If this AbstractExtractor cannot handle the passed object for any /// other reason; an implementor should include a descriptive /// message. /// </exception> public override object Extract(object obj) { IValueExtractor[] extractors = Extractors; IComparer comparer = Comparer; object o1 = extractors[0].Extract(obj); object o2 = extractors[1].Extract(obj); if (NumberUtils.IsNumber(o1) && NumberUtils.IsNumber(o2) && comparer == null) { StreamFormat type; if (o1.GetType() == o2.GetType()) { // most common case; same types type = GetStreamFormat(o1); } else { StreamFormat[] types = new StreamFormat[] { StreamFormat.Byte, // 0 StreamFormat.Short, // 1 StreamFormat.Int, // 2 StreamFormat.Long, // 3 StreamFormat.Float, // 4 StreamFormat.Double, // 5 StreamFormat.RawInt128, // 6 StreamFormat.Decimal // 7 }; StreamFormat type1 = GetStreamFormat(o1); StreamFormat type2 = GetStreamFormat(o2); int typesCount, ix1, ix2; ix1 = ix2 = typesCount = types.Length; for (int i = 0; i < typesCount; i++) { StreamFormat t = types[i]; if (t == type1) { ix1 = i; } if (t == type2) { ix2 = i; } } switch (Math.Max(ix1, ix2)) { case 0: case 1: case 2: type = StreamFormat.Int; break; case 3: type = StreamFormat.Long; break; case 4: case 5: type = StreamFormat.Double; break; case 6: case 7: type = StreamFormat.Decimal; o1 = EnsureDecimal(o1); o2 = EnsureDecimal(o2); break; default: type = StreamFormat.None; break; } } switch (type) { case StreamFormat.Byte: case StreamFormat.Short: case StreamFormat.Int: return(Convert.ToInt32(o1) - Convert.ToInt32(o2)); case StreamFormat.Long: return(Convert.ToInt64(o1) - Convert.ToInt64(o2)); case StreamFormat.Float: return(Convert.ToSingle(o1) - Convert.ToSingle(o2)); case StreamFormat.Double: return(Convert.ToDouble(o1) - Convert.ToDouble(o2)); case StreamFormat.RawInt128: return(NumberUtils.DecimalToRawInt128(Decimal.Subtract(((RawInt128)o1).ToDecimal(), ((RawInt128)o2).ToDecimal()))); case StreamFormat.Decimal: return(Decimal.Subtract(Convert.ToDecimal(o1), Convert.ToDecimal(o2))); } } return(SafeComparer.CompareSafe(comparer, o1, o2)); }
/// <summary> /// Compare two entries. /// </summary> /// <param name="entry1"> /// The first entry to compare values from; read-only. /// </param> /// <param name="entry2"> /// The second entry to compare values from; read-only. /// </param> /// <returns> /// A negative integer, zero, or a positive integer as the first /// entry denotes a value that is is less than, equal to, or greater /// than the value denoted by the second entry /// </returns> /// <exception cref="InvalidCastException"> /// If the arguments' types prevent them from being compared by this /// <b>IComparer</b>. /// </exception> /// <exception cref="ArgumentException"> /// If the extractor cannot handle the passed objects for any other /// reason; an implementor should include a descriptive message. /// </exception> public virtual int CompareEntries(IQueryCacheEntry entry1, IQueryCacheEntry entry2) { return(SafeComparer.CompareSafe(null, entry1.Extract(this), entry2.Extract(this))); }
/// <summary> /// Compares its two arguments for order. /// </summary> /// <remarks> /// Returns a negative integer, zero, or a positive integer as the /// first argument is less than, equal to, or greater than the /// second. <c>null</c> values are evaluated as "less then" any /// non-null value. /// </remarks> /// <param name="o1"> /// The first object to be compared. /// </param> /// <param name="o2"> /// The second object to be compared. /// </param> /// <returns> /// A negative integer, zero, or a positive integer as the first /// argument is less than, equal to, or greater than the second. /// </returns> public virtual int Compare(object o1, object o2) { return(SafeComparer.CompareSafe(null, Extract(o1), Extract(o2))); }