/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "VlppGlrParser.h"
#include "VlppReflection.h"
#include "VlppOS.h"
#include "Vlpp.h"
#include "VlppRegex.h"

/***********************************************************************
.\WFLIBRARYPREDEFINED.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection

Interfaces:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_PREDEFINED
#define VCZH_WORKFLOW_LIBRARY_PREDEFINED

#include <math.h>

namespace vl
{
	namespace reflection
	{
		namespace description
		{

/***********************************************************************
Coroutine
***********************************************************************/

			/// <summary>Status of a coroutine.</summary>
			enum class CoroutineStatus
			{
				/// <summary>The coroutine is waiting for resuming.</summary>
				Waiting,
				/// <summary>The coroutine is being executed.</summary>
				Executing,
				/// <summary>The coroutine has stopped.</summary>
				Stopped,
			};

			/// <summary>An object providing input information when resuming a coroutine.</summary>
			class CoroutineResult : public virtual IDescriptable, public Description<CoroutineResult>
			{
			protected:
				Value									result;
				Ptr<IValueException>					failure;

			public:
				/// <summary>Get the object provided to the coroutine. This object is the return value for the pending async operation, like $Await.</summary>
				/// <returns>The object provided to the coroutine.</returns>
				Value									GetResult();

				/// <summary>Set the object provided to the coroutine.</summary>
				/// <param name="value">The object provided to the coroutine.</summary>
				void									SetResult(const Value& value);

				/// <summary>Get the error provided to the coroutine. When it is not nullptr, the return value of <see cref="GetResult"/> is ignored.</summary>
				/// <returns>The error provided to the coroutine.</returns>
				Ptr<IValueException>					GetFailure();

				/// <summary>Set the error provided to the coroutine.</summary>
				/// <param name="value">The error provided to the coroutine.</summary>
				void									SetFailure(Ptr<IValueException> value);
			};

			/// <summary>A coroutine. This is typically created by a Workflow script.</summary>
			class ICoroutine : public virtual IDescriptable, public Description<ICoroutine>
			{
			public:
				/// <summary>Resume the coroutine.</summary>
				/// <param name="raiseException">Set to true to raise an exception that the coroutine encountered. The same exception is accessible by <see cref="GetFailure"/>.</param>
				/// <param name="output">Input for the coroutine in this resuming.</param>
				virtual void							Resume(bool raiseException, Ptr<CoroutineResult> output) = 0;

				/// <summary>Returns the current exception.</summary>
				/// <returns>The current exception. It could cause by the Workflow script that creates this coroutine, or by calling <see cref="Resume"/> when this coroutine is in an inappropriate state.</returns>
				virtual Ptr<IValueException>			GetFailure() = 0;

				/// <summary>Returns the status of the coroutine.</summary>
				/// <returns>The status of the coroutine. <see cref="Resume"/> can be called only when this function returns <see cref="CoroutineStatus::Waiting"/>.</returns>
				virtual CoroutineStatus					GetStatus() = 0;
			};

/***********************************************************************
Coroutine (Enumerable)
***********************************************************************/

			class EnumerableCoroutine : public Object, public Description<EnumerableCoroutine>
			{
			public:
				class IImpl : public virtual IValueEnumerator, public Description<IImpl>
				{
				public:
					virtual void						OnYield(const Value& value) = 0;
					virtual void						OnJoin(Ptr<IValueEnumerable> value) = 0;
				};

				typedef Func<Ptr<ICoroutine>(IImpl*)>	Creator;

				static void								YieldAndPause(IImpl* impl, const Value& value);
				static void								JoinAndPause(IImpl* impl, Ptr<IValueEnumerable> value);
				static void								ReturnAndExit(IImpl* impl);
				static Ptr<IValueEnumerable>			Create(const Creator& creator);
			};

/***********************************************************************
Coroutine (Async)
***********************************************************************/

			/// <summary>Status of am async operation.</summary>
			enum class AsyncStatus
			{
				/// <summary>The async operation is ready to execute.</summary>
				Ready,
				/// <summary>The async operation is being executed.</summary>
				Executing,
				/// <summary>The async operation has stopped.</summary>
				Stopped,
			};

			/// <summary>A context providing communication between the caller and the async operation.</summary>
			class AsyncContext : public virtual IDescriptable, public Description<AsyncContext>
			{
			protected:
				SpinLock								lock;
				bool									cancelled = false;
				Value									context;

			public:
				/// <summary>Create a context.</summary>
				/// <param name="_context">Set the initial return value for <see cref="GetContext"/> (optional)..</param>
				AsyncContext(const Value& _context = {});
				~AsyncContext();

				/// <summary>Test if the current async operation is expected to cancel.</summary>
				/// <returns>Returns true if the current async operation is expected to cancel.</returns>
				/// <remarks>
				/// This function is accessible by "$.IsCancelled" in an $Async coroutine.
				/// A cancelable async operation should check this value when it is able to stop properly, and stop when it is true.
				/// </remarks>
				bool									IsCancelled();

				/// <summary>Set <see cref="IsCancelled"/> to true.</summary>
				/// <returns>Returns true when this operation succeeded.</returns>
				bool									Cancel();

				/// <summary>Returns a value that is accessible in Workflow script by "$.Context" in an $Async coroutine.</summary>
				/// <returns>A value that is accessible in Workflow script by "$.Context" in an $Async coroutine.</returns>
				const description::Value&				GetContext();

				/// <summary>Set a value that is accessible F</summary>
				/// <param name="value">A value that is accessible in Workflow script by "$.Context" in an $Async coroutine.</param>
				void									SetContext(const description::Value& value);
			};

			/// <summary>An async operation.</summary>
			class IAsync : public virtual IDescriptable, public Description<IAsync>
			{
			public:
				/// <summary>Get the status of this async operation.</summary>
				/// <returns>The status of this async operation.</returns>
				virtual AsyncStatus						GetStatus() = 0;

				/// <summary>Run this async operation.</summary>
				/// <returns>Returns true when this operation succeeded. This function cannot be called twice on the same object.</returns>
				/// <param name="callback">A callback to execute when the async operation finished.</param>
				/// <param name="context">A context object that is accessible in Workflow script by "$" in an $Async coroutine (optional).</param>
				virtual bool							Execute(const Func<void(Ptr<CoroutineResult>)>& callback, Ptr<AsyncContext> context = nullptr) = 0;

				/// <summary>Create an async operation that finished after a specified moment of time.</summary>
				/// <returns>Returns the created async operation.</returns>
				/// <param name="milliseconds">The time in milliseconds to wait. It counts from when this function is called, not from when this async operation is executed.</param>
				static Ptr<IAsync>						Delay(vint milliseconds);
			};

			/// <summary>A promise object that controls a <see cref="IFuture"/> object.</summary>
			class IPromise : public virtual IDescriptable, public Description<IPromise>
			{
			public:
				/// <summary>Mark the <see cref="IFuture"/> object as finished by providing a value.</summary>
				/// <returns>Returns true when this operation succeeded. Multiple calls to <see cref="SendResult"/> and <see cref="SendFailure"/> cause a failure.</returns>
				/// <param name="result">The result of the <see cref="IFuture"/> object.</param>
				virtual bool							SendResult(const Value& result) = 0;

				/// <summary>Mark the <see cref="IFuture"/> object as finished by providing an exception.</summary>
				/// <returns>Returns true when this operation succeeded. Multiple calls to <see cref="SendResult"/> and <see cref="SendFailure"/> cause a failure.</returns>
				/// <param name="failure">The exception of the <see cref="IFuture"/> object.</param>
				virtual bool							SendFailure(Ptr<IValueException> failure) = 0;
			};

			/// <summary>An async operation in the future-promise pattern.</summary>
			class IFuture : public virtual IAsync, public Description<IFuture>
			{
			public:
				/// <summary>Get the <see cref="IPromise"/> that controls this future object.</summary>
				/// <returns>The <see cref="IPromise"/> that controls this future object.</returns>
				virtual Ptr<IPromise>					GetPromise() = 0;

				/// <summary>Create a future object.</summary>
				/// <returns>The created future object.</returns>
				static Ptr<IFuture>						Create();
			};

			/// <summary>A scheduler that controls how async operations are executed. It needs to be implemented and attached to threads that run async operations.</summary>
			/// <remarks>See <a href="/workflow/lang/coroutine_async.html">Async Coroutine</a> for more information.</remarks>
			class IAsyncScheduler : public virtual IDescriptable, public Description<IAsyncScheduler>
			{
			public:
				/// <summary>Called when a callback needs to be executed in any thread.</summary>
				/// <param name="callback">The callback to execute.</param>
				/// <remarks>
				/// You can decide which thread to execute.
				/// For GacUI, the scheduler that attached to the UI thread will execute this callback in the UI thread.
				/// </remarks>
				virtual void							Execute(const Func<void()>& callback) = 0;

				/// <summary>Called when a callback needs to be executed in another thread.</summary>
				/// <param name="callback">The callback to execute.</param>
				/// <remarks>
				/// You can decide which thread to execute except the current one.
				/// For GacUI, the scheduler that attached to any thread will execute this callback in a random background thread.
				/// </remarks>
				virtual void							ExecuteInBackground(const Func<void()>& callback) = 0;

				/// <summary>Called when a callback needs to be executed in any thread after a specified moment of time.</summary>
				/// <param name="callback">The callback to execute.</param>
				/// <param name="milliseconds">The time in milliseconds to wait.</param>
				/// <remarks>
				/// You can decide which thread to execute.
				/// For GacUI, the scheduler that attached to the UI thread will execute this callback in the UI thread.
				/// </remarks>
				virtual void							DelayExecute(const Func<void()>& callback, vint milliseconds) = 0;

				/// <summary>Attach a scheduler for all threads.</summary>
				/// <param name="scheduler">The scheduler to attach.</param>
				static void								RegisterDefaultScheduler(Ptr<IAsyncScheduler> scheduler);

				/// <summary>Attach a scheduler for the current thread.</summary>
				/// <param name="scheduler">The scheduler to attach.</param>
				static void								RegisterSchedulerForCurrentThread(Ptr<IAsyncScheduler> scheduler);

				/// <summary>Detach the scheduler for all threads.</summary>
				/// <returns>The previously attached scheduler.</returns>
				static Ptr<IAsyncScheduler>				UnregisterDefaultScheduler();

				/// <summary>Detach the scheduler for the current thread.</summary>
				/// <returns>The previously attached scheduler.</returns>
				static Ptr<IAsyncScheduler>				UnregisterSchedulerForCurrentThread();

				/// <summary>Get the attached scheduler for the current thread.</summary>
				/// <returns>The attached scheduler. If there is no scheduler that is attached to this particular thread, the default scheduler kicks in.</returns>
				static Ptr<IAsyncScheduler>				GetSchedulerForCurrentThread();
			};

			class AsyncCoroutine : public Object, public Description<AsyncCoroutine>
			{
			public:
				class IImpl : public virtual IAsync, public Description<IImpl>
				{
				public:
					virtual Ptr<IAsyncScheduler>		GetScheduler() = 0;
					virtual Ptr<AsyncContext>			GetContext() = 0;
					virtual void						OnContinue(Ptr<CoroutineResult> output) = 0;
					virtual void						OnReturn(const Value& value) = 0;
				};

				typedef Func<Ptr<ICoroutine>(IImpl*)>	Creator;

				static void								AwaitAndRead(IImpl* impl, Ptr<IAsync> value);
				static void								ReturnAndExit(IImpl* impl, const Value& value);
				static Ptr<AsyncContext>				QueryContext(IImpl* impl);
				static Ptr<IAsync>						Create(const Creator& creator);
				static void								CreateAndRun(const Creator& creator);
			};

