blob: c75863aabfa4c226848965e722ca115cade113bc [file] [log] [blame]
/*=========================================================================
* 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