| /*========================================================================= |
| * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| |
| |
| |
| #pragma once |
| |
| #include "../../gf_defs.hpp" |
| #include <cppcache/CacheableBuiltins.hpp> |
| #include "SerializableMN.hpp" |
| #include "ExceptionTypesMN.hpp" |
| #include "impl/PdxInstanceImpl.hpp" |
| |
| using namespace System; |
| using namespace System::Collections::Generic; |
| #pragma managed |
| |
| namespace GemStone |
| { |
| namespace GemFire |
| { |
| namespace Cache { namespace Generic |
| { |
| namespace Internal |
| { |
| /// <summary> |
| /// A mutable <c>ICacheableKey</c> hash set wrapper that can serve as |
| /// a distributable object for caching. |
| /// </summary> |
| template <uint32_t TYPEID, typename HSTYPE> |
| public ref class CacheableHashSetType |
| : public Serializable, public ICollection<Object^> |
| { |
| public: |
| |
| virtual void ToData(DataOutput^ output) override |
| { |
| output->WriteArrayLen(this->Count); |
| |
| Internal::ManagedPtrWrap< gemfire::Serializable, |
| Internal::SBWrap<gemfire::Serializable> > nptr = NativePtr; |
| HSTYPE* set = static_cast<HSTYPE*>(nptr()); |
| for (typename HSTYPE::Iterator iter = set->begin(); |
| iter != set->end(); ++iter) { |
| //Generic::ICacheableKey^ key = SafeGenericUMKeyConvert<ICacheableKey^>((*iter).ptr()); |
| Object^ key = Serializable::GetManagedValueGeneric<Object^>((*iter)); |
| output->WriteObject(key); |
| } |
| } |
| |
| virtual IGFSerializable^ FromData(DataInput^ input) override |
| { |
| int len = input->ReadArrayLen(); |
| if (len > 0) |
| { |
| for ( int i = 0; i < len; i++) |
| { |
| //Generic::ICacheableKey^ key = dynamic_cast<Generic::ICacheableKey^>(input->ReadObject()); |
| Object^ key = (input->ReadObject()); |
| this->Add(key); |
| } |
| } |
| return this; |
| } |
| |
| virtual property uint32_t ObjectSize |
| { |
| virtual uint32_t get() override |
| { |
| uint32_t size = 0; |
| for each (Object^ key in this) { |
| if ( key != nullptr) |
| //size += key->ObjectSize; |
| //TODO:: how should we do this now |
| size += 1; |
| } |
| return size; |
| } |
| } |
| |
| virtual int GetHashCode() override |
| { |
| IEnumerator<Object^>^ ie = GetEnumerator(); |
| |
| int h = 0; |
| while(ie->MoveNext() == true) |
| { |
| h = h + PdxInstanceImpl::deepArrayHashCode(ie->Current); |
| } |
| return h; |
| } |
| |
| virtual bool Equals(Object^ other)override |
| { |
| if(other == nullptr) |
| return false; |
| |
| CacheableHashSetType^ otherCHST = dynamic_cast<CacheableHashSetType^>(other); |
| |
| if(otherCHST == nullptr) |
| return false; |
| |
| if(Count != otherCHST->Count) |
| return false; |
| |
| IEnumerator<Object^>^ ie = GetEnumerator(); |
| |
| while(ie->MoveNext() == true) |
| { |
| if(otherCHST->Contains(ie->Current)) |
| return true; |
| else |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /// <summary> |
| /// Enumerator for <c>CacheableHashSet</c> class. |
| /// </summary> |
| ref class Enumerator sealed |
| : public Internal::UMWrap<typename HSTYPE::Iterator>, |
| public IEnumerator<Object^> |
| { |
| public: |
| // Region: IEnumerator<ICacheableKey^> Members |
| |
| /// <summary> |
| /// Gets the element in the collection at the current |
| /// position of the enumerator. |
| /// </summary> |
| /// <returns> |
| /// The element in the collection at the current position |
| /// of the enumerator. |
| /// </returns> |
| property Object^ Current |
| { |
| virtual Object^ get() = |
| IEnumerator<Object^>::Current::get |
| { |
| if (!m_started) { |
| throw gcnew System::InvalidOperationException( |
| "Call MoveNext first."); |
| } |
| //return SafeGenericUMKeyConvert<Generic::ICacheableKey^>((*(*NativePtr())).ptr()); |
| return Serializable::GetManagedValueGeneric<Object^>((*(*NativePtr()))); |
| } |
| } |
| |
| // End Region: IEnumerator<ICacheableKey^> Members |
| |
| // Region: IEnumerator Members |
| |
| /// <summary> |
| /// Advances the enumerator to the next element of the collection. |
| /// </summary> |
| /// <returns> |
| /// true if the enumerator was successfully advanced to the next |
| /// element; false if the enumerator has passed the end of |
| /// the collection. |
| /// </returns> |
| virtual bool MoveNext() |
| { |
| Internal::ManagedPtrWrap< typename HSTYPE::Iterator, |
| Internal::UMWrap<typename HSTYPE::Iterator> > nptr = NativePtr; |
| bool isEnd = nptr->isEnd(); |
| if (!m_started) { |
| m_started = true; |
| } |
| else { |
| if (!isEnd) { |
| (*nptr())++; |
| isEnd = nptr->isEnd(); |
| } |
| } |
| GC::KeepAlive(this); |
| return !isEnd; |
| } |
| |
| /// <summary> |
| /// Sets the enumerator to its initial position, which is before |
| /// the first element in the collection. |
| /// </summary> |
| virtual void Reset() |
| { |
| NativePtr->reset(); |
| m_started = false; |
| } |
| |
| // End Region: IEnumerator Members |
| |
| internal: |
| /// <summary> |
| /// Internal constructor to wrap a native object pointer |
| /// </summary> |
| /// <param name="nativeptr">The native object pointer</param> |
| inline Enumerator(typename HSTYPE::Iterator* nativeptr, |
| CacheableHashSetType<TYPEID, HSTYPE>^ set) |
| : UMWrap(nativeptr, true), m_set(set) { } |
| |
| private: |
| // Region: IEnumerator Members |
| |
| /// <summary> |
| /// Gets the current element in the collection. |
| /// </summary> |
| /// <returns> |
| /// The current element in the collection. |
| /// </returns> |
| /// <exception cref="System.InvalidOperationException"> |
| /// The enumerator is positioned before the first element of |
| /// the collection or after the last element. |
| /// </exception> |
| property Object^ ICurrent |
| { |
| virtual Object^ get() sealed = |
| System::Collections::IEnumerator::Current::get |
| { |
| return Current; |
| } |
| } |
| |
| // End Region: IEnumerator Members |
| |
| bool m_started; |
| |
| CacheableHashSetType<TYPEID, HSTYPE>^ m_set; |
| }; |
| |
| /// <summary> |
| /// Returns the classId of the instance being serialized. |
| /// This is used by deserialization to determine what instance |
| /// type to create and deserialize into. |
| /// </summary> |
| /// <returns>the classId</returns> |
| virtual property uint32_t ClassId |
| { |
| virtual uint32_t get() override |
| { |
| //return static_cast<HSTYPE*>(NativePtr())->classId() + 0x80000000; |
| return TYPEID; |
| } |
| } |
| |
| /// <summary> |
| /// Get the largest possible size of the <c>CacheableHashSet</c>. |
| /// </summary> |
| property int32_t MaxSize |
| { |
| inline int32_t get() |
| { |
| return static_cast<HSTYPE*>(NativePtr())->max_size(); |
| } |
| } |
| |
| /// <summary> |
| /// True if the <c>CacheableHashSet</c>'s size is 0. |
| /// </summary> |
| property bool IsEmpty |
| { |
| inline bool get() |
| { |
| return static_cast<HSTYPE*>(NativePtr())->empty(); |
| } |
| } |
| |
| /// <summary> |
| /// Get the number of buckets used by the HashSet. |
| /// </summary> |
| property int32_t BucketCount |
| { |
| inline int32_t get() |
| { |
| return static_cast<HSTYPE*>(NativePtr())->bucket_count(); |
| } |
| } |
| |
| /// <summary> |
| /// Increases the bucket count to at least <c>size</c> elements. |
| /// </summary> |
| /// <param name="size">The new size of the HashSet.</param> |
| virtual void Resize(int32_t size) sealed |
| { |
| static_cast<HSTYPE*>(NativePtr())->resize(size); |
| } |
| |
| /// <summary> |
| /// Swap the contents of this <c>CacheableHashSet</c> |
| /// with the given one. |
| /// </summary> |
| /// <param name="other"> |
| /// The other CacheableHashSet to use for swapping. |
| /// </param> |
| virtual void Swap(CacheableHashSetType<TYPEID, HSTYPE>^ other) sealed |
| { |
| if (other != nullptr) { |
| static_cast<HSTYPE*>(NativePtr())->swap( |
| *static_cast<HSTYPE*>(other->NativePtr())); |
| } |
| } |
| |
| // Region: ICollection<ICacheableKey^> Members |
| |
| /// <summary> |
| /// Adds an item to the <c>CacheableHashSet</c>. |
| /// </summary> |
| /// <param name="item"> |
| /// The object to add to the collection. |
| /// </param> |
| virtual void Add(Object^ item) |
| { |
| _GF_MG_EXCEPTION_TRY2/* due to auto replace */ |
| |
| gemfire::CacheableKeyPtr nativeptr(Serializable::GetUnmanagedValueGeneric(item)); |
| static_cast<HSTYPE*>(NativePtr())->insert(nativeptr); |
| |
| _GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */ |
| } |
| |
| /// <summary> |
| /// Removes all items from the <c>CacheableHashSet</c>. |
| /// </summary> |
| virtual void Clear() |
| { |
| static_cast<HSTYPE*>(NativePtr())->clear(); |
| } |
| |
| /// <summary> |
| /// Determines whether the <c>CacheableHashSet</c> contains |
| /// a specific value. |
| /// </summary> |
| /// <param name="item"> |
| /// The object to locate in the <c>CacheableHashSet</c>. |
| /// </param> |
| /// <returns> |
| /// true if item is found in the <c>CacheableHashSet</c>; |
| /// otherwise false. |
| /// </returns> |
| virtual bool Contains(Object^ item) |
| { |
| return static_cast<HSTYPE*>(NativePtr())->contains( |
| gemfire::CacheableKeyPtr(Serializable::GetUnmanagedValueGeneric(item))); |
| } |
| |
| /// <summary> |
| /// Copies the elements of the <c>CacheableHashSet</c> to an |
| /// <c>System.Array</c>, starting at a particular |
| /// <c>System.Array</c> index. |
| /// </summary> |
| /// <param name="array"> |
| /// The one-dimensional System.Array that is the destination of the |
| /// elements copied from <c>CacheableHashSet</c>. The |
| /// <c>System.Array</c> must have zero-based indexing. |
| /// </param> |
| /// <param name="arrayIndex"> |
| /// The zero-based index in array at which copying begins. |
| /// </param> |
| /// <exception cref="IllegalArgumentException"> |
| /// arrayIndex is less than 0 or array is null. |
| /// </exception> |
| /// <exception cref="OutOfRangeException"> |
| /// arrayIndex is equal to or greater than the length of array. |
| /// -or-The number of elements in the source <c>CacheableHashSet</c> |
| /// is greater than the available space from arrayIndex to the end |
| /// of the destination array. |
| /// </exception> |
| virtual void CopyTo(array<Object^>^ array, int32_t arrayIndex) |
| { |
| if (array == nullptr || arrayIndex < 0) { |
| throw gcnew IllegalArgumentException("CacheableHashSet.CopyTo():" |
| " array is null or array index is less than zero"); |
| } |
| Internal::ManagedPtrWrap< gemfire::Serializable, |
| Internal::SBWrap<gemfire::Serializable> > nptr = NativePtr; |
| HSTYPE* set = static_cast<HSTYPE*>(nptr()); |
| int32_t index = arrayIndex; |
| |
| if (arrayIndex >= array->Length || |
| array->Length < (arrayIndex + (int32_t)set->size())) { |
| throw gcnew OutOfRangeException("CacheableHashSet.CopyTo():" |
| " array index is beyond the HashSet or length of given " |
| "array is less than that required to copy all the " |
| "elements from HashSet"); |
| } |
| for (typename HSTYPE::Iterator iter = set->begin(); |
| iter != set->end(); ++iter, ++index) { |
| array[index] = Serializable::GetManagedValueGeneric<Object^>((*iter)); |
| } |
| GC::KeepAlive(this); |
| } |
| |
| /// <summary> |
| /// Gets the number of elements contained in the |
| /// <c>CacheableHashSet</c>. |
| /// </summary> |
| virtual property int32_t Count |
| { |
| virtual int32_t get() |
| { |
| return static_cast<HSTYPE*>(NativePtr())->size(); |
| } |
| } |
| |
| /// <summary> |
| /// Removes the first occurrence of a specific object from the |
| /// <c>CacheableHashSet</c>. |
| /// </summary> |
| /// <param name="item"> |
| /// The object to remove from the <c>CacheableHashSet</c>. |
| /// </param> |
| /// <returns> |
| /// true if item was successfully removed from the |
| /// <c>CacheableHashSet</c>; otherwise, false. This method also |
| /// returns false if item is not found in the original |
| /// <c>CacheableHashSet</c>. |
| /// </returns> |
| virtual bool Remove(Object^ item) |
| { |
| return (static_cast<HSTYPE*>(NativePtr())->erase( |
| gemfire::CacheableKeyPtr(Serializable::GetUnmanagedValueGeneric(item))) > 0); |
| } |
| |
| /// <summary> |
| /// Gets a value indicating whether the collection is read-only. |
| /// </summary> |
| /// <returns> |
| /// always false for <c>CacheableHashSet</c> |
| /// </returns> |
| virtual property bool IsReadOnly |
| { |
| virtual bool get() |
| { |
| return false; |
| } |
| } |
| |
| // End Region: ICollection<ICacheableKey^> Members |
| |
| // Region: IEnumerable<ICacheableKey^> Members |
| |
| /// <summary> |
| /// Returns an enumerator that iterates through the |
| /// <c>CacheableHashSet</c>. |
| /// </summary> |
| /// <returns> |
| /// A <c>System.Collections.Generic.IEnumerator</c> that |
| /// can be used to iterate through the <c>CacheableHashSet</c>. |
| /// </returns> |
| virtual IEnumerator<Object^>^ GetEnumerator() |
| { |
| typename HSTYPE::Iterator* iter = new typename HSTYPE::Iterator( |
| static_cast<HSTYPE*>(NativePtr())->begin()); |
| |
| return gcnew Enumerator(iter, this); |
| } |
| |
| // End Region: IEnumerable<ICacheableKey^> Members |
| |
| internal: |
| /// <summary> |
| /// Factory function to register wrapper |
| /// </summary> |
| static IGFSerializable^ Create(gemfire::Serializable* obj) |
| { |
| return (obj != NULL ? |
| gcnew CacheableHashSetType<TYPEID,HSTYPE>(obj) : nullptr); |
| } |
| |
| private: |
| // Region: IEnumerable Members |
| |
| /// <summary> |
| /// Returns an enumerator that iterates through a collection. |
| /// </summary> |
| /// <returns> |
| /// An <c>System.Collections.IEnumerator</c> object that can be used |
| /// to iterate through the collection. |
| /// </returns> |
| virtual System::Collections::IEnumerator^ GetIEnumerator() sealed = |
| System::Collections::IEnumerable::GetEnumerator |
| { |
| return GetEnumerator(); |
| } |
| |
| // End Region: IEnumerable Members |
| |
| protected: |
| /// <summary> |
| /// Private constructor to wrap a native object pointer |
| /// </summary> |
| /// <param name="nativeptr">The native object pointer</param> |
| inline CacheableHashSetType<TYPEID, HSTYPE>(gemfire::Serializable* nativeptr) |
| : Serializable(nativeptr) { } |
| |
| /// <summary> |
| /// Allocates a new empty instance. |
| /// </summary> |
| inline CacheableHashSetType<TYPEID, HSTYPE>() |
| : Serializable(HSTYPE::createDeserializable()) |
| { } |
| |
| /// <summary> |
| /// Allocates a new empty instance with given initial size. |
| /// </summary> |
| /// <param name="size">The initial size of the HashSet.</param> |
| inline CacheableHashSetType<TYPEID,HSTYPE>(int32_t size) |
| : Serializable(HSTYPE::create(size).ptr()) |
| { } |
| }; |
| } |
| |
| #define _GFCLI_CACHEABLEHASHSET_DEF_GENERIC(m, HSTYPE) \ |
| public ref class m : public Internal::CacheableHashSetType<GemStone::GemFire::Cache::Generic::GemFireClassIds::m, HSTYPE> \ |
| { \ |
| public: \ |
| /** <summary> |
| * Allocates a new empty instance. |
| * </summary> |
| */ \ |
| inline m() \ |
| : Internal::CacheableHashSetType<GemStone::GemFire::Cache::Generic::GemFireClassIds::m, HSTYPE>() {} \ |
| \ |
| /** <summary> |
| * Allocates a new instance with the given size. |
| * </summary> |
| * <param name="size">the intial size of the new instance</param> |
| */ \ |
| inline m(int32_t size) \ |
| : Internal::CacheableHashSetType<GemStone::GemFire::Cache::Generic::GemFireClassIds::m, HSTYPE>(size) {} \ |
| \ |
| /** <summary> |
| * Static function to create a new empty instance. |
| * </summary> |
| */ \ |
| inline static m^ Create() \ |
| { \ |
| return gcnew m(); \ |
| } \ |
| \ |
| /** <summary> |
| * Static function to create a new instance with the given size. |
| * </summary> |
| */ \ |
| inline static m^ Create(int32_t size) \ |
| { \ |
| return gcnew m(size); \ |
| } \ |
| \ |
| /* <summary> |
| * Factory function to register this class. |
| * </summary> |
| */ \ |
| static IGFSerializable^ CreateDeserializable() \ |
| { \ |
| return gcnew m(); \ |
| } \ |
| \ |
| internal: \ |
| static IGFSerializable^ Create(gemfire::Serializable* obj) \ |
| { \ |
| return gcnew m(obj); \ |
| } \ |
| \ |
| private: \ |
| inline m(gemfire::Serializable* nativeptr) \ |
| : Internal::CacheableHashSetType<GemStone::GemFire::Cache::Generic::GemFireClassIds::m, HSTYPE>(nativeptr) { } \ |
| }; |
| |
| /// <summary> |
| /// A mutable <c>ICacheableKey</c> hash set wrapper that can serve as |
| /// a distributable object for caching. |
| /// </summary> |
| _GFCLI_CACHEABLEHASHSET_DEF_GENERIC(CacheableHashSet, |
| gemfire::CacheableHashSet); |
| |
| /// <summary> |
| /// A mutable <c>ICacheableKey</c> hash set wrapper that can serve as |
| /// a distributable object for caching. This is provided for compability |
| /// with java side though is functionally identical to |
| /// <c>CacheableHashSet</c> i.e. does not provide the linked semantics of |
| /// java <c>LinkedHashSet</c>. |
| /// </summary> |
| _GFCLI_CACHEABLEHASHSET_DEF_GENERIC(CacheableLinkedHashSet, |
| gemfire::CacheableLinkedHashSet); |
| } |
| } |
| } |
| } //namespace |