/***********************************************************************
Coroutine (State Machine)
***********************************************************************/

			class StateMachine : public Object, public AggregatableDescription<StateMachine>
			{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				friend struct CustomTypeDescriptorSelector<StateMachine>;
#endif
			protected:
				bool									stateMachineInitialized = false;
				bool									stateMachineStopped = false;
				vint									stateMachineInput = -1;
				Ptr<ICoroutine>							stateMachineCoroutine;

				void									ResumeStateMachine();
			public:
				StateMachine();
				~StateMachine();

				CoroutineStatus							GetStateMachineStatus();
			};

/***********************************************************************
Libraries
***********************************************************************/

			/// <summary>system::Sys includes a lot of utility functions for type conversion, string operations and date time operations for a Workflow script.</summary>
			class Sys : public Description<Sys>
			{
			public:
				static vint			Int32ToInt(vint32_t value)							{ return (vint)value; }
				static vint			Int64ToInt(vint64_t value)							{ return (vint)value; }
				static vint32_t		IntToInt32(vint value)								{ return (vint32_t)value; }
				static vint64_t		IntToInt64(vint value)								{ return (vint64_t)value; }
				
				static vuint		UInt32ToUInt(vuint32_t value)						{ return (vuint)value; }
				static vuint		UInt64ToUInt(vuint64_t value)						{ return (vuint)value; }
				static vuint32_t	UIntToUInt32(vuint value)							{ return (vuint32_t)value; }
				static vuint64_t	UIntToUInt64(vuint value)							{ return (vuint64_t)value; }

				static vint			Len(const WString& value)							{ return value.Length(); }
				static WString		Left(const WString& value, vint length)				{ return value.Left(length); }
				static WString		Right(const WString& value, vint length)			{ return value.Right(length); }
				static WString		Mid(const WString& value, vint start, vint length)	{ return value.Sub(start, length); }
				static vint			Find(const WString& value, const WString& substr)	{ return INVLOC.FindFirst(value, substr, Locale::Normalization::None).key; }
				static WString		UCase(const WString& value)							{ return wupper(value); }
				static WString		LCase(const WString& value)							{ return wlower(value); }

				static WString		LoremIpsumTitle(vint bestLength)					{ return vl::LoremIpsumTitle(bestLength); }
				static WString		LoremIpsumSentence(vint bestLength)					{ return vl::LoremIpsumSentence(bestLength); }
				static WString		LoremIpsumParagraph(vint bestLength)				{ return vl::LoremIpsumParagraph(bestLength); }

#define DEFINE_COMPARE(TYPE) static vint Compare(TYPE a, TYPE b);
				REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DEFINE_COMPARE)
				DEFINE_COMPARE(DateTime)
#undef DEFINE_COMPARE

				static DateTime		GetLocalTime();
				static DateTime		GetUtcTime();
				static DateTime		ToLocalTime(DateTime dt);
				static DateTime		ToUtcTime(DateTime dt);
				static DateTime		Forward(DateTime dt, vuint64_t milliseconds);
				static DateTime		Backward(DateTime dt, vuint64_t milliseconds);
				static DateTime		CreateDateTime(vint year, vint month, vint day);
				static DateTime		CreateDateTime(vint year, vint month, vint day, vint hour, vint minute, vint second, vint milliseconds);

				static Ptr<IValueEnumerable>		ReverseEnumerable(Ptr<IValueEnumerable> value);
			};

			/// <summary>system::Math includes math functions for a Workflow script.</summary>
			class Math : public Description<Math>
			{
			public:
				static double		Pi()							{ return ASin(1) * 2; }

				static vint8_t		Abs(vint8_t value)				{ return value > 0 ? value : -value; }
				static vint16_t		Abs(vint16_t value)				{ return value > 0 ? value : -value; }
				static vint32_t		Abs(vint32_t value)				{ return value > 0 ? value : -value; }
				static vint64_t		Abs(vint64_t value)				{ return value > 0 ? value : -value; }
				static float		Abs(float value)				{ return value > 0 ? value : -value; }
				static double		Abs(double value)				{ return value > 0 ? value : -value; }
				
#define DEFINE_MINMAX(TYPE)\
				static TYPE Min(TYPE a, TYPE b);\
				static TYPE Max(TYPE a, TYPE b);\

				REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DEFINE_MINMAX)
				DEFINE_MINMAX(DateTime)
#undef DEFINE_MINMAX

				static double		Sin(double value)				{ return sin(value); }
				static double		Cos(double value)				{ return cos(value); }
				static double		Tan(double value)				{ return tan(value); }
				static double		ASin(double value)				{ return asin(value); }
				static double		ACos(double value)				{ return acos(value); }
				static double		ATan(double value)				{ return atan(value); }
				static double		ATan2(double x, double y)		{ return atan2(y, x); }

				static double		Exp(double value)				{ return exp(value);  }
				static double		LogN(double value)				{ return log(value); }
				static double		Log10(double value)				{ return log10(value); }
				static double		Log(double value, double base)	{ return log(value) / log(base); }
				static double		Pow(double value, double power)	{ return pow(value, power); }
				static double		Ceil(double value)				{ return ceil(value); }
				static double		Floor(double value)				{ return floor(value); }
				static double		Round(double value)				{ return round(value); }
				static double		Trunc(double value)				{ return trunc(value); }
			};

			/// <summary>system::Math includes localization awared formatting operations for a Workflow script.</summary>
			/// <remarks>
			/// <p>
			/// There are three locales that reflect the configuration of the operating system:
			/// <ul>
			///     <li><b>Invariant</b>: An invariant locale for general languages.</li>
			///     <li><b>System</b>: Locale for the operating system, including the file system.</li>
			///     <li><b>User</b>: Locale for UI of the operating system.</li>
			/// </ul>
			/// </p>
			/// </remarks>
			class Localization : public Description<Localization>
			{
			public:
				static Locale							Invariant();
				static Locale							System();
				static Locale							User();
				static collections::LazyList<Locale>	Locales();

				static collections::LazyList<WString>	GetShortDateFormats(Locale locale);
				static collections::LazyList<WString>	GetLongDateFormats(Locale locale);
				static collections::LazyList<WString>	GetYearMonthDateFormats(Locale locale);
				static collections::LazyList<WString>	GetLongTimeFormats(Locale locale);
				static collections::LazyList<WString>	GetShortTimeFormats(Locale locale);

				static WString							GetShortDayOfWeekName(Locale locale, vint dayOfWeek);
				static WString							GetLongDayOfWeekName(Locale locale, vint dayOfWeek);
				static WString							GetShortMonthName(Locale locale, vint month);
				static WString							GetLongMonthName(Locale locale, vint month);

				static WString							FormatDate(Locale locale, const WString& format, DateTime date);
				static WString							FormatTime(Locale locale, const WString& format, DateTime date);
				static WString							FormatNumber(Locale locale, const WString& number);
				static WString							FormatCurrency(Locale locale, const WString& number);
			};

/***********************************************************************
MISC
***********************************************************************/

			class Versioning : public Object, public Description<Versioning>
			{
			protected:
				vint					version = 0;

			public:
				Versioning();
				~Versioning();

				vint					AllocateVersion();
				vint					GetVersion();
			};
		}
	}
}

namespace vl
{
	namespace __vwsn
	{
		struct att_cpp_File
		{
			WString						argument;
			auto operator<=>(const att_cpp_File&) const = default;
		};

		struct att_cpp_UserImpl
		{
			auto operator<=>(const att_cpp_UserImpl&) const = default;
		};

		struct att_cpp_Private
		{
			auto operator<=>(const att_cpp_Private&) const = default;
		};

		struct att_cpp_Protected
		{
			auto operator<=>(const att_cpp_Protected&) const = default;
		};

		struct att_cpp_Friend
		{
			reflection::description::ITypeDescriptor*	argument = nullptr;
			auto operator<=>(const att_cpp_Friend&) const = default;
		};

		struct att_rpc_Interface
		{
			auto operator<=>(const att_rpc_Interface&) const = default;
		};

		struct att_rpc_Ctor
		{
			auto operator<=>(const att_rpc_Ctor&) const = default;
		};

		struct att_rpc_Byval
		{
			auto operator<=>(const att_rpc_Byval&) const = default;
		};

		struct att_rpc_Byref
		{
			auto operator<=>(const att_rpc_Byref&) const = default;
		};

		struct att_rpc_Cached
		{
			auto operator<=>(const att_rpc_Cached&) const = default;
		};

		struct att_rpc_Dynamic
		{
			auto operator<=>(const att_rpc_Dynamic&) const = default;
		};

		struct att_rpc_IdString
		{
			WString						argument;
			auto operator<=>(const att_rpc_IdString&) const = default;
		};

		struct att_rpc_IdNumber
		{
			vint						argument = 0;
			auto operator<=>(const att_rpc_IdNumber&) const = default;
		};
	}
}

#endif


