http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/Properties.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/Properties.cpp b/clicache/src/Properties.cpp new file mode 100644 index 0000000..af41931 --- /dev/null +++ b/clicache/src/Properties.cpp @@ -0,0 +1,356 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "begin_native.hpp" +#include "CacheImpl.hpp" +#include "SerializationRegistry.hpp" +#include "end_native.hpp" + +#include "Properties.hpp" +#include "impl/ManagedVisitor.hpp" +#include "impl/ManagedString.hpp" +#include "impl/SafeConvert.hpp" +#include "ExceptionTypes.hpp" + +using namespace System; + + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + namespace native = apache::geode::client; + + // Visitor class to get string representations of a property object + ref class PropertyToString + { + private: + + String^ m_str; + + public: + + inline PropertyToString( ) : m_str( "{" ) + { } + + void Visit( Apache::Geode::Client::ICacheableKey^ key, IGeodeSerializable^ value ) + { + if ( m_str->Length > 1 ) { + m_str += ","; + } + m_str += key->ToString( ) + "=" + value; + } + + virtual String^ ToString( ) override + { + return m_str; + } + }; + + generic<class TPropKey, class TPropValue> + TPropValue Properties<TPropKey, TPropValue>::Find( TPropKey key) + { + try + { + native::CacheableKeyPtr keyptr = Serializable::GetUnmanagedValueGeneric<TPropKey>(key, nullptr); + auto nativeptr = m_nativeptr->get()->find(keyptr); + return Serializable::GetManagedValueGeneric<TPropValue>(nativeptr); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::Insert( TPropKey key, TPropValue value ) + { + native::CacheableKeyPtr keyptr = Serializable::GetUnmanagedValueGeneric<TPropKey>(key, true, nullptr); + native::CacheablePtr valueptr = Serializable::GetUnmanagedValueGeneric<TPropValue>(value, true, nullptr); + + _GF_MG_EXCEPTION_TRY2 + + try + { + m_nativeptr->get()->insert(keyptr, valueptr); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::Remove( TPropKey key) + { + native::CacheableKeyPtr keyptr = Serializable::GetUnmanagedValueGeneric<TPropKey>(key, nullptr); + + _GF_MG_EXCEPTION_TRY2 + + try + { + m_nativeptr->get()->remove( keyptr ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::ForEach( PropertyVisitorGeneric<TPropKey, TPropValue>^ visitor ) + { + if (visitor != nullptr) + { + native::ManagedVisitorGeneric mg_visitor( visitor ); + + auto proxy = gcnew PropertyVisitorProxy<TPropKey, TPropValue>(); + proxy->SetPropertyVisitorGeneric(visitor); + + auto otherVisitor = gcnew PropertyVisitor(proxy, &PropertyVisitorProxy<TPropKey, TPropValue>::Visit); + mg_visitor.setptr(otherVisitor); + + _GF_MG_EXCEPTION_TRY2 + + try + { + m_nativeptr->get()->foreach( mg_visitor ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + } + + generic<class TPropKey, class TPropValue> + System::UInt32 Properties<TPropKey, TPropValue>::Size::get( ) + { + _GF_MG_EXCEPTION_TRY2 + + try + { + return m_nativeptr->get()->getSize( ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::AddAll( Properties<TPropKey, TPropValue>^ other ) + { + _GF_MG_EXCEPTION_TRY2 + + try + { + m_nativeptr->get()->addAll( other->GetNative() ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::Load( String^ fileName ) + { + ManagedString mg_fname( fileName ); + + _GF_MG_EXCEPTION_TRY2 + + try + { + m_nativeptr->get()->load( mg_fname.CharPtr ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + generic<class TPropKey, class TPropValue> + String^ Properties<TPropKey, TPropValue>::ToString( ) + { + return ""; + } + + // IGeodeSerializable methods + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::ToData( DataOutput^ output ) + { + if (output->IsManagedObject()) { + //TODO::?? + output->WriteBytesToUMDataOutput(); + } + + try + { + auto nativeOutput = output->GetNative(); + if (nativeOutput != nullptr) + { + _GF_MG_EXCEPTION_TRY2 + + m_nativeptr->get()->toData(*nativeOutput); + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + if (output->IsManagedObject()) { + output->SetBuffer(); + } + } + finally + { + GC::KeepAlive(output); + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TPropKey, class TPropValue> + IGeodeSerializable^ Properties<TPropKey, TPropValue>::FromData( DataInput^ input ) + { + if(input->IsManagedObject()) { + input->AdvanceUMCursor(); + } + + auto nativeInput = input->GetNative(); + if (nativeInput != nullptr) + { + FromData(*nativeInput); + } + + if(input->IsManagedObject()) { + input->SetBuffer(); + } + + return this; + } + + generic<class TPropKey, class TPropValue> + void Properties<TPropKey, TPropValue>::FromData( native::DataInput& input ) + { + _GF_MG_EXCEPTION_TRY2 + + try + { + auto p = static_cast<native::Properties*>(m_nativeptr->get()->fromData(input)); + if (m_nativeptr->get() != p) { + m_nativeptr->get_shared_ptr().reset(p); + } + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + generic<class TPropKey, class TPropValue> + System::UInt32 Properties<TPropKey, TPropValue>::ObjectSize::get( ) + { + //TODO:: + _GF_MG_EXCEPTION_TRY2 + + try + { + return m_nativeptr->get()->objectSize( ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2 + } + + // ISerializable methods + + //generic<class TPropKey, class TPropValue> + //void Properties<TPropKey, TPropValue>::GetObjectData( SerializationInfo^ info, + // StreamingContext context ) + //{ + // auto output = std::unique_ptr<native::DataOutput>(new native::DataOutput(*m_serializationRegistry->get_shared_ptr())); + + // _GF_MG_EXCEPTION_TRY2 + + // try + // { + // m_nativeptr->get()->toData( *output ); + // } + // finally + // { + // GC::KeepAlive(m_nativeptr); + // } + + // _GF_MG_EXCEPTION_CATCH_ALL2 + + // auto bytes = gcnew array<Byte>( output->getBufferLength( ) ); + // { + // pin_ptr<const Byte> pin_bytes = &bytes[0]; + // memcpy( (System::Byte*)pin_bytes, output->getBuffer( ), + // output->getBufferLength( ) ); + // } + // info->AddValue( "bytes", bytes, array<Byte>::typeid ); + //} + // + //generic<class TPropKey, class TPropValue> + //Properties<TPropKey, TPropValue>::Properties( SerializationInfo^ info, + // StreamingContext context, native::SerializationRegistryPtr serializationRegistry) + // : Properties(serializationRegistry) + //{ + // array<Byte>^ bytes = nullptr; + // try { + // bytes = dynamic_cast<array<Byte>^>( info->GetValue( "bytes", + // array<Byte>::typeid ) ); + // } + // catch ( System::Exception^ ) { + // // could not find the header -- null value + // } + // if (bytes != nullptr) { + // pin_ptr<const Byte> pin_bytes = &bytes[0]; + + // _GF_MG_EXCEPTION_TRY2 + + // native::DataInput input( (System::Byte*)pin_bytes, bytes->Length, *CacheImpl::getInstance()->getSerializationRegistry().get()); + // FromData(input); + // _GF_MG_EXCEPTION_CATCH_ALL2 + // } + //} + + + } // namespace Client + } // namespace Geode +} // namespace Apache
http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/Properties.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/Properties.hpp b/clicache/src/Properties.hpp new file mode 100644 index 0000000..c175fff --- /dev/null +++ b/clicache/src/Properties.hpp @@ -0,0 +1,305 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "geode_defs.hpp" + +#include "begin_native.hpp" +#include <geode/Properties.hpp> +#include "SerializationRegistry.hpp" +#include "end_native.hpp" + +#include "IGeodeSerializable.hpp" +#include "ICacheableKey.hpp" +#include "DataInput.hpp" +#include "DataOutput.hpp" +#include "CacheableString.hpp" +#include "native_shared_ptr.hpp" +#include "impl/SafeConvert.hpp" +#include "Serializable.hpp" + +using namespace System; +using namespace System::Runtime::Serialization; +using namespace System::Collections::Generic; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + namespace native = apache::geode::client; + + delegate void PropertyVisitor(Apache::Geode::Client::ICacheableKey^ key, Apache::Geode::Client::IGeodeSerializable^ value); + + generic <class TPropKey, class TPropValue> + ref class PropertyVisitorProxy; + + /// <summary> + /// Delegate that represents visitor for the <c>Properties</c> class. + /// </summary> + /// <remarks> + /// This delegate is passed to the <c>Properties.ForEach</c> function + /// that invokes this delegate for each property having a key + /// and a value. + /// </remarks> + /// <param name="key">The key of the property.</param> + /// <param name="value">The value of the property.</param> + generic<class TPropKey, class TPropValue> + public delegate void PropertyVisitorGeneric( TPropKey key, TPropValue value ); + + generic<class TPropKey, class TPropValue> + [Serializable] + /// <summary> + /// Provides a collection of properties, each of which is a key/value + /// pair. Each key is a string, and the value may be a string + /// or an integer. + /// </summary> + public ref class Properties sealed + : public IGeodeSerializable //,public ISerializable + { + public: + + /// <summary> + /// Default constructor: returns an empty collection. + /// </summary> + inline Properties() + : Properties(native::Properties::create()) + { + + } + + /// <summary> + /// Factory method to create an empty collection of properties. + /// </summary> + /// <returns>empty collection of properties</returns> + generic<class TPropKey, class TPropValue> + inline static Properties<TPropKey, TPropValue>^ Create() + { + return gcnew Properties<TPropKey, TPropValue>(); + } + + + /// <summary> + /// Return the value for the given key, or NULL if not found. + /// </summary> + /// <param name="key">the key to find</param> + /// <returns>the value for the key</returns> + /// <exception cref="NullPointerException"> + /// if the key is null + /// </exception> + TPropValue Find( TPropKey key ); + + /// <summary> + /// Add or update the string value for key. + /// </summary> + /// <param name="key">the key to insert</param> + /// <param name="value">the string value to insert</param> + /// <exception cref="NullPointerException"> + /// if the key is null + /// </exception> + void Insert( TPropKey key, TPropValue value ); + + /// <summary> + /// Remove the key from the collection. + /// </summary> + /// <param name="key">the key to remove</param> + /// <exception cref="NullPointerException"> + /// if the key is null + /// </exception> + void Remove( TPropKey key ); + + /// <summary> + /// Execute the Visitor delegate for each entry in the collection. + /// </summary> + /// <param name="visitor">visitor delegate</param> + void ForEach( PropertyVisitorGeneric<TPropKey, TPropValue>^ visitor ); + + /// <summary> + /// Return the number of entries in the collection. + /// </summary> + /// <returns>the number of entries</returns> + property System::UInt32 Size + { + System::UInt32 get( ); + } + + /*/// <summary> + /// Adds the contents of <c>other</c> to this instance, replacing + /// any existing values with those from other. + /// </summary> + /// <param name="other">new set of properties</param>*/ + void AddAll( Properties<TPropKey, TPropValue>^ other ); + + /// <summary> + /// Reads property values from a file, overriding what is currently + /// in the properties object. + /// </summary> + /// <param name="fileName">the name of the file</param> + void Load( String^ fileName ); + + /// <summary> + /// Returns a string representation of the current + /// <c>Properties</c> object. + /// </summary> + /// <returns> + /// A comma separated list of property name,value pairs. + /// </returns> + virtual String^ ToString( ) override; + + // IGeodeSerializable members + + /// <summary> + /// Serializes this Properties object. + /// </summary> + /// <param name="output"> + /// the DataOutput stream to use for serialization + /// </param> + virtual void ToData( DataOutput^ output ); + + /// <summary> + /// Deserializes this Properties object. + /// </summary> + /// <param name="input"> + /// the DataInput stream to use for reading data + /// </param> + /// <returns>the deserialized Properties object</returns> + virtual IGeodeSerializable^ FromData( DataInput^ input ); + + /// <summary> + /// return the size of this object in bytes + /// </summary> + virtual property System::UInt32 ObjectSize + { + virtual System::UInt32 get( ); + } + + /// <summary> + /// Returns the classId of this class for serialization. + /// </summary> + /// <returns>classId of the Properties class</returns> + /// <seealso cref="IGeodeSerializable.ClassId" /> + virtual property System::UInt32 ClassId + { + inline virtual System::UInt32 get( ) + { + return GeodeClassIds::Properties; + } + } + + // End: IGeodeSerializable members + + // ISerializable members + + //virtual void GetObjectData( SerializationInfo^ info, + // StreamingContext context); + + // End: ISerializable members + + protected: + + // For deserialization using the .NET serialization (ISerializable) + //Properties(SerializationInfo^ info, StreamingContext context, native::SerializationRegistryPtr serializationRegistry); + + + internal: + + /// <summary> + /// Internal factory function to wrap a native object pointer inside + /// this managed class with null pointer check. + /// </summary> + /// <param name="nativeptr">The native object pointer</param> + /// <returns> + /// The managed wrapper object; null if the native pointer is null. + /// </returns> + //generic<class TPropKey, class TPropValue> + static Properties<TPropKey, TPropValue>^ Create( native::PropertiesPtr nativeptr ) + { + return __nullptr == nativeptr ? nullptr : + gcnew Properties<TPropKey, TPropValue>( nativeptr ); + } + + std::shared_ptr<native::Properties> GetNative() + { + return m_nativeptr->get_shared_ptr(); + } + + inline static IGeodeSerializable^ CreateDeserializable() + { + return Create<TPropKey, TPropValue>(); + } + + private: + + /// <summary> + /// Private constructor to wrap a native object pointer + /// </summary> + /// <param name="nativeptr">The native object pointer</param> + inline Properties( native::PropertiesPtr nativeptr ) + { + m_nativeptr = gcnew native_shared_ptr<native::Properties>(nativeptr); + } + + native_shared_ptr<native::Properties>^ m_nativeptr; + + void FromData(native::DataInput & input); + }; + + generic <class TPropKey, class TPropValue> + ref class PropertyVisitorProxy + { + public: + void Visit(Apache::Geode::Client::ICacheableKey^ key, + Apache::Geode::Client::IGeodeSerializable^ value) + { + TPropKey tpkey = Apache::Geode::Client::Serializable:: + GetManagedValueGeneric<TPropKey>(SerializablePtr(SafeMSerializableConvertGeneric(key))); + TPropValue tpvalue = Apache::Geode::Client::Serializable:: + GetManagedValueGeneric<TPropValue>(SerializablePtr(SafeMSerializableConvertGeneric(value))); + m_visitor->Invoke(tpkey, tpvalue); + } + + void SetPropertyVisitorGeneric( + Apache::Geode::Client::PropertyVisitorGeneric<TPropKey, TPropValue>^ visitor) + { + m_visitor = visitor; + } + + private: + + Apache::Geode::Client::PropertyVisitorGeneric<TPropKey, TPropValue>^ m_visitor; + + }; + + /* ref class PropertiesFactory { + public: + PropertiesFactory(native::SerializationRegistryPtr serializationRegistry) + { + m_serializationRegistry = gcnew native_shared_ptr<native::SerializationRegistry>(serializationRegistry); + } + IGeodeSerializable^ CreateDeserializable() { + return Properties<String^, String^>::CreateDeserializable(m_serializationRegistry->get_shared_ptr()); + } + private: + native_shared_ptr<native::SerializationRegistry>^ m_serializationRegistry; + };*/ + } // namespace Client + } // namespace Geode +} // namespace Apache + + http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/Query.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/Query.cpp b/clicache/src/Query.cpp new file mode 100644 index 0000000..071c51f --- /dev/null +++ b/clicache/src/Query.cpp @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#include "geode_includes.hpp" +#include "Query.hpp" +#include "ISelectResults.hpp" +#include "ResultSet.hpp" +#include "StructSet.hpp" +#include "ExceptionTypes.hpp" +//#include "Serializable.hpp" +#include "impl/SafeConvert.hpp" + +using namespace System; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + generic<class TResult> + ISelectResults<TResult>^ Query<TResult>::Execute( ) + { + return Execute( DEFAULT_QUERY_RESPONSE_TIMEOUT ); + } + + generic<class TResult> + ISelectResults<TResult>^ Query<TResult>::Execute( System::UInt32 timeout ) + { + _GF_MG_EXCEPTION_TRY2/* due to auto replace */ + + try + { + return WrapResults( m_nativeptr->get()->execute( timeout )); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */ + } + + generic<class TResult> + ISelectResults<TResult>^ Query<TResult>::Execute( array<Object^>^ paramList) + { + return Execute(paramList, DEFAULT_QUERY_RESPONSE_TIMEOUT); + } + + generic<class TResult> + ISelectResults<TResult>^ Query<TResult>::Execute( array<Object^>^ paramList, System::UInt32 timeout ) + { + _GF_MG_EXCEPTION_TRY2/* due to auto replace */ + + auto rsptr = apache::geode::client::CacheableVector::create(); + for( int index = 0; index < paramList->Length; index++ ) + { + auto valueptr = Serializable::GetUnmanagedValueGeneric<Object^>(paramList[index]->GetType(), (Object^)paramList[index], nullptr); + rsptr->push_back(valueptr); + } + + try + { + return WrapResults( m_nativeptr->get()->execute(rsptr, timeout )); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */ + } + + generic<class TResult> + ISelectResults<TResult>^ Query<TResult>::WrapResults(const apache::geode::client::SelectResultsPtr& selectResults) + { + if ( __nullptr == selectResults ) return nullptr; + + if (auto resultptr = std::dynamic_pointer_cast<apache::geode::client::ResultSet>(selectResults)) + { + return ResultSet<TResult>::Create(resultptr); + } + else if (auto structptr = std::dynamic_pointer_cast<apache::geode::client::StructSet>(selectResults)) + { + return StructSet<TResult>::Create(structptr); + } + + return nullptr; + } + + generic<class TResult> + String^ Query<TResult>::QueryString::get( ) + { + try + { + return ManagedString::Get( m_nativeptr->get()->getQueryString( ) ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TResult> + void Query<TResult>::Compile( ) + { + _GF_MG_EXCEPTION_TRY2/* due to auto replace */ + + try + { + m_nativeptr->get()->compile( ); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */ + } + + generic<class TResult> + bool Query<TResult>::IsCompiled::get() + { + _GF_MG_EXCEPTION_TRY2/* due to auto replace */ + + try + { + return m_nativeptr->get()->isCompiled(); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + + _GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */ + } + } // namespace Client + } // namespace Geode +} // namespace Apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/Query.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/Query.hpp b/clicache/src/Query.hpp new file mode 100644 index 0000000..951cd2c --- /dev/null +++ b/clicache/src/Query.hpp @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "geode_defs.hpp" +#include "begin_native.hpp" +#include <geode/Query.hpp> +#include "end_native.hpp" + +#include "native_shared_ptr.hpp" + +#include "IGeodeSerializable.hpp" + +using namespace System; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + namespace native = apache::geode::client; + + generic<class TResult> + interface class ISelectResults; + + /// <summary> + /// Class to encapsulate a query. + /// </summary> + /// <remarks> + /// A Query is obtained from a QueryService which in turn is obtained + /// from the Cache. + /// This can be executed to return SelectResults which can be either + /// a ResultSet or a StructSet. + /// + /// This class is intentionally not thread-safe. So multiple threads + /// should not operate on the same <c>Query</c> object concurrently + /// rather should have their own <c>Query</c> objects. + /// </remarks> + generic<class TResult> + public ref class Query sealed + { + public: + + /// <summary> + /// Executes the OQL Query on the cache server and returns + /// the results. The default timeout for the query is 15 secs. + /// </summary> + /// <exception cref="QueryException"> + /// if some query error occurred at the server. + /// </exception> + /// <exception cref="IllegalStateException"> + /// if some other error occurred. + /// </exception> + /// <exception cref="NotConnectedException"> + /// if no java cache server is available. + /// For pools configured with locators, if no locators are available, innerException + /// of NotConnectedException is set to NoAvailableLocatorsException. + /// </exception> + /// <returns> + /// An <see cref="ISelectResults"/> object which can either be a + /// <see cref="ResultSet"/> or a <see cref="StructSet"/>. + /// </returns> + ISelectResults<TResult>^ Execute( ); + + /// <summary> + /// Executes the OQL Query on the cache server with the specified + /// timeout and returns the results. + /// </summary> + /// <param name="timeout">The time (in seconds) to wait for query response. + /// This should be less than or equal to 2^31/1000 i.e. 2147483. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// if timeout parameter is greater than 2^31/1000. + /// </exception> + /// <exception cref="QueryException"> + /// if some query error occurred at the server. + /// </exception> + /// <exception cref="IllegalStateException"> + /// if some other error occurred. + /// </exception> + /// <exception cref="NotConnectedException"> + /// if no java cache server is available + /// For pools configured with locators, if no locators are available, innerException + /// of NotConnectedException is set to NoAvailableLocatorsException. + /// </exception> + /// <returns> + /// An <see cref="ISelectResults"/> object which can either be a + /// <see cref="ResultSet"/> or a <see cref="StructSet"/>. + /// </returns> + ISelectResults<TResult>^ Execute( System::UInt32 timeout ); + + /// <summary> + /// Executes the OQL Parameterized Query on the cache server with the specified + /// paramList & timeout parameters and returns the results. + /// </summary> + /// <param name="paramList">The Parameter List for the specified Query. + /// </param> + /// <param name="timeout">The time (in seconds) to wait for query response. + /// This should be less than or equal to 2^31/1000 i.e. 2147483. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// if timeout parameter is greater than 2^31/1000. + /// </exception> + /// <exception cref="QueryException"> + /// if some query error occurred at the server. + /// </exception> + /// <exception cref="IllegalStateException"> + /// if some other error occurred. + /// </exception> + /// <exception cref="NotConnectedException"> + /// if no java cache server is available + /// For pools configured with locators, if no locators are available, innerException + /// of NotConnectedException is set to NoAvailableLocatorsException. + /// </exception> + /// <returns> + /// An <see cref="ISelectResults"/> object which can either be a + /// <see cref="ResultSet"/> or a <see cref="StructSet"/>. + /// </returns> + ISelectResults<TResult>^ Execute( array<Object^>^ paramList, System::UInt32 timeout ); + + /// <summary> + /// Executes the OQL Parameterized Query on the cache server with the specified + /// paramList and returns the results. The default timeout for the query is 15 secs. + /// </summary> + /// <param name="paramList">The Parameter List for the specified Query. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// if timeout parameter is greater than 2^31/1000. + /// </exception> + /// <exception cref="QueryException"> + /// if some query error occurred at the server. + /// </exception> + /// <exception cref="IllegalStateException"> + /// if some other error occurred. + /// </exception> + /// <exception cref="NotConnectedException"> + /// if no java cache server is available + /// For pools configured with locators, if no locators are available, innerException + /// of NotConnectedException is set to NoAvailableLocatorsException. + /// </exception> + /// <returns> + /// An <see cref="ISelectResults"/> object which can either be a + /// <see cref="ResultSet"/> or a <see cref="StructSet"/>. + /// </returns> + ISelectResults<TResult>^ Execute( array<Object^>^ paramList); + /// <summary> + /// Get the string for this query. + /// </summary> + property String^ QueryString + { + String^ get( ); + } + + /// <summary> + /// Compile the given query -- NOT IMPLEMENTED. + /// </summary> + void Compile( ); + + /// <summary> + /// Check if the query is compiled -- NOT IMPLEMENTED. + /// </summary> + property bool IsCompiled + { + bool get( ); + } + + + internal: + + /// <summary> + /// Internal factory function to wrap a native object pointer inside + /// this managed class with null pointer check. + /// </summary> + /// <param name="nativeptr">The native object pointer</param> + /// <returns> + /// The managed wrapper object; null if the native pointer is null. + /// </returns> + inline static Query<TResult>^ Create( apache::geode::client::QueryPtr nativeptr ) + { + return __nullptr == nativeptr ? nullptr : + gcnew Query<TResult>( nativeptr ); + } + + + private: + + /// <summary> + /// Private constructor to wrap a native object pointer + /// </summary> + /// <param name="nativeptr">The native object pointer</param> + inline Query( apache::geode::client::QueryPtr nativeptr ) + { + m_nativeptr = gcnew native_shared_ptr<native::Query>(nativeptr); + } + + ISelectResults<TResult>^ WrapResults(const apache::geode::client::SelectResultsPtr& selectResults); + + native_shared_ptr<native::Query>^ m_nativeptr; + }; + } // namespace Client + } // namespace Geode +} // namespace Apache + http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/QueryService.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/QueryService.cpp b/clicache/src/QueryService.cpp new file mode 100644 index 0000000..acb38cf --- /dev/null +++ b/clicache/src/QueryService.cpp @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#include "geode_includes.hpp" +#include "QueryService.hpp" +#include "Query.hpp" +#include "Log.hpp" +#include "CqAttributes.hpp" +#include "CqQuery.hpp" +#include "CqServiceStatistics.hpp" +#include "impl/ManagedString.hpp" +#include "ExceptionTypes.hpp" +#include "impl/SafeConvert.hpp" + +using namespace System; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + generic<class TKey, class TResult> + //generic<class TResult> + Query<TResult>^ QueryService<TKey, TResult>::NewQuery(String^ query) + { + ManagedString mg_queryStr(query); + try + { + return Query<TResult>::Create(m_nativeptr->get()->newQuery( + mg_queryStr.CharPtr)); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + CqQuery<TKey, TResult>^ QueryService<TKey, TResult>::NewCq(String^ query, CqAttributes<TKey, TResult>^ cqAttr, bool isDurable) + { + ManagedString mg_queryStr(query); + try + { + return CqQuery<TKey, TResult>::Create(m_nativeptr->get()->newCq( + mg_queryStr.CharPtr, cqAttr->GetNative(), isDurable)); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + CqQuery<TKey, TResult>^ QueryService<TKey, TResult>::NewCq(String^ name, String^ query, CqAttributes<TKey, TResult>^ cqAttr, bool isDurable) + { + ManagedString mg_queryStr(query); + ManagedString mg_nameStr(name); + try + { + return CqQuery<TKey, TResult>::Create(m_nativeptr->get()->newCq( + mg_nameStr.CharPtr, mg_queryStr.CharPtr, cqAttr->GetNative(), isDurable)); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + void QueryService<TKey, TResult>::CloseCqs() + { + try + { + m_nativeptr->get()->closeCqs(); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + array<CqQuery<TKey, TResult>^>^ QueryService<TKey, TResult>::GetCqs() + { + try + { + apache::geode::client::QueryService::query_container_type vrr; + m_nativeptr->get()->getCqs(vrr); + auto cqs = gcnew array<CqQuery<TKey, TResult>^>(vrr.size()); + + for (System::Int32 index = 0; index < vrr.size(); index++) + { + cqs[index] = CqQuery<TKey, TResult>::Create(vrr[index]); + } + return cqs; + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + CqQuery<TKey, TResult>^ QueryService<TKey, TResult>::GetCq(String^ name) + { + ManagedString mg_queryStr(name); + try + { + return CqQuery<TKey, TResult>::Create(m_nativeptr->get()->getCq( + mg_queryStr.CharPtr)); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + void QueryService<TKey, TResult>::ExecuteCqs() + { + try + { + m_nativeptr->get()->executeCqs(); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + void QueryService<TKey, TResult>::StopCqs() + { + try + { + m_nativeptr->get()->stopCqs(); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + CqServiceStatistics^ QueryService<TKey, TResult>::GetCqStatistics() + { + try + { + return CqServiceStatistics::Create(m_nativeptr->get()->getCqServiceStatistics()); + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + + generic<class TKey, class TResult> + System::Collections::Generic::List<String^>^ QueryService<TKey, TResult>::GetAllDurableCqsFromServer() + { + try + { + auto durableCqsArrayListPtr = m_nativeptr->get()->getAllDurableCqsFromServer(); + auto durableCqsList = gcnew System::Collections::Generic::List<String^>(); + for (const auto& d : *durableCqsArrayListPtr) + { + durableCqsList->Add(CacheableString::GetString(std::static_pointer_cast<apache::geode::client::CacheableString>(d))); + } + return durableCqsList; + } + catch (const apache::geode::client::Exception& ex) + { + throw GeodeException::Get(ex); + } + finally + { + GC::KeepAlive(m_nativeptr); + } + } + } // namespace Client + } // namespace Geode +} // namespace Apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/QueryService.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/QueryService.hpp b/clicache/src/QueryService.hpp new file mode 100644 index 0000000..78d29ef --- /dev/null +++ b/clicache/src/QueryService.hpp @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "geode_defs.hpp" +#include "native_shared_ptr.hpp" +#include "begin_native.hpp" +#include <geode/QueryService.hpp> +#include "end_native.hpp" + + + + +using namespace System; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + namespace native = apache::geode::client; + + generic<class TResult> + ref class Query; + + generic<class TKey, class TResult> + ref class CqQuery; + + generic<class TKey, class TResult> + ref class CqAttributes; + + ref class CqServiceStatistics; + + /// <summary> + /// Provides a query service. + /// </summary> + generic<class TKey, class TResult> + public ref class QueryService sealed + { + public: + + /// <summary> + /// Get a <c>Query</c> object to enable querying. + /// </summary> + //generic<class TResult> + Query<TResult>^ NewQuery( String^ query ); + /// @nativeclient + /// <summary> + /// Get a <c>CqQuery</c> object to enable continuous querying. + /// </summary> + /// @endnativeclient + //generic<class TKey, class TResult> + CqQuery<TKey, TResult>^ NewCq( String^ query, CqAttributes<TKey, TResult>^ cqAttr, bool isDurable ); + /// @nativeclient + /// <summary> + /// Get a <c>CqQuery</c> object to enable continuous querying. + /// </summary> + /// @endnativeclient + //generic<class TKey, class TResult> + CqQuery<TKey, TResult>^ NewCq( String^ name, String^ query, CqAttributes<TKey, TResult>^ cqAttr, bool isDurable ); + /// @nativeclient + /// <summary> + /// Close all <c>CqQuery</c> on this client. + /// </summary> + /// @endnativeclient + void CloseCqs(); + + /// @nativeclient + /// <summary> + /// Get all <c>CqQuery</c> on this client. + /// </summary> + /// @endnativeclient + //generic<class TKey, class TResult> + array<CqQuery<TKey, TResult>^>^ GetCqs(); + + /// @nativeclient + /// <summary> + /// Get the <c>CqQuery</c> with the given name on this client. + /// </summary> + /// @endnativeclient + //generic<class TKey, class TResult> + CqQuery<TKey, TResult>^ GetCq(String^ name); + + /// @nativeclient + /// <summary> + /// Get the <c>CqQuery</c> with the given name on this client. + /// </summary> + /// @endnativeclient + void ExecuteCqs(); + + /// @nativeclient + /// <summary> + /// Stop all <c>CqQuery</c> on this client. + /// </summary> + /// @endnativeclient + void StopCqs(); + + /// @nativeclient + /// <summary> + /// Get <c>CqServiceStatistics</c> on this client. + /// </summary> + /// @endnativeclient + CqServiceStatistics^ GetCqStatistics(); + + /// @nativeclient + /// <summary> + /// Get all durableCq nanes from server for this client. + /// </summary> + /// @endnativeclient + System::Collections::Generic::List<String^>^ GetAllDurableCqsFromServer(); + + internal: + + /// <summary> + /// Internal factory function to wrap a native object pointer inside + /// this managed class with null pointer check. + /// </summary> + /// <param name="nativeptr">The native object pointer</param> + /// <returns> + /// The managed wrapper object; null if the native pointer is null. + /// </returns> + inline static QueryService<TKey, TResult>^ Create(native::QueryServicePtr nativeptr ) + { + return __nullptr == nativeptr ? nullptr : + gcnew QueryService<TKey, TResult>( nativeptr ); + } + + + private: + + /// <summary> + /// Private constructor to wrap a native object pointer + /// </summary> + /// <param name="nativeptr">The native object pointer</param> + inline QueryService(native::QueryServicePtr nativeptr) + { + m_nativeptr = gcnew native_shared_ptr<native::QueryService>(nativeptr); + } + + native_shared_ptr<native::QueryService>^ m_nativeptr; + }; + } // namespace Client + } // namespace Geode +} // namespace Apache + http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/ReflectionBasedAutoSerializer.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/ReflectionBasedAutoSerializer.cpp b/clicache/src/ReflectionBasedAutoSerializer.cpp new file mode 100755 index 0000000..436ce4b --- /dev/null +++ b/clicache/src/ReflectionBasedAutoSerializer.cpp @@ -0,0 +1,565 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ReflectionBasedAutoSerializer.hpp" +#include "PdxIdentityFieldAttribute.hpp" +#include "Serializable.hpp" +#pragma warning(disable:4091) +#include <msclr/lock.h> +#include "ExceptionTypes.hpp" +#include "impl/DotNetTypes.hpp" +namespace Apache +{ + namespace Geode + { + namespace Client + { + + ref class FieldWrapper + { + private: + //static readonly Module Module = typeof(Program).Module; + static array<Type^>^ oneObj = gcnew array<Type^>(1) { Type::GetType("System.Object") }; + static array<Type^>^ twoObj = gcnew array<Type^>(2) { Type::GetType("System.Object"), Type::GetType("System.Object") }; + delegate void MySetter(Object^ t1, Object^ t2); + delegate Object^ MyGetter(Object^ t1); + + static Type^ setterDelegateType = Type::GetType("Apache.Geode.Client.FieldWrapper+MySetter"); + static Type^ getterDelegateType = Type::GetType("Apache.Geode.Client.FieldWrapper+MyGetter"); + + FieldInfo^ m_fi; + String^ m_fieldName; + bool m_isIdentityField; + FieldType m_fieldType; + int m_pdxType; + + MyGetter^ m_getter; + MySetter^ m_setter; + + static MySetter^ createFieldSetter(FieldInfo^ fieldInfo) + { + DynamicMethod^ dynam = gcnew DynamicMethod("", Internal::DotNetTypes::VoidType , twoObj, fieldInfo->DeclaringType, true); + ILGenerator^ il = dynam->GetILGenerator(); + + if (!fieldInfo->IsStatic) + pushInstance(il, fieldInfo->DeclaringType); + + il->Emit(OpCodes::Ldarg_1); + unboxIfNeeded(il, fieldInfo->FieldType); + il->Emit(OpCodes::Stfld, fieldInfo); + il->Emit(OpCodes::Ret); + + return (MySetter^)dynam->CreateDelegate( setterDelegateType ); + } + + static MyGetter^ createFieldGetter(FieldInfo^ fieldInfo) + { + DynamicMethod^ dynam = gcnew DynamicMethod( "", Internal::DotNetTypes::ObjectType, oneObj, fieldInfo->DeclaringType, true); + ILGenerator^ il = dynam->GetILGenerator(); + + if (!fieldInfo->IsStatic) + pushInstance(il, fieldInfo->DeclaringType); + + il->Emit(OpCodes::Ldfld, fieldInfo); + boxIfNeeded(il, fieldInfo->FieldType); + il->Emit(OpCodes::Ret); + + return (MyGetter^)dynam->CreateDelegate(getterDelegateType); + } + + static void boxIfNeeded(ILGenerator^ il, Type^ type) + { + if (type->IsValueType) + il->Emit(OpCodes::Box, type); + } + + static void pushInstance( ILGenerator^ il, Type^ type) + { + il->Emit(OpCodes::Ldarg_0); + if (type->IsValueType) + il->Emit(OpCodes::Unbox, type); + } + + static void unboxIfNeeded( ILGenerator^ il, Type^ type) + { + if (type->IsValueType) + il->Emit(OpCodes::Unbox_Any, type); + } + public: + FieldWrapper(FieldInfo^ fi, String^ fieldName, bool isIdentityField, FieldType fieldtype) + { + m_fi = fi; + m_fieldName = fieldName; + m_isIdentityField = isIdentityField; + m_fieldType = fieldtype; + + m_setter = createFieldSetter(fi); + m_getter = createFieldGetter(fi); + } + + property bool isIdentityField + { + bool get(){return m_isIdentityField;} + } + + property Type^ FType + { + Type^ get() {return m_fi->FieldType;} + } + + property String^ FieldName + { + String^ get(){return m_fieldName;} + } + + property FieldInfo^ FI + { + FieldInfo^ get(){return m_fi;} + } + + void SetFieldValue(Object^ parent, Object^ val) + { + m_setter(parent, val); + } + + Object^ GetFieldValue(Object^ parent) + { + return m_getter(parent); + } + + void SerializeField(IPdxWriter^ w, Object^ value) + { + switch(m_fieldType) + { + case FieldType::BOOLEAN: + w->WriteBoolean(m_fieldName, (bool)value); + break; + case FieldType::BYTE: + w->WriteByte(m_fieldName, (SByte)value); + break; + case FieldType::CHAR: + w->WriteChar(m_fieldName, (Char)value); + break; + case FieldType::SHORT: + w->WriteShort(m_fieldName, (short)value); + break; + case FieldType::INT: + w->WriteInt(m_fieldName, (int)value); + break; + case FieldType::LONG: + w->WriteLong(m_fieldName, (Int64)value); + break; + case FieldType::FLOAT: + w->WriteFloat(m_fieldName, (float)value); + break; + case FieldType::DOUBLE: + w->WriteDouble(m_fieldName, (double)value); + break; + case FieldType::DATE: + w->WriteDate(m_fieldName, (DateTime)value); + break; + case FieldType::STRING: + w->WriteString(m_fieldName, (String^)value); + break; + case FieldType::OBJECT: + w->WriteObject(m_fieldName, value); + break; + case FieldType::BOOLEAN_ARRAY: + w->WriteBooleanArray(m_fieldName, (array<bool>^)value); + break; + case FieldType::CHAR_ARRAY: + w->WriteCharArray(m_fieldName, (array<Char>^)value); + break; + case FieldType::BYTE_ARRAY: + w->WriteByteArray(m_fieldName, (array<Byte>^)value); + break; + case FieldType::SHORT_ARRAY: + w->WriteShortArray(m_fieldName, (array<Int16>^)value); + break; + case FieldType::INT_ARRAY: + w->WriteIntArray(m_fieldName, (array<Int32>^)value); + break; + case FieldType::LONG_ARRAY: + w->WriteLongArray(m_fieldName, (array<System::Int64>^)value); + break; + case FieldType::FLOAT_ARRAY: + w->WriteFloatArray(m_fieldName, (array<float>^)value); + break; + case FieldType::DOUBLE_ARRAY: + w->WriteDoubleArray(m_fieldName, (array<double>^)value); + break; + case FieldType::STRING_ARRAY: + w->WriteStringArray(m_fieldName, (array<String^>^)value); + break; + case FieldType::OBJECT_ARRAY: + w->WriteObjectArray(m_fieldName, safe_cast<System::Collections::Generic::List<Object^>^>(value)); + break; + case FieldType::ARRAY_OF_BYTE_ARRAYS: + w->WriteArrayOfByteArrays(m_fieldName, (array<array<Byte>^>^)value); + break; + default: + throw gcnew IllegalStateException("Not found FieldType: " + m_fieldType.ToString()); + } + } + + Object^ DeserializeField(IPdxReader^ r) + { + switch(m_fieldType) + { + case FieldType::BOOLEAN: + return r->ReadBoolean(m_fieldName); + break; + case FieldType::BYTE: + return r->ReadByte(m_fieldName); + break; + case FieldType::CHAR: + return r->ReadChar(m_fieldName); + break; + case FieldType::SHORT: + return r->ReadShort(m_fieldName); + break; + case FieldType::INT: + return r->ReadInt(m_fieldName); + break; + case FieldType::LONG: + return r->ReadLong(m_fieldName); + break; + case FieldType::FLOAT: + return r->ReadFloat(m_fieldName); + break; + case FieldType::DOUBLE: + return r->ReadDouble(m_fieldName); + break; + case FieldType::DATE: + return r->ReadDate(m_fieldName); + break; + case FieldType::STRING: + return r->ReadString(m_fieldName); + break; + case FieldType::OBJECT: + return r->ReadObject(m_fieldName); + break; + case FieldType::BOOLEAN_ARRAY: + return r->ReadBooleanArray(m_fieldName); + break; + case FieldType::CHAR_ARRAY: + return r->ReadCharArray(m_fieldName); + break; + case FieldType::BYTE_ARRAY: + return r->ReadByteArray(m_fieldName); + break; + case FieldType::SHORT_ARRAY: + return r->ReadShortArray(m_fieldName); + break; + case FieldType::INT_ARRAY: + return r->ReadIntArray(m_fieldName); + break; + case FieldType::LONG_ARRAY: + return r->ReadLongArray(m_fieldName); + break; + case FieldType::FLOAT_ARRAY: + return r->ReadFloatArray(m_fieldName); + break; + case FieldType::DOUBLE_ARRAY: + return r->ReadDoubleArray(m_fieldName); + break; + case FieldType::STRING_ARRAY: + return r->ReadStringArray(m_fieldName); + break; + case FieldType::OBJECT_ARRAY: + return r->ReadObjectArray(m_fieldName); + break; + case FieldType::ARRAY_OF_BYTE_ARRAYS: + return r->ReadArrayOfByteArrays(m_fieldName); + break; + default: + throw gcnew IllegalStateException("Not found FieldType: " + m_fieldType.ToString()); + } + return nullptr; + } + + + + }; + + ReflectionBasedAutoSerializer::ReflectionBasedAutoSerializer() + { + PdxIdentityFieldAttribute^ pif = gcnew PdxIdentityFieldAttribute(); + PdxIdentityFieldAttributeType = pif->GetType(); + classNameVsFieldInfoWrapper = gcnew Dictionary<String^, List<FieldWrapper^>^>(); + } + + bool ReflectionBasedAutoSerializer::ToData( Object^ o,IPdxWriter^ writer ) + { + serializeFields(o, writer); + return true; + } + + Object^ ReflectionBasedAutoSerializer::FromData(String^ o, IPdxReader^ reader ) + { + return deserializeFields(o, reader); + } + + void ReflectionBasedAutoSerializer::serializeFields(Object^ o,IPdxWriter^ writer ) + { + Type^ ty = o->GetType(); + // Log::Debug("ReflectionBasedAutoSerializer::serializeFields classname {0}: objectType {1}", o->GetType()->FullName,o->GetType()); + for each(FieldWrapper^ fi in GetFields(o->GetType())) + { + // Log::Debug("ReflectionBasedAutoSerializer::serializeFields fieldName: {0}, fieldType: {1}", fi->FieldName, fi->FType); + // writer->WriteField(fi->Name, fi->GetValue(o), fi->FieldType); + // SerializeField(o, fi, writer); + //Object^ originalValue = fi->FI->GetValue(o); + Object^ originalValue = fi->GetFieldValue(o); + //hook which can overide by app + originalValue = WriteTransform(fi->FI, fi->FType, originalValue); + + fi->SerializeField(writer, originalValue); + + if(fi->isIdentityField) + { + // Log::Debug("ReflectionBasedAutoSerializer::serializeFields fieldName: {0} is identity field.", fi->FieldName); + writer->MarkIdentityField(fi->FieldName); + } + } + + // serializeBaseClassFields(o, writer, ty->BaseType); + } + + + /*void ReflectionBasedAutoSerializer::SerializeField(Object^ o, FieldInfo^ fi, IPdxWriter^ writer) + { + writer->WriteField(fi->Name, fi->GetValue(o), fi->FieldType); + } + + Object^ ReflectionBasedAutoSerializer::DeserializeField(Object^ o, FieldInfo^ fi, IPdxReader^ reader) + { + return reader->ReadField(fi->Name, fi->FieldType); + }*/ + + Object^ ReflectionBasedAutoSerializer::deserializeFields(String^ className, IPdxReader^ reader) + { + Object^ o = CreateObject(className); + //Log::Debug("ReflectionBasedAutoSerializer::deserializeFields classname {0}: objectType {1}", className,o->GetType()); + for each(FieldWrapper^ fi in GetFields(o->GetType())) + { + //Log::Debug("1ReflectionBasedAutoSerializer::deserializeFields fieldName: {0}, fieldType: {1}", fi->FieldName, fi->FType); + Object^ serializeValue = fi->DeserializeField(reader); + serializeValue = ReadTransform( fi->FI, fi->FType, serializeValue); + //fi->FI->SetValue(o, serializeValue); + fi->SetFieldValue(o, serializeValue); + } + + return o; + //deserializeBaseClassFields(o, reader, ty->BaseType); + } + + Object^ ReflectionBasedAutoSerializer::CreateObject(String^ className) + { + return Serializable::CreateObject(className); + } + + bool ReflectionBasedAutoSerializer::IsPdxIdentityField(FieldInfo^ fi) + { + array<Object^>^ cAttr= fi->GetCustomAttributes(PdxIdentityFieldAttributeType, true); + if(cAttr != nullptr && cAttr->Length > 0) + { + PdxIdentityFieldAttribute^ pifa = (PdxIdentityFieldAttribute^)(cAttr[0]); + return true; + } + return false; + } + + List<FieldWrapper^>^ ReflectionBasedAutoSerializer::GetFields(Type^ domaimType) + { + List<FieldWrapper^>^ retVal = nullptr; + + String^ className = domaimType->FullName; + System::Collections::Generic::Dictionary<String^, List<FieldWrapper^>^>^ tmp = classNameVsFieldInfoWrapper; + tmp->TryGetValue(className, retVal); + if(retVal != nullptr) + return retVal; + msclr::lock lockInstance(classNameVsFieldInfoWrapper); + { + tmp = classNameVsFieldInfoWrapper; + tmp->TryGetValue(className, retVal); + if(retVal != nullptr) + return retVal; + + List<FieldWrapper^>^ collectFields = gcnew List<FieldWrapper^>(); + while(domaimType != nullptr) + { + for each(FieldInfo^ fi in domaimType->GetFields(BindingFlags::Public| BindingFlags::NonPublic | BindingFlags::Instance + |BindingFlags::DeclaredOnly + )) + { + if(!fi->IsNotSerialized && !fi->IsStatic && !fi->IsLiteral && !fi->IsInitOnly) + { + //to ignore the fild + if(IsFieldIncluded(fi, domaimType)) + { + //This are all hooks which app can implement + + String^ fieldName = GetFieldName(fi, domaimType); + bool isIdentityField = IsIdentityField(fi, domaimType); + FieldType ft = GetFieldType(fi, domaimType); + + FieldWrapper^ fw = gcnew FieldWrapper(fi, fieldName, isIdentityField, ft); + + collectFields->Add(fw); + } + } + } + domaimType = domaimType->BaseType; + } + tmp = gcnew System::Collections::Generic::Dictionary<String^, List<FieldWrapper^>^>(classNameVsFieldInfoWrapper); + tmp->Add(className, collectFields); + classNameVsFieldInfoWrapper = tmp; + + return collectFields; + } + } + + + String^ ReflectionBasedAutoSerializer::GetFieldName(FieldInfo^ fi, Type^ type) + { + return fi->Name; + } + + bool ReflectionBasedAutoSerializer::IsIdentityField(FieldInfo^ fi, Type^ type) + { + return IsPdxIdentityField(fi); + } + + FieldType ReflectionBasedAutoSerializer::GetFieldType(FieldInfo^ fi, Type^ type) + { + return getPdxFieldType(fi->FieldType); + } + + bool ReflectionBasedAutoSerializer::IsFieldIncluded(FieldInfo^ fi, Type^ type) + { + return true; + } + + Object^ ReflectionBasedAutoSerializer::WriteTransform(FieldInfo^ fi, Type^ type, Object^ originalValue) + { + return originalValue; + } + + Object^ ReflectionBasedAutoSerializer::ReadTransform(FieldInfo^ fi, Type^ type, Object^ serializeValue) + { + return serializeValue; + } + + FieldType ReflectionBasedAutoSerializer::getPdxFieldType( Type^ type) + { + if(type->Equals(Internal::DotNetTypes::IntType)) + { + return FieldType::INT; + } + else if(type->Equals(Internal::DotNetTypes::StringType)) + { + return FieldType::STRING; + } + else if(type->Equals(Internal::DotNetTypes::BooleanType)) + { + return FieldType::BOOLEAN; + } + else if(type->Equals(Internal::DotNetTypes::FloatType)) + { + return FieldType::FLOAT; + } + else if(type->Equals(Internal::DotNetTypes::DoubleType)) + { + return FieldType::DOUBLE; + } + else if(type->Equals(Internal::DotNetTypes::CharType)) + { + return FieldType::CHAR; + } + else if(type->Equals(Internal::DotNetTypes::SByteType)) + { + return FieldType::BYTE; + } + else if(type->Equals(Internal::DotNetTypes::ShortType)) + { + return FieldType::SHORT; + } + else if(type->Equals(Internal::DotNetTypes::LongType)) + { + return FieldType::LONG; + } + else if(type->Equals(Internal::DotNetTypes::ByteArrayType)) + { + return FieldType::BYTE_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::DoubleArrayType)) + { + return FieldType::DOUBLE_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::FloatArrayType)) + { + return FieldType::FLOAT_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::ShortArrayType)) + { + return FieldType::SHORT_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::IntArrayType)) + { + return FieldType::INT_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::LongArrayType)) + { + return FieldType::LONG_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::BoolArrayType)) + { + return FieldType::BOOLEAN_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::CharArrayType)) + { + return FieldType::CHAR_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::StringArrayType)) + { + return FieldType::STRING_ARRAY; + } + else if(type->Equals(Internal::DotNetTypes::DateType)) + { + return FieldType::DATE; + } + else if(type->Equals(Internal::DotNetTypes::ByteArrayOfArrayType)) + { + return FieldType::ARRAY_OF_BYTE_ARRAYS; + } + /*else if(type->Equals(Internal::DotNetTypes::ObjectArrayType)) + { + //Giving more preference to arraylist instead of Object[] in java side + //return this->WriteObjectArray(fieldName, safe_cast<System::Collections::Generic::List<Object^>^>(fieldValue)); + return FieldType::OBJECT_ARRAY; + }*/ + else + { + return FieldType::OBJECT; + //throw gcnew IllegalStateException("WriteField unable to serialize " + // + fieldName + " of " + type); + } // namespace Client + } // namespace Geode +} // namespace Apache + + } +} http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/ReflectionBasedAutoSerializer.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/ReflectionBasedAutoSerializer.hpp b/clicache/src/ReflectionBasedAutoSerializer.hpp new file mode 100755 index 0000000..e32b68f --- /dev/null +++ b/clicache/src/ReflectionBasedAutoSerializer.hpp @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "geode_defs.hpp" +#include "IPdxSerializer.hpp" +#include "PdxIdentityFieldAttribute.hpp" +using namespace System; +using namespace System::Reflection; +using namespace System::Reflection::Emit; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + /// <summary> + /// Enumerated type for pdx FieldType + /// </summary> + public enum class FieldType + { + BOOLEAN, + BYTE, + CHAR, + SHORT, + INT, + LONG, + FLOAT, + DOUBLE, + DATE, + STRING, + OBJECT, + BOOLEAN_ARRAY, + CHAR_ARRAY, + BYTE_ARRAY, + SHORT_ARRAY, + INT_ARRAY, + LONG_ARRAY, + FLOAT_ARRAY, + DOUBLE_ARRAY, + STRING_ARRAY, + OBJECT_ARRAY, + ARRAY_OF_BYTE_ARRAYS + }; + + ref class FieldWrapper; + + /// <summary> + /// This class uses .NET reflection in conjunction with + /// <see cref="IPdxSerializer"/> to perform + /// automatic serialization of domain objects. The implication is that the domain + /// classes do not need to implement the <see cref="IPdxSerializable"> interface. + /// This implementation will serialize all relevant fields. + /// This will not serialize the fields which has defined attribute NonSerialized. + /// This will not serialize the static, literal and readonly fields. + /// + /// Use <see cref="PdxIdentityFieldAttribute"> to define member field as identity field. + /// Identity fields are used for hashcode creation and equals methods. + /// + /// </summary> + public ref class ReflectionBasedAutoSerializer : IPdxSerializer + { + public: + + virtual bool ToData( Object^ o,IPdxWriter^ writer ); + + virtual Object^ FromData(String^ o, IPdxReader^ reader ); + + /// <summary> + /// Controls the field name that will be used in pdx for a field being auto serialized. + /// Override this method to customize the field names that will be generated by auto serialization. + /// It allows you to convert a local, language dependent name, to a more portable name. + /// The returned name is the one that will show up in a <see cref="IPdxInstance" /> and that + /// one that will need to be used to access the field when doing a query. + /// <para> + /// The default implementation returns the name obtained from <code>fi</code>. + /// <para> + /// This method is only called the first time it sees a new class. The result + /// will be remembered and used the next time the same class is seen. + /// </summary> + /// <param name="fi"> the field whose name is returned.</param> + /// <param name"type"> type the original class being serialized that owns this field.</param> + /// <returns> the name of the field </returns> + + virtual String^ GetFieldName(FieldInfo^ fi, Type^ type); + + /// <summary> + /// Controls what fields of a class that is auto serialized will be marked + /// as pdx identity fields. + /// Override this method to customize what fields of an auto serialized class will be + /// identity fields. + /// Identity fields are used when a <see cref="IPdxInstance" /> computes its hash code + /// and checks to see if it is equal to another object. + /// <para> + /// The default implementation only marks fields that match an "#identity=" pattern + /// as identity fields. + /// <para> + /// This method is only called the first time it sees a new class. The result + /// will be remembered and used the next time the same class is seen. + /// </summary> + /// <param name="fi"> the field to test to see if it is an identity field.</param> + /// <param name="type"> the original class being serialized that owns this field.</param> + /// <returns> true if the field should be marked as an identity field; false if not. </returns> + + virtual bool IsIdentityField(FieldInfo^ fi, Type^ type); + + /// <summary> + /// Controls what pdx field type will be used when auto serializing. + /// Override this method to customize what pdx field type will be used + /// for a given domain class field. + /// <para> + /// The default implementation uses type of field. + /// <para> + /// This method is only called the first time it sees a new class. The result + /// will be remembered and used the next time the same class is seen. + /// </summary> + /// <param name="fi"> the field whose pdx field type needs to be determined </param> + /// <param name="type"> the original class being serialized that owns this field.</param> + /// <returns> the pdx field type of the given domain class field.</returns> + + virtual FieldType GetFieldType(FieldInfo^ fi, Type^ type); + + /// <summary> + /// Controls what fields of a class will be auto serialized by this serializer. + /// Override this method to customize what fields of a class will be auto serialized. + /// The default implementation: + /// <list type="bullet"> + /// <item> + /// <description> excludes NonSerialized fields</description> + /// </item> + /// <item> + /// <description> excludes static fields</description> + /// </item> + /// <item> + /// <description> excludes literal fields</description> + /// </item> + /// <item> + /// <description> excludes readonly fields </description> + /// </item> + /// </list> + /// All other fields are included. + /// This method is only called the first time it sees a new class. The result + /// will be remembered and used the next time the same class is seen. + /// </summary> + /// <param name="fi"> the field being considered for serialization</param> + /// <param name="type"> the original class being serialized that owns this field.</param> + /// <returns> true if the field should be serialized as a pdx field; false if it should be ignored.</returns> + + virtual bool IsFieldIncluded(FieldInfo^ fi, Type^ type); + + /// <summary> + /// Controls what field value is written during auto serialization. + /// Override this method to customize the data that will be written + /// during auto serialization. + /// </summary> + /// <param name="fi"> the field in question</param> + /// <param name="type"> the original class being serialized that owns this field.</param> + /// <param name="originalValue"> the value of the field that was read from the domain object.</param> + /// <returns> the actual value to write for this field. Return <code>originalValue</code> + /// if you decide not to transform the value. </returns> + + virtual Object^ WriteTransform(FieldInfo^ fi, Type^ type, Object^ originalValue); + + /// <summary> + /// Controls what field value is read during auto deserialization. + /// Override this method to customize the data that will be read + /// during auto deserialization. + /// This method will only be called if {@link #transformFieldValue} + /// returned true. + /// </summary> + /// <param name="fi"> the field in question </param> + /// <param name="type"> the original class being serialized that owns this field. + /// Note that this field may have been inherited from a super class by this class.</param> + /// <param value="serializeValue"> the value of the field that was serialized for this field.</param> + /// <returns> the actual value to write for this field. Return <code>serializedValue</code> + /// if you decide not to transform the value. </returns> + virtual Object^ ReadTransform(FieldInfo^ fi, Type^ type, Object^ serializeValue); + + /// <summary> + /// Overirde this method to create default instance of <code>className</code> + /// Otherwise it will create instance using zer arg public constructor + /// </summary> + /// <param name="className"> name of the class to create default instance </param> + /// <returns> the defaulf instance </returns> + + virtual Object^ CreateObject(String^ className); + + ReflectionBasedAutoSerializer(); + private: + + FieldType getPdxFieldType( Type^ type); + + void serializeFields(Object^ o,IPdxWriter^ writer ); + + Object^ deserializeFields(String^ o, IPdxReader^ reader); + + bool IsPdxIdentityField(FieldInfo^ fi); + + System::Collections::Generic::Dictionary<String^, List<FieldWrapper^>^>^ classNameVsFieldInfoWrapper; + + List<FieldWrapper^>^ GetFields(Type^ domaimType); + + static Type^ PdxIdentityFieldAttributeType = nullptr; + }; + } // namespace Client + } // namespace Geode +} // namespace Apache +