/***********************************************************************
.\WFLIBRARYCPPHELPER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection

Interfaces:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_CPPLIBRARY
#define VCZH_WORKFLOW_LIBRARY_CPPLIBRARY


namespace vl
{
	namespace __vwsn
	{
		template<typename T>
		struct RunOnExit
		{
			T* function;

			RunOnExit(T* _function)
				:function(_function)
			{
			}

			~RunOnExit()
			{
				function->operator()();
			}
		};

		template<typename T>
		T* This(T* thisValue)
		{
			CHECK_ERROR(thisValue != nullptr, L"The this pointer cannot be null.");
			return thisValue;
		}

		template<typename T>
		T* Ensure(T* pointer)
		{
			CHECK_ERROR(pointer != nullptr, L"The pointer cannot be null.");
			return pointer;
		}

		template<typename T>
		Ptr<T>& Ensure(Ptr<T>& pointer)
		{
			CHECK_ERROR(pointer != nullptr, L"The pointer cannot be null.");
			return pointer;
		}

		template<typename T>
		Ptr<T> Ensure(Ptr<T>&& pointer)
		{
			CHECK_ERROR(pointer != nullptr, L"The pointer cannot be null.");
			return std::move(pointer);
		}

		template<typename T>
		Nullable<T> Ensure(Nullable<T>&& nullable)
		{
			CHECK_ERROR(nullable, L"The pointer cannot be null.");
			return std::move(nullable);
		}

		template<typename T>
		Nullable<T>& Ensure(Nullable<T>& nullable)
		{
			CHECK_ERROR(nullable, L"The pointer cannot be null.");
			return nullable;
		}

		template<typename T>
		WString ToString(const T& value)
		{
			WString str;
			CHECK_ERROR(reflection::description::TypedValueSerializerProvider<std::remove_cvref_t<T>>::Serialize(value, str), L"Failed to serialize.");
			return str;
		}

		template<typename T>
		T Parse(const WString& str)
		{
			T value;
			CHECK_ERROR(reflection::description::TypedValueSerializerProvider<std::remove_cvref_t<T>>::Deserialize(str, value), L"Failed to serialize.");
			return value;
		}

		template<typename TTo, typename TFrom>
		struct NullableCastHelper
		{
			static Nullable<TTo> Cast(Nullable<TFrom> nullable)
			{
				return Nullable<TTo>(static_cast<TTo>(nullable.Value()));
			}
		};

		template<typename TFrom>
		struct NullableCastHelper<WString, TFrom>
		{
			static Nullable<WString> Cast(Nullable<TFrom> nullable)
			{
				return Nullable<WString>(ToString(nullable.Value()));
			}
		};

		template<typename TTo>
		struct NullableCastHelper<TTo, WString>
		{
			static Nullable<TTo> Cast(Nullable<WString> nullable)
			{
				return Nullable<TTo>(Parse<TTo>(nullable.Value()));
			}
		};

		template<typename TTo, typename TFrom>
		Nullable<TTo> NullableCast(Nullable<TFrom> nullable)
		{
			if (!nullable) return Nullable<TTo>();
			return NullableCastHelper<TTo, TFrom>::Cast(nullable);
		}

		template<typename TTo, typename TFrom>
		TTo* RawPtrCast(TFrom* pointer)
		{
			if (!pointer) return nullptr;
			if (auto converted = dynamic_cast<TTo*>(pointer)) return converted;
			return pointer->template SafeAggregationCast<TTo>();
		}

		template<typename TTo, typename TFrom>
		Ptr<TTo> SharedPtrCast(TFrom* pointer)
		{
			if (!pointer) return nullptr;
			if (auto converted = dynamic_cast<TTo*>(pointer)) return Ptr(converted);
			return Ptr(pointer->template SafeAggregationCast<TTo>());
		}

		template<typename T>
		reflection::description::Value Box(T&& value)
		{
			return reflection::description::BoxParameter(value);
		}

		template<typename T>
		T Unbox(const reflection::description::Value& value)
		{
			auto unboxed = reflection::description::UnboxParameter<std::remove_cvref_t<T>>(value);
			if (std::is_reference_v<T>)
			{
				CHECK_ERROR(!unboxed.IsOwned(), L"It is impossible to return a reference from a unboxed value, when the unboxing has to call new T(...).");
			}
			return unboxed.Ref();
		}

		template<typename T>
		struct UnboxWeakHelper
		{
		};

		template<typename T>
		struct UnboxWeakHelper<T*>
		{
			static T* Unbox(const reflection::description::Value& value)
			{
				if (value.IsNull()) return nullptr;
				auto rawPtr = value.GetRawPtr();
				if (!rawPtr) return nullptr;
				if (auto converted = dynamic_cast<T*>(rawPtr)) return converted;
				try
				{
					return rawPtr->SafeAggregationCast<T>();
				}
				catch (const Exception&)
				{
					return nullptr;
				}
			}
		};

		template<typename T>
		struct UnboxWeakHelper<Ptr<T>>
		{
			static Ptr<T> Unbox(const reflection::description::Value& value)
			{
				if (value.IsNull()) return nullptr;
				auto rawPtr = value.GetRawPtr();
				if (!rawPtr) return nullptr;
				if (auto converted = dynamic_cast<T*>(rawPtr)) return Ptr(converted);
				try
				{
					return Ptr(rawPtr->SafeAggregationCast<T>());
				}
				catch (const Exception&)
				{
					return nullptr;
				}
			}
		};

		template<typename T>
		struct UnboxWeakHelper<Nullable<T>>
		{
			static Nullable<T> Unbox(const reflection::description::Value& value)
			{
				if (value.IsNull()) return Nullable<T>();
				auto boxed = value.GetBoxedValue().Cast<reflection::description::IValueType::TypedBox<T>>();
				if (!boxed) return Nullable<T>();
				return Nullable<T>(boxed->value);
			}
		};

		template<typename T>
		T UnboxWeak(const reflection::description::Value& value)
		{
			return UnboxWeakHelper<std::remove_cvref_t<T>>::Unbox(value);
		}

		template<typename T>
		collections::LazyList<T> Range(T begin, T end)
		{
			return collections::Range<T>(begin, end - begin);
		}

		template<typename T>
		bool InSet(const T& value, const collections::LazyList<T>& collection)
		{
			return collection.Any([&](const T& element) {return element == value; });
		}

		template<typename T>
		bool InSet(const T& value, Ptr<reflection::description::IValueReadonlyList> collection)
		{
			return InSet<T>(value, reflection::description::GetLazyList<T>(collection));
		}

		template<typename T, typename U>
		Ptr<T> UnboxCollection(U&& value)
		{
			auto boxedValue = reflection::description::BoxParameter(value);
			return reflection::description::UnboxParameter<Ptr<T>>(boxedValue).Ref();
		}

		template<typename T, typename U>
		Ptr<T> UnboxCollection(const collections::LazyList<U>& value)
		{
			auto boxedValue = reflection::description::BoxParameter(const_cast<collections::LazyList<U>&>(value));
			return reflection::description::UnboxParameter<Ptr<T>>(boxedValue).Ref();
		}

		struct CreateArray
		{
			using IValueArray = reflection::description::IValueArray;

			Ptr<IValueArray>		list;

			CreateArray();
			CreateArray(Ptr<IValueArray> _list);

			CreateArray Resize(vint size)
			{
				list->Resize(size);
				return{ list };
			}

			template<typename T>
			CreateArray Set(vint index, const T& value)
			{
				list->Set(index, Box(value));
				return{ list };
			}
		};

		struct CreateList
		{
			using IValueList = reflection::description::IValueList;

			Ptr<IValueList>			list;

			CreateList();
			CreateList(Ptr<IValueList> _list);

			template<typename T>
			CreateList Add(const T& value)
			{
				list->Add(Box(value));
				return{ list };
			}
		};

		struct CreateObservableList
		{
			using IValueObservableList = reflection::description::IValueObservableList;

			Ptr<IValueObservableList>			list;

			CreateObservableList();
			CreateObservableList(Ptr<IValueObservableList> _list);

			template<typename T>
			CreateObservableList Add(const T& value)
			{
				list->Add(Box(value));
				return{ list };
			}
		};

		struct CreateDictionary
		{
			using IValueDictionary = reflection::description::IValueDictionary;

			Ptr<IValueDictionary>	dictionary;

			CreateDictionary();
			CreateDictionary(Ptr<IValueDictionary> _dictionary);

			template<typename K, typename V>
			CreateDictionary Add(const K& key, const V& value)
			{
				dictionary->Set(Box(key), Box(value));
				return{ dictionary };
			}
		};

		template<typename T>
		struct EventHelper
		{
		};

		template<typename T>
		Ptr<reflection::description::IEventHandler> EventAttach(T& e, typename EventHelper<T>::Handler handler)
		{
			return EventHelper<T>::Attach(e, handler);
		}

		template<typename T>
		bool EventDetach(T& e, Ptr<reflection::description::IEventHandler> handler)
		{
			return EventHelper<T>::Detach(e, handler);
		}

		template<typename T>
		decltype(auto) EventInvoke(T& e)
		{
			return EventHelper<T>::Invoke(e);
		}

		template<typename ...TArgs>
		struct EventHelper<Event<void(TArgs...)>>
		{
			using Handler = const Func<void(TArgs...)>&;

			class EventHandlerImpl : public Object, public reflection::description::IEventHandler
			{
			public:
				Ptr<EventHandler> handler;

				EventHandlerImpl(Ptr<EventHandler> _handler)
					:handler(_handler)
				{
				}

				bool IsAttached()override
				{
					return handler->IsAttached();
				}
			};

			static Ptr<reflection::description::IEventHandler> Attach(Event<void(TArgs...)>& e, Handler handler)
			{
				return Ptr(new EventHandlerImpl(e.Add(handler)));
			}

			static bool Detach(Event<void(TArgs...)>& e, Ptr<reflection::description::IEventHandler> handler)
			{
				auto impl = handler.Cast<EventHandlerImpl>();
				if (!impl) return false;
				return e.Remove(impl->handler);
			}

			static Event<void(TArgs...)>& Invoke(Event<void(TArgs...)>& e)
			{
				return e;
			}
		};
	}
}

#endif


/***********************************************************************
.\RPC\WFLIBRARYRPC.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::RPC

Interfaces:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_RPC
#define VCZH_WORKFLOW_LIBRARY_RPC


namespace vl
{
	namespace rpc_controller
	{
		constexpr vint RpcTypeId_NotFound = -100;
		constexpr vint RpcClientId_Invalid = -1;
		constexpr vint RpcObjectId_Invalid = -1;

		struct RpcObjectReference
		{
			vint							clientId = RpcClientId_Invalid;
			vint							objectId = RpcObjectId_Invalid;
			vint							typeId = RpcTypeId_NotFound;

			auto operator<=>(const RpcObjectReference&) const = default;
		};

		struct RpcException
		{
			WString							message;

			auto operator<=>(const RpcException&) const = default;
		};

		using RpcEventExceptionMap = Ptr<reflection::description::IValueDictionary>;
		using RpcLocalServiceMap = collections::Dictionary<vint, Ptr<reflection::IDescriptable>>;

		extern void												MergeRpcEventExceptionMap(RpcEventExceptionMap target, RpcEventExceptionMap source);

		class RpcByvalReturnValue
			: public Object
			, public reflection::Description<RpcByvalReturnValue>
		{
		public:
			reflection::description::Value	value;
			vint							slot = -1;
		};

		inline constexpr vint				RpcTypeId_IValueEnumerable = -1;
		inline constexpr vint				RpcTypeId_IValueEnumerator = -2;
		inline constexpr vint				RpcTypeId_IValueArray = -3;
		inline constexpr vint				RpcTypeId_IValueList = -4;
		inline constexpr vint				RpcTypeId_IValueObservableList = -5;
		inline constexpr vint				RpcTypeId_IValueDictionary = -6;
		inline constexpr vint				RpcTypeId_IValueReadonlyList = -7;

		inline constexpr vint				RpcMethodId_IValueEnumerable_CreateEnumerator = -1;
		inline constexpr vint				RpcMethodId_IValueEnumerator_Next = -2;
		inline constexpr vint				RpcMethodId_IValueEnumerator_GetCurrent = -3;
		inline constexpr vint				RpcMethodId_IValueReadonlyList_GetCount = -4;
		inline constexpr vint				RpcMethodId_IValueReadonlyList_Get = -5;
		inline constexpr vint				RpcMethodId_IValueList_Set = -6;
		inline constexpr vint				RpcMethodId_IValueList_Add = -7;
		inline constexpr vint				RpcMethodId_IValueList_Insert = -8;
		inline constexpr vint				RpcMethodId_IValueList_RemoveAt = -9;
		inline constexpr vint				RpcMethodId_IValueList_Clear = -10;
		inline constexpr vint				RpcMethodId_IValueReadonlyList_Contains = -11;
		inline constexpr vint				RpcMethodId_IValueReadonlyList_IndexOf = -12;
		inline constexpr vint				RpcMethodId_IValueReadonlyDictionary_GetCount = -13;
		inline constexpr vint				RpcMethodId_IValueReadonlyDictionary_Get = -14;
		inline constexpr vint				RpcMethodId_IValueDictionary_Set = -15;
		inline constexpr vint				RpcMethodId_IValueDictionary_Remove = -16;
		inline constexpr vint				RpcMethodId_IValueDictionary_Clear = -17;
		inline constexpr vint				RpcMethodId_IValueReadonlyDictionary_ContainsKey = -18;
		inline constexpr vint				RpcMethodId_IValueReadonlyDictionary_GetKeys = -19;
		inline constexpr vint				RpcMethodId_IValueReadonlyDictionary_GetValues = -20;
		inline constexpr vint				RpcMethodId_IValueArray_Resize = -21;

		inline constexpr vint				RpcEventId_IValueObservableList_ItemChanged = -1;

/***********************************************************************
* Interfaces (Serialization)
***********************************************************************/

		class IRpcSerializer
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcSerializer>
		{
		public:
			virtual reflection::description::Value					Serialize(const reflection::description::Value& value) = 0;
			virtual reflection::description::Value					Deserialize(const reflection::description::Value& value) = 0;
		};

/***********************************************************************
* Interfaces (Operations)
***********************************************************************/

		class IRpcListOps
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcListOps>
		{
		public:
			virtual RpcObjectReference								EnumCreate(RpcObjectReference ref) = 0;
			virtual bool											EnumNext(RpcObjectReference enumerator) = 0;
			virtual reflection::description::Value					EnumGetCurrent(RpcObjectReference enumerator) = 0;

			virtual vint											ListGetCount(RpcObjectReference ref) = 0;
			virtual reflection::description::Value					ListGet(RpcObjectReference ref, vint index) = 0;
			virtual void											ListSet(RpcObjectReference ref, vint index, const reflection::description::Value& value) = 0;
			virtual vint											ListAdd(RpcObjectReference ref, const reflection::description::Value& value) = 0;
			virtual vint											ListInsert(RpcObjectReference ref, vint index, const reflection::description::Value& value) = 0;
			virtual bool											ListRemoveAt(RpcObjectReference ref, vint index) = 0;
			virtual void											ListClear(RpcObjectReference ref) = 0;
			virtual bool											ListContains(RpcObjectReference ref, const reflection::description::Value& value) = 0;
			virtual vint											ListIndexOf(RpcObjectReference ref, const reflection::description::Value& value) = 0;
			virtual void											ArrayResize(RpcObjectReference ref, vint size) = 0;

			virtual vint											DictGetCount(RpcObjectReference ref) = 0;
			virtual reflection::description::Value					DictGet(RpcObjectReference ref, const reflection::description::Value& key) = 0;
			virtual void											DictSet(RpcObjectReference ref, const reflection::description::Value& key, const reflection::description::Value& value) = 0;
			virtual bool											DictRemove(RpcObjectReference ref, const reflection::description::Value& key) = 0;
			virtual void											DictClear(RpcObjectReference ref) = 0;
			virtual bool											DictContainsKey(RpcObjectReference ref, const reflection::description::Value& key) = 0;
			virtual RpcObjectReference								DictGetKeys(RpcObjectReference ref) = 0;
			virtual RpcObjectReference								DictGetValues(RpcObjectReference ref) = 0;
		};

		class IRpcObjectOps
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcObjectOps>
		{
		public:
			virtual reflection::description::Value					InvokeMethod(RpcObjectReference ref, vint methodId, Ptr<reflection::description::IValueArray> arguments) = 0;
			virtual void											EndInvokeMethod(vint slot) = 0;
			virtual void											ObjectHold(RpcObjectReference ref, vint remoteClientId, bool hold) = 0;
		};

		class IRpcListEventOps
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcListEventOps>
		{
		public:
			virtual reflection::description::Value					OnItemChanged(RpcObjectReference ref, vint index, vint oldCount, vint newCount) = 0;
		};

		class IRpcObjectEventOps
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcObjectEventOps>
		{
		public:
			virtual reflection::description::Value					InvokeEvent(RpcObjectReference ref, vint eventId, Ptr<reflection::description::IValueArray> arguments) = 0;
		};

/***********************************************************************
* Interfaces (Lifecycle)
***********************************************************************/

		class IRpcOperations
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcOperations>
		{
		public:
			virtual IRpcObjectOps*					GetObjectOps() = 0;
			virtual IRpcObjectEventOps*				GetObjectEventOps() = 0;
		};

		class IRpcDispatcher
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcDispatcher>
		{
		public:
			virtual void							Finalize() = 0;
			virtual void							Initialize() = 0;
			virtual void							DeclareLocalService(RpcObjectReference ref) = 0;

			virtual IRpcObjectEventOps*				BroadcastFromClient_ObjectEventOps(vint selfClientId) = 0;
			virtual IRpcObjectOps*					SendToClient_ObjectOps(vint targetClientId) = 0;
		};

		class IRpcController
			: public virtual IRpcOperations
			, public reflection::Description<IRpcController>
		{
		public:
			virtual void							Finalize() = 0;
			virtual void							SetEventSuppressedFlag(RpcObjectReference ref, vint eventId, bool suppressed) = 0;
			virtual bool							GetEventSuppressedFlag(RpcObjectReference ref, vint eventId) = 0;
			virtual void							SetItemChangedSuppressedFlag(RpcObjectReference ref, bool suppressed) = 0;
			virtual bool							GetItemChangedSuppressedFlag(RpcObjectReference ref) = 0;
		};

		/*
		* [Configuration]
		*
		* RunRpcTestCase_JsonRequest configures one RpcJsonDispatcher and one RpcJsonLifecycle for each client.
		*   messageDispatcher = shared IRpcJsonMessageDispatcher
		*   dispatcher = RpcJsonDispatcher(clientId, messageDispatcher)
		*   lifecycle = RpcJsonLifecycle(clientId, dispatcher)
		*   serializer = rpcops_IRpcSerializer()
		*   getTypeId = [rpcwrapper_GetTypeId(BoxValue<IDescriptable*>(obj))]
		*   lifecycle->Register(serializer, rpcops_IRpcObjectOpsJson(lifecycle), rpcops_IRpcObjectEventOpsJson(lifecycle), getTypeId, eventAttacher)
		*
		* Triggering RpcLifecycleBase::AttachLocalObjectEvents
		*   call rpclistener_Attach(ref.typeId, this, ref, obj, (cached)rpcops_IOps_CreateJson(this))
		*
		* [Call graph for JSON based RPC]
		*
		* Calling Method of Remote Object:
		*   -> IMyInterface::Method (generated Workflow code)
		*   -> rpcops_IOps_<Application>::InvokeMethod_IMyInterface_Method (generated Workflow code)
		*   {
		*     -> IRpcLifecycle->GetDispatcher()->SendToClient_ObjectOps()->InvokeMethod
		*     -> RpcJsonObjectOps::InvokeMethod
		*     -> IRpcJsonMessageDispatcher::OnJsonRequest
		*     ---- NETWORK PROTOCOL (request) ----
		*     -> RpcJsonObjectOps::Translate
		*     -> IRpcLifecycle->GetController()->GetObjectOps()->InvokeMethod
		*     -> RpcCalleeObjectOpsForList::InvokeMethod
		*     -> rpcops_IRpcObjectOpsJson()->InvokeMethod (generated Workflow code)
		*     -> IMyInterface::Method (actual)
		*     ---- NETWORK PROTOCOL (response) ----
		*   }
		*   { optional EndInvokeMethod when @rpc:Byval on return value }
		*
		* Triggering Event of Remote Object (events are automatically hooked when creating a wrapper for a remote object):
		*   -> IMyInterface::SomethingHappened
		*   -> rpcops_IOps_<Application>::InvokeMethod_IMyInterface_SomethingHappened (generated Workflow code)
		*   {
		*     -> IRpcLifecycle->GetDispatcher()->BroadcastFromClient_ObjectEventOps()->InvokeEvent
		*     -> RpcJsonEventObjectOps::InvokeEvent
		*     -> IRpcJsonMessageDispatcher::OnJsonRequest
		*     ---- NETWORK PROTOCOL (broadcast) ----
		*     -> RpcJsonEventObjectOps::Translate
		*     -> IRpcLifecycle->GetController()->GetObjectOps()->InvokeEvent
		*     -> RpcCalleeObjectEventOpsForList::InvokeEvent
		*     -> rpcops_IRpcObjectEventOpsJson()->InvokeEvent (generated Workflow code)
		*     -> IMyInterface::SomethingHappened
		*     ---- NETWORK PROTOCOL (response) ----
		*   }
		*
		* Triggering Event of Local Object (when a local object is tracked, RpcLifecycleBase::AttachLocalObjectEvents will be called)
		*   The same to remote object.
		*
		* Registering Service:
		*   -> IRpcLifecycle->RegisterLocalService
		*   {
		*     -> IRpcLifecycle->GetDispatcher()->DeclareLocalService(ref)
		*     ---- NETWORK PROTOCOL (broadcast) ----
		*     -> IRpcLifecycle::DeclareRemoteService(ref)
		*   }
		*/
		class IRpcLifecycle
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcLifecycle>
		{
		public:
			virtual void							Finalize() = 0;
			virtual void							Initialize() = 0;
			virtual vint							GetClientId() = 0;
			virtual IRpcDispatcher*					GetDispatcher() = 0;
			virtual IRpcController*					GetController() = 0;
			virtual IRpcSerializer*					GetSerializer() = 0;
			virtual const RpcLocalServiceMap&		GetRegisteredLocalServices() = 0;
			virtual Ptr<reflection::IDescriptable>	RefToPtr(RpcObjectReference ref) = 0;
			virtual RpcObjectReference				PtrToRef(Ptr<reflection::IDescriptable> obj) = 0;
			virtual void							LocalObjectHold(RpcObjectReference ref, vint remoteClientId) = 0;
			virtual void							LocalObjectUnhold(RpcObjectReference ref, vint remoteClientId) = 0;
			virtual void							RegisterLocalService(vint typeId, Ptr<reflection::IDescriptable> service) = 0;
			virtual void							DeclareRemoteService(RpcObjectReference ref) = 0;
			virtual vint							GetTypeIdFromName(WString typeName) = 0;
			virtual Ptr<reflection::IDescriptable>	RequestService(WString typeName) = 0;
		};

		class IRpcWrapperBase
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcWrapperBase>
		{
		public:
			virtual void							DisconnectFromLifecycle() = 0;
		};

/***********************************************************************
* Helpers
***********************************************************************/

		extern RpcObjectReference					RpcBoxByref(Ptr<reflection::IDescriptable> trivial, IRpcLifecycle* lc);
		extern Ptr<reflection::IDescriptable>		RpcUnboxByref(RpcObjectReference serializable, IRpcLifecycle* lc);
		extern reflection::description::Value		RpcCopyByval(const reflection::description::Value& trivial, IRpcLifecycle* lc);
		extern reflection::description::Value		RpcBoxByval(Ptr<reflection::IDescriptable> trivial, IRpcLifecycle* lc);
		extern reflection::description::Value		RpcBoxByval(const reflection::description::Value& trivial, IRpcLifecycle* lc);
		extern Ptr<reflection::IDescriptable>		RpcUnboxByval(const reflection::description::Value& serializable, IRpcLifecycle* lc);
		extern void									ReadMethodException(const reflection::description::Value& value);
		extern void									ReadEventException(RpcEventExceptionMap exceptions);
	}
}

#endif


/***********************************************************************
.\RPC\WFLIBRARYRPCCONTROLLER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::RPC

Interfaces:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_RPC_CONTROLLER
#define VCZH_WORKFLOW_LIBRARY_RPC_CONTROLLER


namespace vl
{
	namespace rpc_controller
	{
		struct RpcEventSuppressionKey
		{
			RpcObjectReference					ref;
			vint								eventId = 0;

			auto operator<=>(const RpcEventSuppressionKey&) const = default;
		};

		class RpcControllerDefault : public Object, public IRpcController
		{
		protected:
			Ptr<IRpcObjectOps>										objectCallback;
			Ptr<IRpcObjectEventOps>									eventCallback;
			collections::Dictionary<RpcEventSuppressionKey, vint>	eventSuppressedFlags;
			collections::Dictionary<RpcObjectReference, vint>		itemChangedSuppressedFlags;

			template<typename TKey>
			static void												SetSuppressedFlag(collections::Dictionary<TKey, vint>& flags, const TKey& key, bool suppressed);

			template<typename TKey>
			static bool												GetSuppressedFlag(const collections::Dictionary<TKey, vint>& flags, const TKey& key);

		public:

			RpcControllerDefault();
			~RpcControllerDefault();

			void													Register(Ptr<IRpcObjectOps> objectCallback, Ptr<IRpcObjectEventOps> eventCallback);

			// IRpcController

			IRpcObjectOps*											GetObjectOps()override;
			IRpcObjectEventOps*										GetObjectEventOps()override;

			void													Finalize()override;
			void													SetEventSuppressedFlag(RpcObjectReference ref, vint eventId, bool suppressed)override;
			bool													GetEventSuppressedFlag(RpcObjectReference ref, vint eventId)override;
			void													SetItemChangedSuppressedFlag(RpcObjectReference ref, bool suppressed)override;
			bool													GetItemChangedSuppressedFlag(RpcObjectReference ref)override;
		};
	}
}

#endif


/***********************************************************************
.\RPC\WFLIBRARYRPCLIFECYCLE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::RPC

Lifecycle:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_RPC_LIFECYCLE
#define VCZH_WORKFLOW_LIBRARY_RPC_LIFECYCLE


namespace vl
{
	namespace rpc_controller
	{
		class IRpcSerializer;
		class RpcLifecycleBase;

		class RpcLocalObjectTracker : public Object
		{
			friend class RpcLifecycleBase;
		private:
			RpcLifecycleBase*								lifecycle = nullptr;
			RpcObjectReference								ref;
		public:
			RpcLocalObjectTracker(RpcLifecycleBase* lc, RpcObjectReference r);
			~RpcLocalObjectTracker();
			void											Attach(RpcLifecycleBase* lc, RpcObjectReference r);
			void											Detach();
			RpcObjectReference								GetRef() const { return ref; }
			vint											GetClientId() const { return ref.clientId; }
			RpcLifecycleBase*								GetLifecycle() const { return lifecycle; }
			bool											IsTracked() const { return lifecycle != nullptr; }
		};

		class RpcWrapperTracker : public Object
		{
			friend class RpcLifecycleBase;
		private:
			RpcLifecycleBase*								lifecycle = nullptr;
			RpcObjectReference								ref;
		public:
			RpcWrapperTracker(RpcLifecycleBase* lc, RpcObjectReference r);
			~RpcWrapperTracker();
			void											Detach();
			RpcObjectReference								GetRef() const { return ref; }
			RpcLifecycleBase*								GetLifecycle() const { return lifecycle; }
		};

		struct RpcLocalObjectProperties : public Object
		{
			RpcObjectReference								ref;
			collections::SortedList<vint>					interestedClients;
			reflection::IDescriptable*						rawPtr = nullptr;
			Ptr<reflection::IDescriptable>					ownedPtr;
			Ptr<EventHandler>								eventHandler;
		};

		class RpcLifecycleBase : public Object, public IRpcLifecycle
		{
			friend class RpcLocalObjectTracker;
			friend class RpcWrapperTracker;
		public:
			using UniversalWrapperFactory = Func<Ptr<IRpcWrapperBase>(RpcObjectReference, IRpcLifecycle*)>;
		private:
			struct RpcWrapperProperties
			{
				reflection::DescriptableObject*				root = nullptr;
				IRpcWrapperBase*							proxy = nullptr;
			};
			using LocalProperties = collections::Dictionary<vint, Ptr<RpcLocalObjectProperties>>;
			using WrapperProperties = collections::Dictionary<RpcObjectReference, RpcWrapperProperties>;
		private:
			RpcControllerDefault							controller;
			vint											clientId = RpcClientId_Invalid;
			vint											nextObjectId = RpcObjectId_Invalid;
			bool											initialized = false;
			LocalProperties									localObjectProperties;
			RpcLocalServiceMap								registeredLocalServices;
			collections::Dictionary<vint, RpcObjectReference>	registeredRemoteServices;
			static WString									InternalProperty_LocalObjectTracker;
			static WString									InternalProperty_WrapperTracker;
			UniversalWrapperFactory							universalWrapperFactory;
			WrapperProperties								wrapperProperties;

			void											TrackWrapper(reflection::DescriptableObject* root, IRpcWrapperBase* proxy, RpcObjectReference ref);
			void											UntrackWrapper(RpcObjectReference ref);
			bool											TryGetTrackedWrapperRef(reflection::DescriptableObject* obj, RpcObjectReference& ref)const;
			IRpcWrapperBase*								GetTrackedWrapper(RpcObjectReference ref)const;
			void											TrackLocalObject(RpcObjectReference ref, reflection::IDescriptable* obj);
			RpcObjectReference								CreateLocalObject(Ptr<reflection::IDescriptable> obj, RpcObjectReference ref);
			void											UntrackLocalObject(RpcObjectReference ref, bool clearInternalProperty);
			void											RemoveLocalObject(RpcObjectReference ref, bool clearInternalProperty);
			bool											IsTracked(vint objectId)const;
			Ptr<reflection::IDescriptable>					CreateCallerProxy(RpcObjectReference ref, IRpcSerializer* serializer);
			void											DisconnectWrappersForFinalize();
		protected:
			collections::Dictionary<WString, vint>			idMap;
			Ptr<IRpcSerializer>								serializer;

			virtual vint									DecideTypeId(reflection::IDescriptable* obj)const;
			virtual void									AttachLocalObjectEvents(RpcObjectReference ref, reflection::IDescriptable* obj) = 0;
		public:
			RpcLifecycleBase(vint _clientId);
			~RpcLifecycleBase();

			void											SetIdMap(const collections::Dictionary<WString, vint>& _idMap);
			void											RegisterWrapperFactory(UniversalWrapperFactory factory);
			void											SetSerializer(Ptr<IRpcSerializer> _serializer);
			IRpcSerializer*									GetSerializer() override;

			// IRpcLifecycle

			void											Finalize()override;
			void											Initialize()override;
			vint											GetClientId()override;
			RpcControllerDefault*							GetController()override;
			const RpcLocalServiceMap&						GetRegisteredLocalServices()override;
			void											LocalObjectHold(RpcObjectReference ref, vint remoteClientId)override;
			void											LocalObjectUnhold(RpcObjectReference ref, vint remoteClientId)override;
			void											RegisterLocalService(vint typeId, Ptr<reflection::IDescriptable> service)override;
			void											DeclareRemoteService(RpcObjectReference ref)override;
			vint											GetTypeIdFromName(WString typeName)override;
			Ptr<reflection::IDescriptable>					RequestService(WString typeName)override;
			Ptr<reflection::IDescriptable>					RefToPtr(RpcObjectReference ref)override;
			Ptr<reflection::IDescriptable>					RefToPtr(RpcObjectReference ref, IRpcSerializer* serializer);
			RpcObjectReference								PtrToRef(Ptr<reflection::IDescriptable> obj)override;
		};
	}
}

#endif


/***********************************************************************
.\RPC\WFLIBRARYRPCWRAPPERS.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::RPC

Collection Wrappers:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_RPC_WRAPPERS
#define VCZH_WORKFLOW_LIBRARY_RPC_WRAPPERS


namespace vl
{
	namespace rpc_controller
	{

/***********************************************************************
* Collection Caller Wrappers
***********************************************************************/

		class RpcByrefEnumerator : public Object, public reflection::Description<RpcByrefEnumerator>, public reflection::description::IValueEnumerator, public virtual IRpcWrapperBase
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;
			RpcObjectReference								ref;
			vint											index = -1;
		public:
			RpcByrefEnumerator(IRpcLifecycle* lc, RpcObjectReference enumeratorRef, IRpcSerializer* _serializer);
			~RpcByrefEnumerator();

			void											DisconnectFromLifecycle()override;
			reflection::description::Value					GetCurrent()override;
			vint											GetIndex()override;
			bool											Next()override;
		};

		class RpcByrefEnumerable : public Object, public reflection::Description<RpcByrefEnumerable>, public reflection::description::IValueEnumerable, public virtual IRpcWrapperBase
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;
			RpcObjectReference								ref;
		public:
			RpcByrefEnumerable(IRpcLifecycle* lc, RpcObjectReference enumerableRef, IRpcSerializer* _serializer);
			~RpcByrefEnumerable();

			void											DisconnectFromLifecycle()override;
			Ptr<reflection::description::IValueEnumerator>	CreateEnumerator()override;
		};

		class RpcByrefReadonlyList : public Object, public reflection::Description<RpcByrefReadonlyList>, public virtual reflection::description::IValueReadonlyList, public virtual IRpcWrapperBase
		{
		protected:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;
			RpcObjectReference								ref;
		public:
			RpcByrefReadonlyList(IRpcLifecycle* lc, RpcObjectReference listRef, IRpcSerializer* _serializer);
			~RpcByrefReadonlyList();

			void											DisconnectFromLifecycle()override;
			Ptr<reflection::description::IValueEnumerator>	CreateEnumerator()override;
			vint											GetCount()override;
			reflection::description::Value					Get(vint index)override;
			bool											Contains(const reflection::description::Value& value)override;
			vint											IndexOf(const reflection::description::Value& value)override;
		};

		class RpcByrefList : public RpcByrefReadonlyList, public reflection::Description<RpcByrefList>, public virtual reflection::description::IValueList
		{
		public:
			RpcByrefList(IRpcLifecycle* lc, RpcObjectReference listRef, IRpcSerializer* _serializer);
			~RpcByrefList()override;

			Ptr<reflection::description::IValueEnumerator>	CreateEnumerator()override;
			vint											GetCount()override;
			reflection::description::Value					Get(vint index)override;
			bool											Contains(const reflection::description::Value& value)override;
			vint											IndexOf(const reflection::description::Value& value)override;
			void											Set(vint index, const reflection::description::Value& value)override;
			vint											Add(const reflection::description::Value& value)override;
			vint											Insert(vint index, const reflection::description::Value& value)override;
			bool											Remove(const reflection::description::Value& value)override;
			bool											RemoveAt(vint index)override;
			void											Clear()override;
		};

		class RpcByrefArray : public Object, public reflection::Description<RpcByrefArray>, public reflection::description::IValueArray, public virtual IRpcWrapperBase
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;
			RpcObjectReference								ref;
		public:
			RpcByrefArray(IRpcLifecycle* lc, RpcObjectReference arrayRef, IRpcSerializer* _serializer);
			~RpcByrefArray();

			void											DisconnectFromLifecycle()override;
			Ptr<reflection::description::IValueEnumerator>	CreateEnumerator()override;
			vint											GetCount()override;
			reflection::description::Value					Get(vint index)override;
			bool											Contains(const reflection::description::Value& value)override;
			vint											IndexOf(const reflection::description::Value& value)override;
			void											Set(vint index, const reflection::description::Value& value)override;
			void											Resize(vint size)override;
		};

		class RpcByrefObservableList : public Object, public reflection::Description<RpcByrefObservableList>, public reflection::description::IValueObservableList, public virtual IRpcWrapperBase
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;
			RpcObjectReference								ref;
		public:
			RpcByrefObservableList(IRpcLifecycle* lc, RpcObjectReference listRef, IRpcSerializer* _serializer);
			~RpcByrefObservableList();

			void											DisconnectFromLifecycle()override;
			Ptr<reflection::description::IValueEnumerator>	CreateEnumerator()override;
			vint											GetCount()override;
			reflection::description::Value					Get(vint index)override;
			bool											Contains(const reflection::description::Value& value)override;
			vint											IndexOf(const reflection::description::Value& value)override;
			void											Set(vint index, const reflection::description::Value& value)override;
			vint											Add(const reflection::description::Value& value)override;
			vint											Insert(vint index, const reflection::description::Value& value)override;
			bool											Remove(const reflection::description::Value& value)override;
			bool											RemoveAt(vint index)override;
			void											Clear()override;
		};

		class RpcByrefDictionary : public Object, public reflection::Description<RpcByrefDictionary>, public reflection::description::IValueDictionary, public virtual IRpcWrapperBase
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;
			RpcObjectReference								ref;
		public:
			RpcByrefDictionary(IRpcLifecycle* lc, RpcObjectReference dictRef, IRpcSerializer* _serializer);
			~RpcByrefDictionary();

			void												DisconnectFromLifecycle()override;
			Ptr<reflection::description::IValueReadonlyList>	GetKeys()override;
			Ptr<reflection::description::IValueReadonlyList>	GetValues()override;
			vint												GetCount()override;
			reflection::description::Value						Get(const reflection::description::Value& key)override;
			void												Set(const reflection::description::Value& key, const reflection::description::Value& value)override;
			bool												Remove(const reflection::description::Value& key)override;
			void												Clear()override;
		};
		
/***********************************************************************
* Collection Callee Wrappers
***********************************************************************/

		class RpcCalleeListOps : public Object, public IRpcListOps
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;

		public:
			RpcCalleeListOps(IRpcLifecycle* lc, IRpcSerializer* _serializer);

			RpcObjectReference								EnumCreate(RpcObjectReference ref)override;
			bool											EnumNext(RpcObjectReference enumerator)override;
			reflection::description::Value					EnumGetCurrent(RpcObjectReference enumerator)override;

			vint											ListGetCount(RpcObjectReference ref)override;
			reflection::description::Value					ListGet(RpcObjectReference ref, vint index)override;
			void											ListSet(RpcObjectReference ref, vint index, const reflection::description::Value& value)override;
			vint											ListAdd(RpcObjectReference ref, const reflection::description::Value& value)override;
			vint											ListInsert(RpcObjectReference ref, vint index, const reflection::description::Value& value)override;
			bool											ListRemoveAt(RpcObjectReference ref, vint index)override;
			void											ListClear(RpcObjectReference ref)override;
			bool											ListContains(RpcObjectReference ref, const reflection::description::Value& value)override;
			vint											ListIndexOf(RpcObjectReference ref, const reflection::description::Value& value)override;
			void											ArrayResize(RpcObjectReference ref, vint size)override;

			vint											DictGetCount(RpcObjectReference ref)override;
			reflection::description::Value					DictGet(RpcObjectReference ref, const reflection::description::Value& key)override;
			void											DictSet(RpcObjectReference ref, const reflection::description::Value& key, const reflection::description::Value& value)override;
			bool											DictRemove(RpcObjectReference ref, const reflection::description::Value& key)override;
			void											DictClear(RpcObjectReference ref)override;
			bool											DictContainsKey(RpcObjectReference ref, const reflection::description::Value& key)override;
			RpcObjectReference								DictGetKeys(RpcObjectReference ref)override;
			RpcObjectReference								DictGetValues(RpcObjectReference ref)override;
		};

		class RpcCalleeListEventOps : public Object, public IRpcListEventOps
		{
		private:
			IRpcLifecycle*									lifecycle = nullptr;
			IRpcSerializer*									serializer = nullptr;

		public:
			RpcCalleeListEventOps(IRpcLifecycle* lc, IRpcSerializer* _serializer);

			reflection::description::Value					OnItemChanged(RpcObjectReference ref, vint index, vint oldCount, vint newCount)override;
		};

		class RpcCalleeObjectOpsForList : public Object, public IRpcObjectOps
		{
		private:
			Ptr<RpcCalleeListOps>							listOps;
			Ptr<IRpcObjectOps>								objectOps;
			IRpcSerializer*									serializer = nullptr;

		public:
			RpcCalleeObjectOpsForList(Ptr<RpcCalleeListOps> _listOps, Ptr<IRpcObjectOps> _objectOps, IRpcSerializer* _serializer);

			reflection::description::Value					InvokeMethod(RpcObjectReference ref, vint methodId, Ptr<reflection::description::IValueArray> arguments)override;
			void											EndInvokeMethod(vint slot)override;
			void											ObjectHold(RpcObjectReference ref, vint remoteClientId, bool hold)override;
		};

		class RpcCalleeObjectEventOpsForList : public Object, public IRpcObjectEventOps
		{
		private:
			Ptr<RpcCalleeListEventOps>						listEventOps;
			Ptr<IRpcObjectEventOps>							objectEventOps;
			IRpcSerializer*									serializer = nullptr;

		public:
			RpcCalleeObjectEventOpsForList(Ptr<RpcCalleeListEventOps> _listEventOps, Ptr<IRpcObjectEventOps> _objectEventOps, IRpcSerializer* _serializer);

			reflection::description::Value					InvokeEvent(RpcObjectReference ref, vint eventId, Ptr<reflection::description::IValueArray> arguments)override;
		};

		class RpcCallerListOps : public Object, public IRpcListOps
		{
		private:
			IRpcObjectOps*									objectOps = nullptr;
			IRpcSerializer*									serializer = nullptr;

		public:
			RpcCallerListOps(IRpcObjectOps* _objectOps, IRpcSerializer* _serializer);

			RpcObjectReference								EnumCreate(RpcObjectReference ref)override;
			bool											EnumNext(RpcObjectReference enumerator)override;
			reflection::description::Value					EnumGetCurrent(RpcObjectReference enumerator)override;

			vint											ListGetCount(RpcObjectReference ref)override;
			reflection::description::Value					ListGet(RpcObjectReference ref, vint index)override;
			void											ListSet(RpcObjectReference ref, vint index, const reflection::description::Value& value)override;
			vint											ListAdd(RpcObjectReference ref, const reflection::description::Value& value)override;
			vint											ListInsert(RpcObjectReference ref, vint index, const reflection::description::Value& value)override;
			bool											ListRemoveAt(RpcObjectReference ref, vint index)override;
			void											ListClear(RpcObjectReference ref)override;
			bool											ListContains(RpcObjectReference ref, const reflection::description::Value& value)override;
			vint											ListIndexOf(RpcObjectReference ref, const reflection::description::Value& value)override;
			void											ArrayResize(RpcObjectReference ref, vint size)override;

			vint											DictGetCount(RpcObjectReference ref)override;
			reflection::description::Value					DictGet(RpcObjectReference ref, const reflection::description::Value& key)override;
			void											DictSet(RpcObjectReference ref, const reflection::description::Value& key, const reflection::description::Value& value)override;
			bool											DictRemove(RpcObjectReference ref, const reflection::description::Value& key)override;
			void											DictClear(RpcObjectReference ref)override;
			bool											DictContainsKey(RpcObjectReference ref, const reflection::description::Value& key)override;
			RpcObjectReference								DictGetKeys(RpcObjectReference ref)override;
			RpcObjectReference								DictGetValues(RpcObjectReference ref)override;
		};

		class RpcCallerListEventOps : public Object, public IRpcListEventOps
		{
		private:
			IRpcObjectEventOps*								objectEventOps = nullptr;
			IRpcSerializer*									serializer = nullptr;

		public:
			RpcCallerListEventOps(IRpcObjectEventOps* _objectEventOps, IRpcSerializer* _serializer);

			reflection::description::Value					OnItemChanged(RpcObjectReference ref, vint index, vint oldCount, vint newCount)override;
		};
	}
}

#endif


/***********************************************************************
.\RPCJSON\WFLIBRARYRPCJSON.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::RPC

JSON Helpers:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON
#define VCZH_WORKFLOW_LIBRARY_RPC_JSON


namespace vl
{
	namespace rpc_controller
	{
		class RpcCalleeListOps;
		class RpcCalleeListEventOps;
		class RpcCalleeObjectOpsForList;
		class RpcCalleeObjectEventOpsForList;

		using RpcJsonSerializeCallback = Func<Ptr<glr::json::JsonNode>(const reflection::description::Value&)>;
		using RpcJsonDeserializeCallback = Func<reflection::description::Value(Ptr<glr::json::JsonNode>)>;

		extern Ptr<glr::json::JsonNode>				JsonSerializePredefinedTypes(const reflection::description::Value& value, const RpcJsonSerializeCallback& rpcjson_Serialize);
		extern reflection::description::Value		JsonDeserializePredefinedTypes(const reflection::description::Value& value, const RpcJsonDeserializeCallback& rpcjson_Deserialize);

		class IRpcJsonMessageDispatcher
			: public virtual reflection::IDescriptable
			, public reflection::Description<IRpcJsonMessageDispatcher>
		{
		public:
			enum class RequestType
			{
				Direct,
				Broadcast,
				BroadcastAndDrop,
			};

			virtual vint							AllocateRequestId() = 0;
			virtual Ptr<glr::json::JsonNode>		OnJsonRequest(Ptr<glr::json::JsonNode> message, RequestType requestType) = 0;

			static Ptr<glr::json::JsonNode>			DefaultTranslate(
														Ptr<glr::json::JsonNode> message,
														RequestType requestType,
														IRpcObjectOps* objectOps,
														IRpcObjectEventOps* objectEventOps,
														IRpcDispatcher* dispatcher,
														IRpcLifecycle* lifecycle
														);
		};

		class RpcJsonObjectOps : public Object, public IRpcObjectOps
		{
		private:
			vint									sourceClientId = RpcClientId_Invalid;
			vint									targetClientId = RpcClientId_Invalid;
			IRpcJsonMessageDispatcher*				dispatcher = nullptr;

		public:
			RpcJsonObjectOps(IRpcJsonMessageDispatcher* _dispatcher);
			RpcJsonObjectOps(vint _sourceClientId, vint _targetClientId, IRpcJsonMessageDispatcher* _dispatcher);
			~RpcJsonObjectOps();

			reflection::description::Value			InvokeMethod(RpcObjectReference ref, vint methodId, Ptr<reflection::description::IValueArray> arguments)override;
			void									EndInvokeMethod(vint slot)override;
			void									ObjectHold(RpcObjectReference ref, vint remoteClientId, bool hold)override;

			static Ptr<glr::json::JsonNode>			Translate(Ptr<glr::json::JsonNode> message, IRpcObjectOps* ops, IRpcLifecycle* lifecycle = nullptr);
		};

		class RpcJsonObjectEventOps : public Object, public IRpcObjectEventOps
		{
		private:
			vint									sourceClientId = RpcClientId_Invalid;
			IRpcJsonMessageDispatcher*				dispatcher = nullptr;

		public:
			RpcJsonObjectEventOps(IRpcJsonMessageDispatcher* _dispatcher);
			RpcJsonObjectEventOps(vint _sourceClientId, IRpcJsonMessageDispatcher* _dispatcher);
			~RpcJsonObjectEventOps();

			reflection::description::Value			InvokeEvent(RpcObjectReference ref, vint eventId, Ptr<reflection::description::IValueArray> arguments)override;

			static Ptr<glr::json::JsonNode>			Translate(Ptr<glr::json::JsonNode> message, IRpcObjectEventOps* ops, IRpcLifecycle* lifecycle = nullptr);
		};

		class RpcJsonDispatcher : public Object, public IRpcDispatcher
		{
		private:
			vint									sourceClientId = RpcClientId_Invalid;
			IRpcJsonMessageDispatcher*				dispatcher = nullptr;
			Ptr<RpcJsonObjectEventOps>				objectEventOps;
			collections::Dictionary<vint, Ptr<RpcJsonObjectOps>> objectOps;

		public:
			RpcJsonDispatcher(vint _sourceClientId, IRpcJsonMessageDispatcher* _dispatcher);

			void									Finalize()override;
			void									Initialize()override;
			void									DeclareLocalService(RpcObjectReference ref)override;
			IRpcObjectEventOps*						BroadcastFromClient_ObjectEventOps(vint selfClientId)override;
			IRpcObjectOps*							SendToClient_ObjectOps(vint targetClientId)override;

			static Ptr<glr::json::JsonNode>			Translate(Ptr<glr::json::JsonNode> message, IRpcDispatcher* dispatcher, IRpcLifecycle* lifecycle);
		};

		class RpcJsonLifecycle : public RpcLifecycleBase
		{
		private:
			RpcJsonDispatcher*						dispatcher = nullptr;
			Func<vint(reflection::IDescriptable*)>	getTypeId;
			Func<void(RpcObjectReference, reflection::IDescriptable*)> eventAttacher;
			Ptr<RpcCalleeListOps>					listOps;
			Ptr<RpcCalleeListEventOps>				listEventOps;
			Ptr<RpcCalleeObjectOpsForList>			objectOpsForList;
			Ptr<RpcCalleeObjectEventOpsForList>		objectEventOpsForList;

		protected:
			vint									DecideTypeId(reflection::IDescriptable* obj)const override;
			void									AttachLocalObjectEvents(RpcObjectReference ref, reflection::IDescriptable* obj)override;

		public:
			RpcJsonLifecycle(vint _clientId, RpcJsonDispatcher* _dispatcher);

			void									Register(
														Ptr<IRpcSerializer> _serializer,
														Ptr<IRpcObjectOps> _objectOps,
														Ptr<IRpcObjectEventOps> _objectEventOps,
														Func<vint(reflection::IDescriptable*)> _getTypeId,
														Func<void(RpcObjectReference, reflection::IDescriptable*)> _eventAttacher
														);
			IRpcSerializer*							GetSerializer()override;
			IRpcDispatcher*							GetDispatcher()override;
		};

		extern vint									ReadRequestId(Ptr<glr::json::JsonNode> message);
		extern void									WriteRequestId(Ptr<glr::json::JsonNode> message, vint requestId);
	}
}

#endif


/***********************************************************************
.\WFLIBRARYREFLECTION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection

Interfaces:
***********************************************************************/

#ifndef VCZH_WORKFLOW_LIBRARY_REFLECTION
#define VCZH_WORKFLOW_LIBRARY_REFLECTION


namespace vl
{
	namespace reflection
	{
		namespace description
		{

/***********************************************************************
Predefined Types
***********************************************************************/

#ifndef VCZH_DEBUG_NO_REFLECTION

#define WORKFLOW_LIBRARY_ATTRIBUTE_TYPES(F)\
			F(vl::__vwsn::att_cpp_File)\
			F(vl::__vwsn::att_cpp_UserImpl)\
			F(vl::__vwsn::att_cpp_Private)\
			F(vl::__vwsn::att_cpp_Protected)\
			F(vl::__vwsn::att_cpp_Friend)\
			F(vl::__vwsn::att_rpc_Interface)\
			F(vl::__vwsn::att_rpc_Ctor)\
			F(vl::__vwsn::att_rpc_Byval)\
			F(vl::__vwsn::att_rpc_Byref)\
			F(vl::__vwsn::att_rpc_Cached)\
			F(vl::__vwsn::att_rpc_Dynamic)\
			F(vl::__vwsn::att_rpc_IdString)\
			F(vl::__vwsn::att_rpc_IdNumber)\

#define WORKFLOW_LIBRARY_TYPES(F)\
			F(Sys)							\
			F(Math)							\
			F(Localization)					\
			F(CoroutineStatus)				\
			F(CoroutineResult)				\
			F(ICoroutine)					\
			F(EnumerableCoroutine::IImpl)	\
			F(EnumerableCoroutine)			\
			F(AsyncStatus)					\
			F(AsyncContext)					\
			F(IAsync)						\
			F(IPromise)						\
			F(IFuture)						\
			F(IAsyncScheduler)				\
			F(AsyncCoroutine::IImpl)		\
			F(AsyncCoroutine)				\
			F(StateMachine)					\
			F(Versioning)					\
			F(vl::rpc_controller::RpcObjectReference)\
			F(vl::rpc_controller::RpcException)\
			F(vl::rpc_controller::RpcByvalReturnValue)\
			F(vl::rpc_controller::IRpcSerializer)\
			F(vl::rpc_controller::IRpcJsonMessageDispatcher::RequestType)\
			F(vl::rpc_controller::IRpcJsonMessageDispatcher)\
			F(vl::rpc_controller::IRpcListOps)\
			F(vl::rpc_controller::IRpcListEventOps)\
			F(vl::rpc_controller::IRpcObjectOps)\
			F(vl::rpc_controller::IRpcObjectEventOps)\
			F(vl::rpc_controller::IRpcOperations)\
			F(vl::rpc_controller::IRpcDispatcher)\
			F(vl::rpc_controller::IRpcController)\
			F(vl::rpc_controller::IRpcLifecycle)\
			F(vl::rpc_controller::IRpcWrapperBase)\
			F(vl::rpc_controller::RpcByrefEnumerator)\
			F(vl::rpc_controller::RpcByrefEnumerable)\
			F(vl::rpc_controller::RpcByrefReadonlyList)\
			F(vl::rpc_controller::RpcByrefList)\
			F(vl::rpc_controller::RpcByrefArray)\
			F(vl::rpc_controller::RpcByrefObservableList)\
			F(vl::rpc_controller::RpcByrefDictionary)\
			WORKFLOW_LIBRARY_ATTRIBUTE_TYPES(F)\

			WORKFLOW_LIBRARY_TYPES(DECL_TYPE_INFO)

#endif

/***********************************************************************
Interface Implementation Proxy (Implement)
***********************************************************************/

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

#pragma warning(push)
#pragma warning(disable:4250)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcSerializer)
				vl::reflection::description::Value Serialize(const vl::reflection::description::Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(Serialize, value);
				}

				vl::reflection::description::Value Deserialize(const vl::reflection::description::Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(Deserialize, value);
				}
			END_INTERFACE_PROXY(vl::rpc_controller::IRpcSerializer)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcJsonMessageDispatcher)
				vl::vint AllocateRequestId()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(AllocateRequestId);
				}

				vl::Ptr<vl::glr::json::JsonNode> OnJsonRequest(vl::Ptr<vl::glr::json::JsonNode> message, vl::rpc_controller::IRpcJsonMessageDispatcher::RequestType requestType)override
				{
					INVOKEGET_INTERFACE_PROXY(OnJsonRequest, message, requestType);
				}
			END_INTERFACE_PROXY(vl::rpc_controller::IRpcJsonMessageDispatcher)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcListOps)
				vl::rpc_controller::RpcObjectReference EnumCreate(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKEGET_INTERFACE_PROXY(EnumCreate, ref);
				}

				bool EnumNext(vl::rpc_controller::RpcObjectReference enumerator)override
				{
					INVOKEGET_INTERFACE_PROXY(EnumNext, enumerator);
				}

				vl::reflection::description::Value EnumGetCurrent(vl::rpc_controller::RpcObjectReference enumerator)override
				{
					INVOKEGET_INTERFACE_PROXY(EnumGetCurrent, enumerator);
				}

				vl::vint ListGetCount(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKEGET_INTERFACE_PROXY(ListGetCount, ref);
				}

				vl::reflection::description::Value ListGet(vl::rpc_controller::RpcObjectReference ref, vl::vint index)override
				{
					INVOKEGET_INTERFACE_PROXY(ListGet, ref, index);
				}

				void ListSet(vl::rpc_controller::RpcObjectReference ref, vl::vint index, const vl::reflection::description::Value& value)override
				{
					INVOKE_INTERFACE_PROXY(ListSet, ref, index, value);
				}

				vl::vint ListAdd(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(ListAdd, ref, value);
				}

				vl::vint ListInsert(vl::rpc_controller::RpcObjectReference ref, vl::vint index, const vl::reflection::description::Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(ListInsert, ref, index, value);
				}

				bool ListRemoveAt(vl::rpc_controller::RpcObjectReference ref, vl::vint index)override
				{
					INVOKEGET_INTERFACE_PROXY(ListRemoveAt, ref, index);
				}

				void ListClear(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKE_INTERFACE_PROXY(ListClear, ref);
				}

				bool ListContains(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(ListContains, ref, value);
				}

				vl::vint ListIndexOf(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(ListIndexOf, ref, value);
				}

				void ArrayResize(vl::rpc_controller::RpcObjectReference ref, vl::vint size)override
				{
					INVOKE_INTERFACE_PROXY(ArrayResize, ref, size);
				}

				vl::vint DictGetCount(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKEGET_INTERFACE_PROXY(DictGetCount, ref);
				}

				vl::reflection::description::Value DictGet(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key)override
				{
					INVOKEGET_INTERFACE_PROXY(DictGet, ref, key);
				}

				void DictSet(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key, const vl::reflection::description::Value& value)override
				{
					INVOKE_INTERFACE_PROXY(DictSet, ref, key, value);
				}

				bool DictRemove(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key)override
				{
					INVOKEGET_INTERFACE_PROXY(DictRemove, ref, key);
				}

				void DictClear(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKE_INTERFACE_PROXY(DictClear, ref);
				}

				bool DictContainsKey(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key)override
				{
					INVOKEGET_INTERFACE_PROXY(DictContainsKey, ref, key);
				}

				vl::rpc_controller::RpcObjectReference DictGetKeys(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKEGET_INTERFACE_PROXY(DictGetKeys, ref);
				}

				vl::rpc_controller::RpcObjectReference DictGetValues(vl::rpc_controller::RpcObjectReference ref)override
				{
					INVOKEGET_INTERFACE_PROXY(DictGetValues, ref);
				}
			END_INTERFACE_PROXY(vl::rpc_controller::IRpcListOps)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcObjectOps)
				vl::reflection::description::Value InvokeMethod(vl::rpc_controller::RpcObjectReference ref, vl::vint methodId, vl::Ptr<vl::reflection::description::IValueArray> arguments)override
				{
					INVOKEGET_INTERFACE_PROXY(InvokeMethod, ref, methodId, arguments);
				}

				void EndInvokeMethod(vl::vint slot)override
				{
					INVOKE_INTERFACE_PROXY(EndInvokeMethod, slot);
				}

				void ObjectHold(vl::rpc_controller::RpcObjectReference ref, vl::vint remoteClientId, bool hold)override
				{
					INVOKE_INTERFACE_PROXY(ObjectHold, ref, remoteClientId, hold);
				}

			END_INTERFACE_PROXY(vl::rpc_controller::IRpcObjectOps)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcListEventOps)
				vl::reflection::description::Value OnItemChanged(vl::rpc_controller::RpcObjectReference ref, vl::vint index, vl::vint oldCount, vl::vint newCount)override
				{
					INVOKEGET_INTERFACE_PROXY(OnItemChanged, ref, index, oldCount, newCount);
				}
			END_INTERFACE_PROXY(vl::rpc_controller::IRpcListEventOps)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcObjectEventOps)
				vl::reflection::description::Value InvokeEvent(vl::rpc_controller::RpcObjectReference ref, vl::vint eventId, vl::Ptr<vl::reflection::description::IValueArray> arguments)override
				{
					INVOKEGET_INTERFACE_PROXY(InvokeEvent, ref, eventId, arguments);
				}
			END_INTERFACE_PROXY(vl::rpc_controller::IRpcObjectEventOps)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcWrapperBase)
				void DisconnectFromLifecycle()override
				{
					INVOKE_INTERFACE_PROXY_NOPARAMS(DisconnectFromLifecycle);
				}
			END_INTERFACE_PROXY(vl::rpc_controller::IRpcWrapperBase)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(ICoroutine)

				void Resume(bool raiseException, Ptr<CoroutineResult> output)override
				{
					INVOKE_INTERFACE_PROXY(Resume, raiseException, output);
				}

				Ptr<IValueException> GetFailure()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetFailure);
				}

				CoroutineStatus GetStatus()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetStatus);
				}
			END_INTERFACE_PROXY(ICoroutine)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IAsync)

				AsyncStatus GetStatus()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetStatus);
				}

				bool Execute(const Func<void(Ptr<CoroutineResult>)>& callback, Ptr<AsyncContext> context)override
				{
					INVOKEGET_INTERFACE_PROXY(Execute, callback, context);
				}
			END_INTERFACE_PROXY(IAsync)

#pragma warning(pop)

#endif

/***********************************************************************
LoadPredefinedTypes
***********************************************************************/

			extern bool										WfLoadLibraryTypes();
		}
	}
}

#endif


/***********************************************************************
.\RPCJSON\WFLIBRARYRPCJSONDISPATCHERSHARED.H
***********************************************************************/
#ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SHARED
#define VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SHARED


namespace vl::rpc_controller::channeling
{
	using JsonPackage				= vl::Ptr<vl::glr::json::JsonNode>;
	using JsonChannel				= vl::inter_process::IChannel<JsonPackage>;
	using JsonChannelClient			= vl::inter_process::IChannelClient<JsonPackage>;
	using JsonChannelServer			= vl::inter_process::IChannelServer<JsonPackage>;
	using JsonNetworkChannelClient	= vl::inter_process::NetworkProtocolChannelClient<JsonPackage, vl::glr::json::JsonNodeListSerializer>;
	using JsonLocalChannelClient	= vl::inter_process::NetworkProtocolLocalChannelClient<JsonPackage, vl::glr::json::JsonNodeListSerializer>;
	template<typename TServerBase>
	using JsonNetworkChannelServer	= vl::inter_process::NetworkProtocolChannelServer<JsonPackage, vl::glr::json::JsonNodeListSerializer, TServerBase>;
	using TaskQueue					= vl::TaskQueue;
}

#endif


/***********************************************************************
.\RPCJSON\WFLIBRARYRPCJSONDISPATCHERCLIENT.H
***********************************************************************/
#ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_CLIENT
#define VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_CLIENT


namespace vl::rpc_controller::channeling
{
	/// <summary>
	/// A IChannelReader for hosting and connecting RPC services
	/// </summary>
	class RpcJsonDispatcherClient
		: public vl::Object
		, public virtual vl::rpc_controller::IRpcJsonMessageDispatcher
		, public virtual vl::inter_process::IChannelReader<JsonPackage>
	{
	protected:
		using RequestType = vl::rpc_controller::IRpcJsonMessageDispatcher::RequestType;

	private:
		struct ReceivedJsonMessage
		{
			vl::vint									senderClientId = -1;
			JsonPackage									message;
		};

		JsonChannel*									rpcChannel = nullptr;
		vl::atomic_vint									nextRequestId = 0;
		vl::atomic_vint									activeJsonRequests = 0;
		vl::atomic_vint									initialized = 0;
		vl::atomic_vint									serverLocalClientId = -1;
		vl::Ptr<vl::rpc_controller::RpcJsonDispatcher>	rpcDispatcher;
		vl::Ptr<vl::rpc_controller::RpcJsonLifecycle>	lifecycle;

		// covers messages and bufferedResponses
		vl::SpinLock									lockMessages;
		vl::Semaphore									semaphoreMessages;
		vl::collections::List<ReceivedJsonMessage>		messages;
		vl::collections::List<ReceivedJsonMessage>		bufferedResponses;

		// covers cachedIncomingServiceDeclarations and cachedOutgoingServiceDeclarations
		vl::SpinLock									lockServiceDeclarations;
		vl::collections::List<JsonPackage>				cachedIncomingServiceDeclarations;
		vl::collections::List<JsonPackage>				cachedOutgoingServiceDeclarations;

		// covers waitingForServices
		vl::SpinLock									lockWaitingForServices;
		vl::collections::List<vl::WString>				waitingForServices;
		vl::EventObject									eventWaitingForServices;
		bool											eventWaitingForServicesCreated = false;
		vl::EventObject									eventServerLocalClientId;

		void											PrepareConnection(JsonChannel* channel, const vl::collections::List<vl::WString>& _waitingForServices);
		void											ProcessCachedIncomingServiceDeclarations();
		void											SendCachedOutgoingServiceDeclarations();
		void											ProcessIncomingServiceDeclaration(JsonPackage request);
		void											UpdateWaitingForServices(JsonPackage request);
		void											WaitForServerClientId();
		void											WaitForExpectedServices();
		void											SendJsonRequest(JsonPackage message, RequestType requestType);
		void											PushReceivedMessage(vl::vint senderClientId, JsonPackage message);
		ReceivedJsonMessage								PopReceivedMessage();
		bool											TryPopBufferedResponse(vl::vint requestId, ReceivedJsonMessage& message);
		void											PushBufferedResponse(ReceivedJsonMessage message);
		void											SendJsonResponse(vl::vint receiverClientId, JsonPackage response);
		void											FlushChannel();
		void											ProcessRequestAndSendResponse(vl::vint senderClientId, JsonPackage request);
		JsonPackage										TranslateRequest(JsonPackage request);

	protected:
		virtual void									ScheduleTask(vl::Func<void()> task) = 0;
		void											SetRpcObjects(vl::Ptr<vl::rpc_controller::RpcJsonDispatcher> _rpcDispatcher, vl::Ptr<vl::rpc_controller::RpcJsonLifecycle> _lifecycle);
		vl::rpc_controller::RpcJsonLifecycle*			GetRpcJsonLifecycle();

	public:
		RpcJsonDispatcherClient();

		void											WaitForServer(JsonChannelClient* channelClient, JsonChannel* channel, const vl::collections::List<vl::WString>& _waitingForServices);
		vl::vint										ConnectLocalServer(JsonChannelServer* channelServer, vl::Ptr<JsonChannelClient> localClient, JsonChannel* channel, const vl::collections::List<vl::WString>& _waitingForServices);
		void											Initialize();
		vl::rpc_controller::IRpcLifecycle*				GetRpcLifecycle();
		vl::rpc_controller::IRpcDispatcher*				GetRpcDispatcher();
		void											SetServerLocalClientId(vl::vint clientId);
		void											NotifyServerClientDisconnected();

		vl::vint										AllocateRequestId() override;
		JsonPackage										OnJsonRequest(JsonPackage message, RequestType requestType) override;
		void											OnRead(vl::vint senderClientId, const JsonPackage& package) override;

		virtual void									FinalizeRpc();
	};

	class RpcJsonDispatcherClientForTaskQueue : public RpcJsonDispatcherClient
	{
	private:
		vl::Ptr<TaskQueue>								taskQueue;

	protected:
		void											ScheduleTask(vl::Func<void()> task) override;

	public:
		RpcJsonDispatcherClientForTaskQueue(vl::Ptr<TaskQueue> _taskQueue);
	};
}

#endif


/***********************************************************************
.\RPCJSON\WFLIBRARYRPCJSONDISPATCHERSERVER.H
***********************************************************************/
#ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SERVER
#define VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SERVER


namespace vl::rpc_controller::channeling
{
	/// <summary>
	/// A IChannelReader for RPC service delivering and request broadcasting
	/// </summary>
	class RpcJsonDispatcherServer
		: public vl::Object
		, public virtual vl::inter_process::IChannelReader<JsonPackage>
	{
	public:
		struct PendingBroadcast : public vl::Object
		{
			vl::vint											originalClientId = -1;
			vl::vint											originalRequestId = -1;
			vl::vint											redirectedRequestId = -1;
			bool												hasNonNullResponse = false;
			vl::collections::List<vl::vint>						expectedClientIds;
			vl::collections::Dictionary<vl::vint, JsonPackage>	responses;
		};

		struct CompletedBroadcast
		{
			vl::vint											originalClientId = -1;
			JsonPackage											response;
		};

	private:
		JsonChannel*														rpcChannel = nullptr;
		JsonChannelClient*													serverClient = nullptr;
		vl::atomic_vint														nextRequestId = 0;

		// covers connectedClientIds, pendingBroadcasts, redirectedBroadcasts and cachedServiceDeclarations
		vl::SpinLock														lockBroadcasts;
		vl::collections::SortedList<vl::vint>								connectedClientIds;
		vl::collections::Dictionary<vl::WString, vl::Ptr<PendingBroadcast>>	pendingBroadcasts;
		vl::collections::Dictionary<vl::vint, vl::WString>					redirectedBroadcasts;
		vl::collections::List<JsonPackage>									cachedServiceDeclarations;

		vl::vint										AllocateRequestId();
		vl::WString										MakeBroadcastKey(vl::vint clientId, vl::vint requestId);
		JsonPackage										CreateBroadcastResponse(vl::vint sourceClientId, vl::vint targetClientId, vl::vint requestId, vl::Ptr<PendingBroadcast> pending);
		CompletedBroadcast								CompleteBroadcastLocked(const vl::WString& key);
		void											DeliverCompletedBroadcast(const CompletedBroadcast& completed);
		JsonPackage										StartBroadcast(vl::vint originalClientId, vl::vint originalRequestId, JsonPackage message);
		void											StartBroadcastAndDrop(vl::vint originalClientId, JsonPackage message);
		bool											TryHandleBroadcastResponse(vl::vint senderClientId, JsonPackage response);
		void											HandleServiceDeclaration(vl::vint senderClientId, JsonPackage request);
		void											SendLoginMessages(vl::vint clientId);
		void											SendJsonResponse(vl::vint receiverClientId, JsonPackage response);
		void											FlushChannel();

	protected:
		virtual void									ScheduleTask(vl::Func<void()> task) = 0;

	public:
		RpcJsonDispatcherServer(JsonChannelClient* _serverClient, JsonChannel* channel);

		bool											HasServerClientId();
		void											RegisterClient(vl::vint clientId);
		void											DisconnectClient(vl::vint clientId);
		vl::vint										GetServerClientId();
		void											OnRead(vl::vint senderClientId, const JsonPackage& package) override;
	};

	class RpcJsonDispatcherServerForTaskQueue : public RpcJsonDispatcherServer
	{
	private:
		vl::Ptr<TaskQueue>								taskQueue;

	protected:
		void											ScheduleTask(vl::Func<void()> task) override;

	public:
		RpcJsonDispatcherServerForTaskQueue(JsonChannelClient* _serverClient, JsonChannel* channel, vl::Ptr<TaskQueue> _taskQueue);
	};
}

#endif

