diff options
author | Jordi Mas i Hernandez <jordi@mono-cvs.ximian.com> | 2006-09-01 23:58:48 +0400 |
---|---|---|
committer | Jordi Mas i Hernandez <jordi@mono-cvs.ximian.com> | 2006-09-01 23:58:48 +0400 |
commit | fe5f3f78b87e003da314aaeba821dfe2fd84827a (patch) | |
tree | 9ead0b682195cb2e805181c337407f5993e57ca2 | |
parent | db3f43858c94de6414d6d57276d8b6a18c2fa3a3 (diff) |
Initial work on System.Workflow.Runtime
svn path=/trunk/mcs/; revision=64741
40 files changed, 3418 insertions, 0 deletions
diff --git a/mcs/class/System.Workflow.Runtime/Assembly/AssemblyInfo.cs b/mcs/class/System.Workflow.Runtime/Assembly/AssemblyInfo.cs new file mode 100644 index 00000000000..89b22456c58 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Assembly/AssemblyInfo.cs @@ -0,0 +1,65 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// Authors: +// +// Andreas Nahr (ClassDevelopment@A-SoftTech.com) +// Jordi Mas i Hernandez <jordimash@gmail.com> +// + + +using System; +using System.Reflection; +using System.Resources; +using System.Security; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + + +[assembly: AssemblyVersion ("3.0.0.0")] +[assembly: SatelliteContractVersion ("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")]
+[assembly: CompilationRelaxations (8)] + + +[assembly: AssemblyTitle("System.Workflow.Runtime.dll")] +[assembly: AssemblyDescription("System.Workflow.Runtime.dll")] +[assembly: AssemblyCompany("MONO development team")] +[assembly: AssemblyProduct("MONO CLI")] +[assembly: AssemblyCopyright("(c) 2006 Various Authors")] + +#if !TARGET_JVM +[assembly: CLSCompliant(true)] +#endif +[assembly: AssemblyDefaultAlias("System.Windows.Runtime.dll")] +[assembly: AssemblyInformationalVersion("0.0.0.1")] +[assembly: NeutralResourcesLanguage("en-US")] + +[assembly: ComCompatibleVersion (1, 0, 3300, 0)] +[assembly: ComVisible(false)] +[assembly: AllowPartiallyTrustedCallers] + +#if TARGET_JVM +[assembly: AssemblyDelaySign(false)] +#else +[assembly: AssemblyDelaySign(true)] +[assembly: AssemblyKeyFile("../msfinal3.pub")] +#endif + diff --git a/mcs/class/System.Workflow.Runtime/Assembly/ChangeLog b/mcs/class/System.Workflow.Runtime/Assembly/ChangeLog new file mode 100644 index 00000000000..e5d29422895 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Assembly/ChangeLog @@ -0,0 +1,4 @@ +2006-09-02 Jordi Mas i Hernandez <jordimash@gmail.com> + + * Initial check-in + diff --git a/mcs/class/System.Workflow.Runtime/ChangeLog b/mcs/class/System.Workflow.Runtime/ChangeLog new file mode 100644 index 00000000000..e5d29422895 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/ChangeLog @@ -0,0 +1,4 @@ +2006-09-02 Jordi Mas i Hernandez <jordimash@gmail.com> + + * Initial check-in + diff --git a/mcs/class/System.Workflow.Runtime/Makefile b/mcs/class/System.Workflow.Runtime/Makefile new file mode 100644 index 00000000000..5f0e7cda214 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Makefile @@ -0,0 +1,20 @@ +thisdir = class/System.Workflow.Runtime +include ../../build/rules.make +SUBDIRS = + +LIBRARY = System.Workflow.Runtime.dll + +LIBRARY_USE_INTERMEDIATE_FILE = yes + +# this c:/tmp no /cygdrive/tmp /r:/tmp/System.Workflow.ComponentModel.dll +LIB_MCS_FLAGS = /r:$(corlib) /r:System.dll /r:System.Workflow.ComponentModel.dll /r:System.Workflow.Activities /r:System.Xml /r:System.Transactions.dll +TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) + +include ../../build/library.make + + + + + + + diff --git a/mcs/class/System.Workflow.Runtime/README b/mcs/class/System.Workflow.Runtime/README new file mode 100644 index 00000000000..a96f4418ce7 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/README @@ -0,0 +1,39 @@ +Welcome to Windows Workflow Foundation Mono implementation + +* Introduction + +Windows Workflow Foundation (WWF) has been introduced as part of Microsoft .Net 3.0 framework (also called WinFX). It is a namespace and a set of tools designed +for building workflow enabled applications on .Net. + +The WWF is implemented using three assemblies: System.Workflow.Activities, System.Workflow.ComponentModel and System.Workflow.Runtime. + +* Status + +This library is in pre-alpha state. Development is still in the very early stages. Bug reports are welcome, provided they don't just point out missing +classes. Please use http://bugzilla.ximian.com/. + +* Contributions + +Some indications when contributing to this namespace: + +- Contributions providing only stubs are not useful at this point. Our goal is to have a consistent and complete working implementation. New classes, enumerator +or interfaces should be defined as they are need it as progress is made in the implementation. + +- For every new class or behavior added to a class provide a clear test case to verify its functionality and it to the test case suite for the assembly. + +- Before committing a change or propose a patch please verify that it does not break any existing test case for any of the three assemblies used to implement +WWF. + +- Check the 'CodingStyle' file at mcs/CodingStyle + +* Install + +In order to install WWF you should compile the assemblies using 'make PROFILE=net_2_0 install' in the following order: + +- System.Workflow.ComponentModel +- System.Workflow.Activities +- System.Workflow.Runtime +- System.Workflow.ComponentModel (twice, due to cyclic dependencies) + +At System.Workflow.Runtime/Samples you have some examples to demonstrate some basic functionality. + diff --git a/mcs/class/System.Workflow.Runtime/Samples/ChangeLog b/mcs/class/System.Workflow.Runtime/Samples/ChangeLog new file mode 100644 index 00000000000..e5d29422895 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Samples/ChangeLog @@ -0,0 +1,4 @@ +2006-09-02 Jordi Mas i Hernandez <jordimash@gmail.com> + + * Initial check-in + diff --git a/mcs/class/System.Workflow.Runtime/Samples/SchedulerMonitor.cs b/mcs/class/System.Workflow.Runtime/Samples/SchedulerMonitor.cs new file mode 100644 index 00000000000..ea9a4d0c382 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Samples/SchedulerMonitor.cs @@ -0,0 +1,324 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// +// +// This sample should be executed on MS .Net runtime. +// It helps to understand how the MS. Net runtime workflow +// executor works internally, how interacts with the sheduler service +// and so on +// + +using System; +using System.ComponentModel; +using System.Collections.ObjectModel; +using System.Collections; +using System.Workflow.Activities; +using System.Workflow.Runtime; +using System.Workflow.ComponentModel; +using System.Workflow.Runtime.Hosting; +using System.Threading; +using System.Workflow.ComponentModel.Compiler; +using System.ComponentModel.Design; + +class Program +{ + public class ourDefaultWorkflowSchedulerService : DefaultWorkflowSchedulerService + { + public ourDefaultWorkflowSchedulerService () + { + + } + + protected override void OnStarted () + { + base.OnStarted (); + Console.WriteLine ("*** ourDefaultWorkflowSchedulerService::ourDefaultWorkflowSchedulerService.OnStarted", + Environment.StackTrace); + } + + protected override void Schedule (WaitCallback callback, Guid workflowInstanceId) + { + Console.WriteLine ("*** ourDefaultWorkflowSchedulerService::Schedule {0} {1}", + callback, workflowInstanceId); + + base.Schedule (callback, workflowInstanceId); + } + + protected override void Schedule(WaitCallback callback, Guid workflowInstanceId, DateTime whenUtc, Guid timerId) + { + Console.WriteLine ("*** ourDefaultWorkflowSchedulerService::Schedule {0} {1} {2}", + callback, workflowInstanceId, whenUtc); + + base.Schedule (callback, workflowInstanceId, whenUtc, timerId); + } + + protected override void Stop () + { + Console.WriteLine ("*** ourDefaultWorkflowSchedulerService::Stop"); + base.Stop (); + } + } + + public class ourCodeActivity : Activity + { + public ourCodeActivity () + { + + } + + public event EventHandler ExecuteCode; + + protected override void Initialize (IServiceProvider provider) + { + Console.WriteLine ("***ourCodeActivity.IServiceProvider {0}", + Environment.StackTrace); + + + } + + protected sealed override ActivityExecutionStatus Execute (ActivityExecutionContext executionContext) + { + ActivityExecutionStatus status; + ActivityExecutionContextManager manager = executionContext.ExecutionContextManager; + ReadOnlyCollection <ActivityExecutionContext> contexts = manager.ExecutionContexts; + + Console.WriteLine ("***ourCodeActivity.Execute {0}", contexts.Count); + + IComparable queue_name = "our_queue"; + + WorkflowQueuingService qService = executionContext.GetService<WorkflowQueuingService> ();
+
+ if (!qService.Exists (queue_name)) { + Console.WriteLine ("CreatingQue");
+ qService.CreateWorkflowQueue (queue_name, true);
+ }
+ + status = base.Execute (executionContext); + return status; + } + } + + public sealed class SequentialWorkflow : SequentialWorkflowActivity + { + private ourCodeActivity CodeCloseMailProgram2; + private DelayActivity DelayWaitForSentMail2; + private CodeActivity PrepareMail2; + private CodeActivity CodeCloseMailProgram1; + private DelayActivity DelayWaitForSentMail1; + private CodeActivity CodePrepareMail1; + private SequenceActivity SeqSendMail2; + private SequenceActivity SeqSendMail1; + private ParallelActivity Parallel; + private IfElseBranchActivity IfElseBranchActivityNoNeed; + private IfElseBranchActivity IfElseBranchActivityNeedToSendMail; + private TerminateActivity TerminateFinishNoNeedToReadMail; + private IfElseActivity NeedToSendMail; + + public SequentialWorkflow () + { + InitializeComponent (); + } + + private void InitializeComponent () + { + + CanModifyActivities = true; + CodeCondition codecondition1 = new CodeCondition (); + CodeCloseMailProgram2 = new ourCodeActivity (); + DelayWaitForSentMail2 = new DelayActivity (); + PrepareMail2 = new CodeActivity (); + CodeCloseMailProgram1 = new CodeActivity (); + DelayWaitForSentMail1 = new DelayActivity (); + CodePrepareMail1 = new CodeActivity (); + SeqSendMail2 = new SequenceActivity (); + SeqSendMail1 = new SequenceActivity (); + TerminateFinishNoNeedToReadMail = new TerminateActivity (); + Parallel = new ParallelActivity (); + IfElseBranchActivityNoNeed = new IfElseBranchActivity (); + IfElseBranchActivityNeedToSendMail = new IfElseBranchActivity (); + NeedToSendMail = new IfElseActivity (); + + CodeCloseMailProgram2.Name = "CodeCloseMailProgram2"; + CodeCloseMailProgram2.ExecuteCode += new EventHandler (CodeCloseMailProgram2_ExecuteCode); + + DelayWaitForSentMail2.Name = "DelayWaitForSentMail2"; + DelayWaitForSentMail2.TimeoutDuration = System.TimeSpan.Parse ("00:00:05"); + DelayWaitForSentMail2.InitializeTimeoutDuration += new EventHandler (DelayWaitForSentMail2_InitializeTimeoutDuration); + + PrepareMail2.Name = "PrepareMail2"; + PrepareMail2.ExecuteCode += new EventHandler (PrepareMail2_ExecuteCode); + + CodeCloseMailProgram1.Name = "CodeCloseMailProgram1"; + CodeCloseMailProgram1.ExecuteCode += new EventHandler (CodeCloseMailProgram_ExecuteCode); + + DelayWaitForSentMail1.Name = "DelayWaitForSentMail1"; + DelayWaitForSentMail1.TimeoutDuration = System.TimeSpan.Parse ("00:00:03"); + DelayWaitForSentMail1.InitializeTimeoutDuration += new EventHandler (DelayWaitForSentMail1_InitializeTimeoutDuration); + + CodePrepareMail1.Name = "CodePrepareMail1"; + CodePrepareMail1.ExecuteCode += new EventHandler (CodeActivity1_ExecuteCode); + + SeqSendMail2.Activities.Add (PrepareMail2); + SeqSendMail2.Activities.Add (DelayWaitForSentMail2); + SeqSendMail2.Activities.Add (CodeCloseMailProgram2); + SeqSendMail2.Name = "SeqSendMail2"; + + SeqSendMail1.Activities.Add (CodePrepareMail1); + //SeqSendMail1.Activities.Add (DelayWaitForSentMail1); + SeqSendMail1.Activities.Add (CodeCloseMailProgram1); + SeqSendMail1.Name = "SeqSendMail1"; + + TerminateFinishNoNeedToReadMail.Name = "TerminateFinishNoNeedToReadMail"; + + Parallel.Activities.Add (SeqSendMail1); + Parallel.Activities.Add (SeqSendMail2); + Parallel.Name = "Parallel"; + + IfElseBranchActivityNoNeed.Activities.Add (TerminateFinishNoNeedToReadMail); + IfElseBranchActivityNoNeed.Name = "IfElseBranchActivityNoNeed"; + + IfElseBranchActivityNeedToSendMail.Activities.Add (Parallel); + codecondition1.Condition += new EventHandler <ConditionalEventArgs>(IfElseCondition); + IfElseBranchActivityNeedToSendMail.Condition = codecondition1; + IfElseBranchActivityNeedToSendMail.Name = "IfElseBranchActivityNeedToSendMail"; + + NeedToSendMail.Activities.Add (IfElseBranchActivityNeedToSendMail); + NeedToSendMail.Activities.Add (IfElseBranchActivityNoNeed); + NeedToSendMail.Name = "NeedToSendMail"; + + Activities.Add (NeedToSendMail); + Name = "IfElseParalellWorkFlow"; + CanModifyActivities = false; + + } + + + + // The event handler that executes on ExecuteCode event of the ApprovePO activity + private void ExecutingCode (object sender, EventArgs e) + { + //Console.WriteLine ("**Executing. {0}", Environment.StackTrace); + Console.WriteLine ("**Executing."); + } + + // The event handler that executes on ExecuteCode event of the ApprovePO activity + private void OnApproved(object sender, EventArgs e) + { + Console.WriteLine ("**Purchase Order Approved."); + } + + + // Code condition to evaluate whether to take the first branch, YesIfElseBranch + // Since it always returns true, the first branch is always taken. + private void IsCondition (object sender, ConditionalEventArgs e) + { + e.Result = true; + //e.Result = false; + Console.WriteLine ("**IsCondition called {0}", e.Result); + } + + + private void IfElseCondition (object sender, ConditionalEventArgs e) + { + Console.WriteLine ("IfElseCondition"); + e.Result = true; + } + + private void CodeActivity1_ExecuteCode (object sender, EventArgs e) + { + Console.WriteLine ("PrepareMail1_ExecuteCode"); + } + + private void DelayWaitForSentMail2_InitializeTimeoutDuration (object sender, EventArgs e) + { + Console.WriteLine ("DelayWaitForSentMail2_InitializeTimeoutDuration"); + } + + private void CodeCloseMailProgram_ExecuteCode (object sender, EventArgs e) + { + Console.WriteLine ("CodeCloseMailProgram1_ExecuteCode"); + } + + private void PrepareMail2_ExecuteCode (object sender, EventArgs e) + { + Console.WriteLine ("PrepareMail2_ExecuteCode"); + } + + private void CodeCloseMailProgram2_ExecuteCode (object sender, EventArgs e) + { + Console.WriteLine ("CodeCloseMailProgram2_ExecuteCode"); + } + + private void DelayWaitForSentMail1_InitializeTimeoutDuration (object sender, EventArgs e) + { + Console.WriteLine ("DelayWaitForSentMail1_InitializeTimeoutDuration"); + } + } + + static AutoResetEvent waitHandle = new AutoResetEvent(false); + + static void Main () + { + // Create the WorkflowRuntime + WorkflowRuntime workflowRuntime = new WorkflowRuntime (); + + workflowRuntime.AddService ((object) new ourDefaultWorkflowSchedulerService ()); + + workflowRuntime.StartRuntime (); + Type type = typeof (SequentialWorkflow); + + // Listen for the workflow events + workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; + workflowRuntime.WorkflowTerminated += OnWorkflowTerminated; + WorkflowInstance wi = workflowRuntime.CreateWorkflow (type); + wi.Start (); + + waitHandle.WaitOne (); + + // Stop the runtime + Console.WriteLine("Program Complete."); + //workflowRuntime.Dispose (); + } + + // This method will be called when a workflow instance is completed; since we have started only a single + // instance we are ignoring the event args and signaling the waitHandle so the main thread can continue + static void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs e) + { + + //Console.WriteLine ("-->{0}", Environment.StackTrace); + Console.WriteLine ("OnWorkflowCompleted"); + waitHandle.Set(); + } + + // This method is called when the workflow terminates and does not complete + // This should not occur in this sample; however, it is good practice to include a + // handler for this event so the host application can manage workflows that are + // unexpectedly terminated (e.g. unhandled workflow exception). + // waitHandle is set so the main thread can continue + static void OnWorkflowTerminated(object sender, WorkflowTerminatedEventArgs e) + { + Console.WriteLine(e.Exception.Message); + waitHandle.Set(); + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Samples/WorkflowQueues.cs b/mcs/class/System.Workflow.Runtime/Samples/WorkflowQueues.cs new file mode 100644 index 00000000000..2c12960759a --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Samples/WorkflowQueues.cs @@ -0,0 +1,180 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// +// +// This sample should be executed on MS .Net runtime. +// It helps to understand how the MS. Net runtime workflow +// executor works internally, how interacts with the sheduler service +// and so on +// + +using System; +using System.ComponentModel; +using System.Collections.ObjectModel; +using System.Collections; +using System.Workflow.Activities; +using System.Workflow.Runtime; +using System.Workflow.ComponentModel; +using System.Workflow.Runtime.Hosting; +using System.Threading; + + +class Program +{ + + public class ourCodeActivity : Activity + { + public WorkflowQueue workflowQueue; + + public ourCodeActivity () + { + + } + + public event EventHandler ExecuteCode; + + protected override void Initialize (IServiceProvider provider) + { + Console.WriteLine ("***ourCodeActivity.Initialize thread:{0}",
+ Thread.CurrentThread.ManagedThreadId); +
+ WorkflowQueuingService queuingService = (WorkflowQueuingService)provider.GetService (typeof(WorkflowQueuingService)); + + IComparable queue_name = "LaNostra_Queue"; + WorkflowQueuingService qService = (WorkflowQueuingService) provider.GetService (typeof (WorkflowQueuingService));
+
+ if (!qService.Exists (queue_name)) {
+ workflowQueue = qService.CreateWorkflowQueue (queue_name, true);
+ } + else + workflowQueue = qService.GetWorkflowQueue (queue_name); +
+ workflowQueue.QueueItemAvailable += OnQueueItemAvailable; + workflowQueue.QueueItemArrived += OnQueueItemArrived; + } + + protected sealed override ActivityExecutionStatus Execute (ActivityExecutionContext executionContext) + { + Console.WriteLine ("***ourCodeActivity.Execute thread:{0}",
+ Thread.CurrentThread.ManagedThreadId); + + ActivityExecutionStatus status; + //ActivityExecutionContextManager manager = executionContext.ExecutionContextManager; + //ReadOnlyCollection <ActivityExecutionContext> contexts = manager.ExecutionContexts; + + //Console.WriteLine ("***ourCodeActivity.Execute {0}", contexts.Count); + object data = workflowQueue.Peek (); + Console.WriteLine ("OnQueueItemAvailable! {0}", data); + + status = base.Execute (executionContext); + return status; + } + + public void OnQueueItemArrived (Object sender, QueueEventArgs args)
+ { + object data = this.workflowQueue.Peek (); + Console.WriteLine ("OnQueueItemArrived! event {0}", data); + } + + public void OnQueueItemAvailable (Object sender, QueueEventArgs args)
+ { + Console.WriteLine ("OnQueueItemAvailable!");
+ //ThreadMonitor.WriteToConsole (Thread.CurrentThread, "WaitForMessageActivity", + // "WaitForMessageActivity: Processed External Event");
+
+ object data = this.workflowQueue.Peek (); + Console.WriteLine ("OnQueueItemAvailable event! {0}", data);
+
+ ActivityExecutionContext context = sender as ActivityExecutionContext;
+ //context.CloseActivity ();
+ } + } + + public sealed class SequentialWorkflow : SequentialWorkflowActivity + { + private ourCodeActivity activity; + + public SequentialWorkflow () + { + InitializeComponent (); + } + + private void InitializeComponent () + { + CanModifyActivities = true; + activity = new ourCodeActivity (); + + activity.Name = "activity"; + activity.ExecuteCode += new EventHandler (activity_ExecuteCode); + + Activities.Add (activity); + CanModifyActivities = false; + } + + private void activity_ExecuteCode (object sender, EventArgs e) + { + Console.WriteLine ("activity_ExecuteCode"); + } + } + + static AutoResetEvent waitHandle = new AutoResetEvent(false); + + static void Main () + { + // Create the WorkflowRuntime + WorkflowRuntime workflowRuntime = new WorkflowRuntime (); + + Console.WriteLine ("App.Main thread:{0}", Thread.CurrentThread.ManagedThreadId); + + workflowRuntime.StartRuntime (); + Type type = typeof (SequentialWorkflow); + + // Listen for the workflow events + workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; + workflowRuntime.WorkflowTerminated += OnWorkflowTerminated; + WorkflowInstance wi = workflowRuntime.CreateWorkflow (type); + wi.Start (); + + Console.WriteLine ("Enquing data"); + wi.EnqueueItem ("LaNostra_Queue", "Hello", null, null); + + waitHandle.WaitOne (); + + // Stop the runtime + Console.WriteLine ("Program Complete."); + //workflowRuntime.Dispose (); + } + + static void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs e) + { + Console.WriteLine ("OnWorkflowCompleted"); + waitHandle.Set (); + } + + static void OnWorkflowTerminated(object sender, WorkflowTerminatedEventArgs e) + { + Console.WriteLine (e.Exception.Message); + waitHandle.Set (); + } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/ChangeLog b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/ChangeLog new file mode 100644 index 00000000000..e5d29422895 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/ChangeLog @@ -0,0 +1,4 @@ +2006-09-02 Jordi Mas i Hernandez <jordimash@gmail.com> + + * Initial check-in + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/DefaultWorkflowLoaderService.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/DefaultWorkflowLoaderService.cs new file mode 100644 index 00000000000..857617a5939 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/DefaultWorkflowLoaderService.cs @@ -0,0 +1,51 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + + +using System.Xml; +using System.Workflow.Activities; +using System.Workflow.ComponentModel; + +namespace System.Workflow.Runtime.Hosting +{ + public class DefaultWorkflowLoaderService : WorkflowLoaderService
+ {
+ public DefaultWorkflowLoaderService () + { + + } + + // Methods
+ protected internal override Activity CreateInstance (Type workflowType) + { + return (Activity) Activator.CreateInstance (workflowType); + } +
+ protected internal override Activity CreateInstance (XmlReader workflowDefinitionReader, XmlReader rulesReader) + { + throw new NotImplementedException (); + }
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/DefaultWorkflowSchedulerService.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/DefaultWorkflowSchedulerService.cs new file mode 100644 index 00000000000..21862601eb5 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/DefaultWorkflowSchedulerService.cs @@ -0,0 +1,60 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + + +using System.Xml; +using System.Threading; +using System.Workflow.Activities; +using System.Workflow.ComponentModel; + +namespace System.Workflow.Runtime.Hosting +{ + public class DefaultWorkflowSchedulerService : WorkflowSchedulerService
+ {
+ public DefaultWorkflowSchedulerService () + { + + } + + protected internal override void Cancel (Guid timerId) + { + + } +
+ protected internal override void Schedule (WaitCallback callback, Guid workflowInstanceId) + { + ThreadPool.QueueUserWorkItem (callback, workflowInstanceId); + } +
+ protected internal override void Schedule (WaitCallback callback, Guid workflowInstanceId, DateTime whenUtc, Guid timerId) + { + //WorkflowInstance wi = WorkflowRuntime.GetInstanceFromGuid (workflowInstanceId); + + //wi.TimerEventSubscriptionCollection.Add + // (new TimerEventSubscription (workflowInstanceId, timerId)); + } +
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowLoaderService.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowLoaderService.cs new file mode 100644 index 00000000000..b7124a51f08 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowLoaderService.cs @@ -0,0 +1,44 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System.Xml; +using System.Workflow.ComponentModel; +using System.Workflow.Activities; + +namespace System.Workflow.Runtime.Hosting +{ + public abstract class WorkflowLoaderService : WorkflowRuntimeService
+ { + protected WorkflowLoaderService () + { + + } +
+ // Methods
+ protected internal abstract Activity CreateInstance (Type workflowType); + protected internal abstract Activity CreateInstance (XmlReader workflowDefinitionReader, XmlReader rulesReader);
+
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowRuntimeService.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowRuntimeService.cs new file mode 100644 index 00000000000..b8d03d9d2ab --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowRuntimeService.cs @@ -0,0 +1,66 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +namespace System.Workflow.Runtime.Hosting +{ + public abstract class WorkflowRuntimeService
+ {
+ protected WorkflowRuntimeService () + { + + } + + // Methods
+ protected virtual void OnStarted () + { + + } +
+ protected virtual void OnStopped () + { + + } +
+ internal void RaiseExceptionNotHandledEvent (Exception exception, Guid instanceId) + { + + } +
+ protected void RaiseServicesExceptionNotHandledEvent (Exception exception, Guid instanceId) + { + + } +
+ protected internal virtual void Start () + { + + } +
+ protected internal virtual void Stop () + { + + }
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowRuntimeServiceState.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowRuntimeServiceState.cs new file mode 100644 index 00000000000..bdaabf6f75c --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowRuntimeServiceState.cs @@ -0,0 +1,35 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +namespace System.Workflow.Runtime.Hosting +{ + public enum WorkflowRuntimeServiceState
+ { + Stopped = 0, + Starting = 1,
+ Started = 2,
+ Stopping = 3
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowSchedulerService.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowSchedulerService.cs new file mode 100644 index 00000000000..254d05ff2ed --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Hosting/WorkflowSchedulerService.cs @@ -0,0 +1,46 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + + +using System.Xml; +using System.Workflow.Activities; +using System.Workflow.ComponentModel; +using System.Threading; + +namespace System.Workflow.Runtime.Hosting +{ + public abstract class WorkflowSchedulerService : WorkflowRuntimeService
+ { + protected WorkflowSchedulerService () + { + + } +
+ // Methods
+ protected internal abstract void Cancel (Guid timerId);
+ protected internal abstract void Schedule (WaitCallback callback, Guid workflowInstanceId);
+ protected internal abstract void Schedule (WaitCallback callback, Guid workflowInstanceId, DateTime whenUtc, Guid timerId);
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime.dll.sources b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime.dll.sources new file mode 100644 index 00000000000..911cb945da1 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime.dll.sources @@ -0,0 +1,21 @@ +Assembly/AssemblyInfo.cs +../../build/common/Consts.cs +../../build/common/Locale.cs +../../build/common/MonoTODOAttribute.cs +System.Workflow.Runtime/WorkflowQueuingService.cs +System.Workflow.Runtime/WorkflowQueue.cs +System.Workflow.Runtime/WorkflowRuntime.cs +System.Workflow.Runtime/WorkflowInstance.cs +System.Workflow.Hosting/WorkflowRuntimeService.cs +System.Workflow.Hosting/WorkflowRuntimeServiceState.cs +System.Workflow.Hosting/WorkflowLoaderService.cs +System.Workflow.Hosting/DefaultWorkflowLoaderService.cs +System.Workflow.Hosting/WorkflowSchedulerService.cs +System.Workflow.Hosting/DefaultWorkflowSchedulerService.cs +System.Workflow.Runtime/WorkflowTerminatedEventArgs.cs +System.Workflow.Runtime/WorkflowEventArgs.cs +System.Workflow.Runtime/WorkflowCompletedEventArgs.cs +System.Workflow.Runtime/TimerEventSubscription.cs +System.Workflow.Runtime/TimerEventSubscriptionCollection.cs +System.Workflow.Runtime/IPendingWork.cs +System.Workflow.Runtime/WorkflowProcessor.cs
\ No newline at end of file diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/ChangeLog b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/ChangeLog new file mode 100644 index 00000000000..e5d29422895 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/ChangeLog @@ -0,0 +1,4 @@ +2006-09-02 Jordi Mas i Hernandez <jordimash@gmail.com> + + * Initial check-in + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/IPendingWork.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/IPendingWork.cs new file mode 100644 index 00000000000..cfca5d21a07 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/IPendingWork.cs @@ -0,0 +1,39 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using System.Collections; +using System.Transactions;
+ +namespace System.Workflow.Runtime +{ + public interface IPendingWork + { + void Commit (Transaction transaction, ICollection items);
+ void Complete (bool succeeded, ICollection items);
+ bool MustCommit (ICollection items); + }
+ +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/TimerEventSubscription.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/TimerEventSubscription.cs new file mode 100644 index 00000000000..916d92fafc2 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/TimerEventSubscription.cs @@ -0,0 +1,76 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +namespace System.Workflow.Runtime +{ + [Serializable]
+ public class TimerEventSubscription
+ { + private Guid timerId; + private Guid workflowInstanceId; + private DateTime expiresAt; + private IComparable name;
+
+ protected TimerEventSubscription () + { + + } +
+ public TimerEventSubscription (Guid workflowInstanceId, DateTime expiresAt) : this () + { + this.workflowInstanceId = workflowInstanceId; + this.expiresAt = expiresAt; + this.timerId = Guid.NewGuid (); + this.name = timerId; + }
+ + public TimerEventSubscription (Guid timerId, Guid workflowInstanceId, DateTime expiresAt) : this () + { + this.timerId = timerId; + this.workflowInstanceId = workflowInstanceId; + this.expiresAt = expiresAt; + this.name = timerId; + }
+
+ // Properties
+ public virtual DateTime ExpiresAt { + get { return expiresAt; } + } +
+ public virtual IComparable QueueName { + get {return name; } + protected set {name = value; } + }
+
+ public virtual Guid SubscriptionId { + get { return timerId; } + } +
+ public virtual Guid WorkflowInstanceId { + get { return workflowInstanceId; } + }
+ } +} + + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/TimerEventSubscriptionCollection.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/TimerEventSubscriptionCollection.cs new file mode 100644 index 00000000000..e4dd413bb41 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/TimerEventSubscriptionCollection.cs @@ -0,0 +1,138 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Workflow.ComponentModel; + + +namespace System.Workflow.Runtime +{ + [Serializable]
+ public class TimerEventSubscriptionCollection : ICollection, IEnumerable
+ { + public static readonly DependencyProperty TimerCollectionProperty; + private ArrayList list; +
+ static TimerEventSubscriptionCollection () + { + + } + + // Constructor is private in MS Net + internal TimerEventSubscriptionCollection () + { + list = new ArrayList (); + } + + // Properties
+ public int Count { + get { return list.Count; } + }
+
+ bool ICollection.IsSynchronized { + get { return false; } + } + + object ICollection.SyncRoot { + get { return this; } + } + + // Private properties + internal TimerEventSubscription this [int index] { + get {return (TimerEventSubscription) list [index];} + } +
+ // Methods
+ public void Add (TimerEventSubscription item) + { + int range = list.Count; + int middle, cmp; + int left = 0; + int right = range-1; + + // Adds items always in a stored order + while (left <= right) { + + middle = (left + right) >> 1; + cmp = Comparer.Default.Compare (item.ExpiresAt, + ((TimerEventSubscription) list [middle]).ExpiresAt); + + if (cmp == 0) { + break; + } + + if (cmp > 0) { + left = middle + 1; + } + else { + right = middle - 1; + } + } + + list.Insert (left, item); + }
+ + public void CopyTo (Array array, int index) + { + list.CopyTo (array, index); + } +
+ public IEnumerator GetEnumerator () + { + return list.GetEnumerator (); + } +
+ public TimerEventSubscription Peek () + { + if (Count == 0) + return null; + + return (TimerEventSubscription) list[0]; + } +
+ public void Remove (Guid timerSubscriptionId) + { + TimerEventSubscription te; + + for (IEnumerator enumerator = GetEnumerator (); enumerator.MoveNext (); ) { + te = (TimerEventSubscription) enumerator.Current; + if (timerSubscriptionId == te.SubscriptionId) { + Remove (te); + return; + } + } + } +
+ public void Remove (TimerEventSubscription item) + { + list.Remove (item); + } +
+ } +} + + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowCompletedEventArgs.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowCompletedEventArgs.cs new file mode 100644 index 00000000000..8f95c4cf594 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowCompletedEventArgs.cs @@ -0,0 +1,52 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using System.Workflow.ComponentModel; + +namespace System.Workflow.Runtime +{ + public class WorkflowCompletedEventArgs : WorkflowEventArgs
+ { + private Activity activity; +
+ internal WorkflowCompletedEventArgs (WorkflowInstance workflow_instance, Activity activity) : + base (workflow_instance) + { + this.activity = activity; + }
+
+ // Properties
+ //public Dictionary <string, object> OutputParameters { + // get; + //}
+ + public Activity WorkflowDefinition { + get {return activity;} + }
+
+ } +} + + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowEventArgs.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowEventArgs.cs new file mode 100644 index 00000000000..e1bf60fa3b5 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowEventArgs.cs @@ -0,0 +1,45 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; + +namespace System.Workflow.Runtime +{ + public class WorkflowEventArgs : EventArgs
+ { + private WorkflowInstance workflow_instance; + + internal WorkflowEventArgs (WorkflowInstance workflow_instance) + { + this.workflow_instance = workflow_instance; + } + + // Properties + public WorkflowInstance WorkflowInstance { + get {return workflow_instance; } + }
+ } +} + + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowInstance.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowInstance.cs new file mode 100644 index 00000000000..dbd0dd8974b --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowInstance.cs @@ -0,0 +1,191 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using System.ComponentModel; +using System.Workflow.ComponentModel; +using System.Workflow.Runtime.Hosting; +using System.Threading; + +namespace System.Workflow.Runtime +{ + public sealed class WorkflowInstance
+ { + private Guid guid; + private WorkflowRuntime runtime; + private Activity root_activity; + private TimerEventSubscriptionCollection subscription_collection; + private WorkflowQueuingService queuing_service; + internal Timer timer_subscriptions; + + internal WorkflowInstance (Guid guid, WorkflowRuntime runtime, Activity root_activity) + { + this.guid = guid; + this.runtime = runtime; + this.root_activity = root_activity; + subscription_collection = new TimerEventSubscriptionCollection (); + queuing_service = new WorkflowQueuingService (); + } + + // Properties
+ public Guid InstanceId { + get { + return guid; + } + } +
+ public WorkflowRuntime WorkflowRuntime { + get { + return runtime; + } + } + + // TODO: This breaks .Net API signature compatibility + public TimerEventSubscriptionCollection TimerEventSubscriptionCollection { + get { + return subscription_collection; + } + } + + // TODO: This breaks .Net API signature compatibility + public WorkflowQueuingService WorkflowQueuingService { + get { + return queuing_service; + } + } + + // Methods
+ public void Abort () + { + timer_subscriptions.Dispose (); + } +
+ //public void ApplyWorkflowChanges (WorkflowChanges workflowChanges); +
+ public void EnqueueItem (IComparable queueName, object item, IPendingWork pendingWork, object workItem) + { + WorkflowQueue queue; + + // TODO: What to do with pendingWork and workItem? + if (queuing_service.Exists (queueName)) { + queue = queuing_service.GetWorkflowQueue (queueName); + } else { + queue = queuing_service.CreateWorkflowQueue (queueName, true); + } + + queue.Enqueue (item); + } +
+ public void EnqueueItemOnIdle (IComparable queueName, object item, IPendingWork pendingWork, object workItem) + { + + } +
+ public override bool Equals (object obj) + { + WorkflowInstance wi = (WorkflowInstance) obj; + + if (wi == null) { + return false; + } + + return wi.InstanceId.Equals (guid); + } +
+ public override int GetHashCode () + { + return guid.GetHashCode (); + } +
+ public Activity GetWorkflowDefinition () + { + return root_activity; + } +
+ public DateTime GetWorkflowNextTimerExpiration () + { + TimerEventSubscription timer; + timer = subscription_collection.Peek (); + + if (timer == null) { + return DateTime.MaxValue; + } + + return timer.ExpiresAt; + } +
+ /*public ReadOnlyCollection<WorkflowQueueInfo> GetWorkflowQueueData();*/
+ public void Load () + { + + } +
+ public void ReloadTrackingProfiles () + { + + } +
+ public void Resume () + { + + } +
+ public void Start () + { + WorkflowSchedulerService sheduler; + + // init all activities + ActivityExecutionContextManager manager = new ActivityExecutionContextManager (this); + ActivityExecutionContext context = manager.CreateExecutionContext (GetWorkflowDefinition ()); + + GetWorkflowDefinition ().InitializeInternal (context); + + sheduler = (WorkflowSchedulerService) runtime.GetService (typeof (WorkflowSchedulerService)); + //sheduler.Schedule (new WaitCallback (WorkflowProcessor.RunWorkflow), guid); + + WorkflowProcessor.RunWorkflow (guid); + } +
+ public void Suspend (string error) + { + + } +
+ public void Terminate (string error) + { + + } +
+ public bool TryUnload () + { + throw new NotImplementedException (); + } +
+ public void Unload () + { + + } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowProcessor.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowProcessor.cs new file mode 100644 index 00000000000..b15191067a9 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowProcessor.cs @@ -0,0 +1,239 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +//#define DEBUG_EXECUTIONLOOP + +using System; +using System.Threading; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Workflow.ComponentModel; +using System.Workflow.Runtime.Hosting; +using System.Workflow.Activities;
+ +namespace System.Workflow.Runtime +{ + internal class WorkflowProcessor
+ { + static WorkflowProcessor () + { + + } + + // Workflow processor + internal static void RunWorkflow (Object stateInfo) + { + Stack <Activity> stack = new Stack <Activity> (); + WorkflowInstance wi = WorkflowRuntime.GetInstanceFromGuid ((Guid)stateInfo); + wi.timer_subscriptions = new Timer (TimerSubscriptionsCallback, wi, 0, 1000); + Activity activity = wi.GetWorkflowDefinition (); + Activity next_activity; + ActivityExecutionContextManager manager = new ActivityExecutionContextManager (wi); + ActivityExecutionContext context; + List <DelayActivity> waiting = new List <DelayActivity> (); + bool wait = false; + StateMachineWorkflowActivity state_machine = null; + + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Initiating thread for activity {0}", wi.GetWorkflowDefinition ()); + #endif + context = manager.CreateExecutionContext (activity); + + // Main Workflow execution loop + while (activity != null) { + + next_activity = null; + if (activity.NeedsExecution) { + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("*** Executing {0}, parallel {1}", activity, activity.ParallelParent); + #endif + context.ExecuteActivity (activity); + } + + // If this a state machine changing its statge update StateMachineWorkflowActivity + if (state_machine != null && IsBasedOnType (activity, typeof (SetStateActivity))) { + state_machine.SetCurrentStateName (((SetStateActivity) activity).TargetStateName); + } + + + #if DEBUG_EXECUTIONLOOP + Console.WriteLine (" ActivitiesToExecute.Count {0}, stack {1}, waiting {2}", + activity.ActivitiesToExecute.Count, stack.Count, waiting.Count); + #endif + wait = false; + + // State machine workflow, first activity is InitialStateName + if (IsBasedOnType (activity, typeof (StateMachineWorkflowActivity))) { + state_machine = (StateMachineWorkflowActivity) activity; + stack.Push (activity.GetActivityByName (state_machine.InitialStateName)); + state_machine.SetCurrentStateName (state_machine.InitialStateName); + + #if DEBUG_EXECUTIONLOOP + Console.WriteLine (" StateMachineWorkflowActivity, pushing {0}", + activity.GetActivityByName (sm.InitialStateName)); + #endif + } + + // TODO: if (IsBasedOnType (current, typeof (CompositeActivity))) { + if (activity.GetType () == typeof (DelayActivity)) { + if (activity.ParallelParent == null) { + wi.WorkflowRuntime.OnWorkflowIdled (wi); + waiting.Add ((DelayActivity) activity); + wait = true; + } else { + // Continue from parent activities + // TODO: This can be moved to the Execute method + // of the paralell activity + if (activity.ParallelParent.ActivitiesToExecute.Count > 0) { + stack.Push (activity.ParallelParent); + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Pushing parent {0}", activity.ParallelParent); + #endif + waiting.Add ((DelayActivity) activity); + } else { // If not possible, wait for the delay + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Schedule Waiting"); + #endif + waiting.Add ((DelayActivity) activity); + wait = true; + } + } + } + + if (activity.NeedsExecution) { // ex. While + stack.Push (activity); + } + + if (activity.ActivitiesToExecute.Count == 0 && stack.Count == 0 && waiting.Count == 0) { + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Exiting..."); + #endif + break; + } + + // Does it have sub-activities to run? + // Delay is not composite, cannot have children activities + if (wait == false) { + if (activity.ActivitiesToExecute.Count > 0) { + next_activity = activity.ActivitiesToExecute.Dequeue (); + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Next Activity A {0}", next_activity); + #endif + if (activity.ActivitiesToExecute.Count > 0) { + stack.Push (activity); + } + } else { + if (stack.Count > 0) { + next_activity = stack.Pop (); + } + + if (next_activity != null && next_activity.NeedsExecution == false) { + if (next_activity.ActivitiesToExecute.Count > 0) { + next_activity = next_activity.ActivitiesToExecute.Dequeue (); + } + } + + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Next Activity B {0}", next_activity); + #endif + } + } + + if (next_activity == null) { + if (waiting.Count > 0) { + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Waiting for {0} handles...", waiting.Count); + #endif + wi.WorkflowRuntime.OnWorkflowIdled (wi); + DelayActivity.WaitEvent.WaitOne (); + } + } + + // Do we have delay activities no longer waiting? + foreach (DelayActivity delay in waiting) { + if (delay.Delayed == false) { + bool flag = false; + // Continue with the list of activities pending in the parent + next_activity = delay.Parent; + waiting.Remove (delay); + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Delayed Parent {0}", next_activity); + #endif + if (next_activity.ActivitiesToExecute.Count > 0) { + if (next_activity.ActivitiesToExecute.Count > 1) + flag = true; + + if (next_activity != null) { + next_activity = next_activity.ActivitiesToExecute.Dequeue (); + + if (flag == true) { + stack.Push (delay.Parent); + } + } + } + break; + } + } + + #if DEBUG_EXECUTIONLOOP + Console.WriteLine ("Next activity to process {0}", next_activity); + #endif + activity = next_activity; + } + wi.WorkflowRuntime.OnWorkflowCompleted (wi); + } + + // This is called by the timer to process the TimeEventSubcriptionCollection + static private void TimerSubscriptionsCallback (object state) + { + WorkflowInstance wi = (WorkflowInstance) state; + + if (wi.TimerEventSubscriptionCollection.Count == 0) { + return; + } + + if (wi.TimerEventSubscriptionCollection.Peek ().ExpiresAt > DateTime.UtcNow) { + return; + } + + TimerEventSubscription ti = wi.TimerEventSubscriptionCollection [0]; + // Event has arrived, send a message to the queue + wi.EnqueueItem (ti.QueueName, ti, null, null); + wi.TimerEventSubscriptionCollection.Remove (ti); + } + + static private bool IsBasedOnType (object obj, Type target) + { + for (Type type = obj.GetType (); type != null; type = type.BaseType) { + if (type == target) { + return true; + } + } + + return false; + } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowQueue.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowQueue.cs new file mode 100644 index 00000000000..dc6fe04c2bc --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowQueue.cs @@ -0,0 +1,109 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using System.ComponentModel; +using System.Collections.Generic; +using System.Workflow.ComponentModel; + +namespace System.Workflow.Runtime +{ + public sealed class WorkflowQueue
+ { + private Queue <object> queue; + private WorkflowQueuingService service; + private IComparable queue_name; + + internal WorkflowQueue (WorkflowQueuingService service, IComparable queue_name) + { + queue = new Queue <object> (); + this.service = service; + this.queue_name = queue_name; + } + + // Properties
+ public int Count { + get { return queue.Count; } + }
+ + //public bool Enabled { get; set; }
+ public IComparable QueueName { + get { return queue_name; } + } +
+ public WorkflowQueuingService QueuingService { + get {return service; } + } + + // Events + public event EventHandler <QueueEventArgs> QueueItemArrived; + public event EventHandler <QueueEventArgs> QueueItemAvailable; + + // Methods
+ public object Dequeue () + { + return queue.Dequeue (); + } +
+ public void Enqueue (object item) + { + queue.Enqueue (item); + + if (QueueItemArrived != null) { + QueueItemArrived (this, new QueueEventArgs (queue_name)); + } + }
+ + public object Peek () + { + return queue.Peek (); + } +
+ public void RegisterForQueueItemArrived (IActivityEventListener<QueueEventArgs> eventListener) + { + + } +
+ public void RegisterForQueueItemAvailable (IActivityEventListener<QueueEventArgs> eventListener) + { + + } +
+ public void RegisterForQueueItemAvailable (IActivityEventListener<QueueEventArgs> eventListener, string subscriberQualifiedName) + { + + } +
+ public void UnregisterForQueueItemArrived (IActivityEventListener<QueueEventArgs> eventListener) + { + + } +
+ public void UnregisterForQueueItemAvailable (IActivityEventListener<QueueEventArgs> eventListener) + { + + }
+ } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowQueuingService.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowQueuingService.cs new file mode 100644 index 00000000000..2f89d37e9de --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowQueuingService.cs @@ -0,0 +1,83 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using System.ComponentModel; +using System.Workflow.ComponentModel; +using System.Collections; +using System.Collections.Generic; +using System.Threading; + +namespace System.Workflow.Runtime +{ + public sealed class WorkflowQueuingService
+ { + private IDictionary <IComparable, WorkflowQueue> queues; + public static readonly DependencyProperty PendingMessagesProperty; + + static WorkflowQueuingService ()
+ {
+ PendingMessagesProperty = DependencyProperty.RegisterAttached ("PendingMessages", + typeof (Queue), typeof (WorkflowQueuingService), new PropertyMetadata ()); + } + + internal WorkflowQueuingService () + { + queues = new Dictionary <IComparable, WorkflowQueue> (); + } + + // Methods
+ public WorkflowQueue CreateWorkflowQueue (IComparable queueName, bool transactional) + { + WorkflowQueue queue; + + if (Exists (queueName)) { + throw new InvalidOperationException ("A queue with this name already exists."); + } + + queue = new WorkflowQueue (this, queueName); + queues.Add (queueName, queue); + + //Console.WriteLine ("CreateWorkflowQueue {0}", queueName); + return queue; + } +
+ public void DeleteWorkflowQueue (IComparable queueName) + { + queues.Remove (queueName); + } +
+ public bool Exists (IComparable queueName) + { + WorkflowQueue queue; + return queues.TryGetValue (queueName, out queue); + } +
+ public WorkflowQueue GetWorkflowQueue (IComparable queueName) + { + return queues [queueName]; + } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowRuntime.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowRuntime.cs new file mode 100644 index 00000000000..4519907011f --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowRuntime.cs @@ -0,0 +1,277 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Workflow.ComponentModel; +using System.Workflow.Runtime.Hosting; +using System.Xml;
+ +namespace System.Workflow.Runtime +{ + public sealed class WorkflowRuntime : IDisposable
+
+ { + private bool is_started; + private string name; + private List <object> services; + internal Dictionary <Guid, WorkflowInstance> instances; // for this runtime + private static List <WorkflowRuntime> runtimes; // all runtimes +
+ public WorkflowRuntime () + { + services = new List <object> (); + runtimes = new List <WorkflowRuntime> (); + instances = new Dictionary <Guid, WorkflowInstance> (); + is_started = false; + } +
+ public WorkflowRuntime (string configSectionName) : this () + { + + } +
+ /*public WorkflowRuntime (WorkflowRuntimeSection settings) {} */ + + // Events
+ //public event EventHandler<WorkflowRuntimeEventArgs> Started;
+ //public event EventHandler<WorkflowRuntimeEventArgs> Stopped;
+ public event EventHandler <WorkflowCompletedEventArgs> WorkflowCompleted;
+ public event EventHandler <WorkflowEventArgs> WorkflowCreated;
+ public event EventHandler <WorkflowEventArgs> WorkflowResumed;
+ public event EventHandler <WorkflowEventArgs> WorkflowStarted; + public event EventHandler <WorkflowTerminatedEventArgs> WorkflowTerminated; + public event EventHandler <WorkflowEventArgs> WorkflowIdled; + + // Properties + public bool IsStarted { + get { return is_started; } + } +
+ public string Name { + get { return name; } + set { name = value; } + }
+ + // Methods
+ public void AddService (object service_toadd) + { + foreach (object service in services) { + if (service == service_toadd) { + throw new InvalidOperationException ("Cannot add a service that already exists."); + } + } + + services.Add (service_toadd); + } +
+ public WorkflowInstance CreateWorkflow (Type workflowType) + { + return CreateWorkflow (workflowType, null, Guid.NewGuid ()); + } +
+ public WorkflowInstance CreateWorkflow (XmlReader workflowDefinitionReader) + { + throw new NotImplementedException (); + } +
+ public WorkflowInstance CreateWorkflow (Type workflowType, Dictionary <string, object> namedArgumentValues) + { + return CreateWorkflow (workflowType, namedArgumentValues, Guid.NewGuid ()); + } +
+ public WorkflowInstance CreateWorkflow (Type workflowType, Dictionary <string, object> namedArgumentValues, Guid instanceId) + { + WorkflowLoaderService loader; + Activity root_activity; + WorkflowInstance instance; + + if (is_started == false) { + StartRuntime (); + } + + loader = (WorkflowLoaderService) GetService (typeof (WorkflowLoaderService)); + root_activity = loader.CreateInstance (workflowType); + instance = new WorkflowInstance (instanceId, this, root_activity); + instances.Add (instanceId, instance); + + if (WorkflowStarted != null) { + WorkflowStarted (this, new WorkflowEventArgs (instance)); + } + + return instance; + } +
+ public WorkflowInstance CreateWorkflow (XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary <string, object> namedArgumentValues) + { + throw new NotImplementedException (); + } +
+ public WorkflowInstance CreateWorkflow (XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary <string, object> namedArgumentValues, Guid instanceId) + { + throw new NotImplementedException (); + } +
+ public void Dispose () + { + StopRuntime (); + } +
+ public ReadOnlyCollection <T> GetAllServices <T> () + { + List <T> services_req = new List <T> (); + + foreach (T service in services) { + // To determine if we have a service in the list we have to + // check the class and its base types + for (Type type = service.GetType (); type != null; type = type.BaseType) { + if (type == typeof (T)) { + services_req.Add (service); + } + } + } + + return new ReadOnlyCollection <T> (services_req); + } +
+ public ReadOnlyCollection <object> GetAllServices (Type serviceType) + { + List <object> services_req = new List <object> (); + + foreach (object service in services) { + + // To determine if we have a service in the list we have to + // check the class and its base types + for (Type type = service.GetType (); type != null; type = type.BaseType) { + if (type == serviceType) { + services_req.Add (service); + } + } + } + + return new ReadOnlyCollection <object> (services_req); + } + +
+ public ReadOnlyCollection <WorkflowInstance> GetLoadedWorkflows () + { + throw new NotImplementedException (); + } +
+ public T GetService <T> () + { + return (T) GetService (typeof (T)); + } +
+ public WorkflowInstance GetWorkflow (Guid instanceId) + { + // TODO: This is related to persistence services + if (IsStarted == false) { + throw new InvalidOperationException ("This operation can only be performed with a started WorkflowRuntime"); + } + + throw new NotImplementedException (); + } + + public object GetService (Type serviceType) + { + ReadOnlyCollection <object> objs = GetAllServices (serviceType); + + if (objs.Count > 1) { + throw new InvalidOperationException ("More than one runtime service exists"); + } + + return objs[0]; + } + + public void RemoveService (object service) + { + if (services.Contains (service) == false) { + throw new InvalidOperationException ("Cannot remove a service that has not been added"); + } + + services.Remove (service); + } + + public void StartRuntime () + { + // Provide default services if the user has not provided them + if ((GetAllServices (typeof (WorkflowLoaderService))).Count == 0) { + AddService (new DefaultWorkflowLoaderService ()); + } + + if ((GetAllServices (typeof (WorkflowSchedulerService))).Count == 0) { + AddService (new DefaultWorkflowSchedulerService ()); + } + + is_started = true; + runtimes.Add (this); + } +
+ public void StopRuntime () + { + is_started = false; + + foreach (WorkflowInstance wi in instances.Values) { + wi.Abort (); + } + + runtimes.Remove (this); + } + + // Private + internal void OnWorkflowCompleted (WorkflowInstance wi) + { + if (WorkflowCompleted != null) { + WorkflowCompleted (this, new WorkflowCompletedEventArgs (wi, + wi.GetWorkflowDefinition ())); + } + } + + internal void OnWorkflowIdled (WorkflowInstance wi) + { + if (WorkflowIdled != null) { + WorkflowIdled (this, new WorkflowEventArgs (wi)); + } + } + + static internal WorkflowInstance GetInstanceFromGuid (Guid instanceId) + { + WorkflowInstance wi; + foreach (WorkflowRuntime rt in runtimes) { + wi = rt.instances [instanceId]; + + if (wi != null) { + return wi; + } + } + + return null; + } + + } +} + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowTerminatedEventArgs.cs b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowTerminatedEventArgs.cs new file mode 100644 index 00000000000..2cddd6f7f03 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime/WorkflowTerminatedEventArgs.cs @@ -0,0 +1,46 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; + +namespace System.Workflow.Runtime +{ + public class WorkflowTerminatedEventArgs : WorkflowEventArgs
+ { + private Exception exception; + + internal WorkflowTerminatedEventArgs (WorkflowInstance workflow_instance, Exception exception) : + base (workflow_instance) + { + this.exception = exception; + } + + // Properties
+ public Exception Exception { + get {return exception; } + }
+ } +} + + diff --git a/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime_test.dll.sources b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime_test.dll.sources new file mode 100644 index 00000000000..8e8f77984fb --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/System.Workflow.Runtime_test.dll.sources @@ -0,0 +1,8 @@ +System.Workflow.Runtime/WorkflowQueuingServiceTest.cs +System.Workflow.Runtime/WorkflowRuntimeTest.cs +Workflows/SingleActivityCodeTest.cs +Workflows/SimpleWorkFlowDelayTest.cs +System.Workflow.Runtime/TimerEventSubscriptionTest.cs +Workflows/WorkFlowParallelTest.cs +Workflows/WorkFlowMachineStatusTest.cs +System.Workflow.Runtime/TimerEventSubscriptionCollectionTest.cs
\ No newline at end of file diff --git a/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/TimerEventSubscriptionCollectionTest.cs b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/TimerEventSubscriptionCollectionTest.cs new file mode 100644 index 00000000000..dfd59e1ccac --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/TimerEventSubscriptionCollectionTest.cs @@ -0,0 +1,97 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using NUnit.Framework; +using System.Collections; +using System.Collections.Generic; +using System.Workflow.Runtime; +using System.Reflection; + +namespace MonoTests.System.Workflow.Runtime +{ + + [TestFixture] + [Category ("NotDotNet")] // Cannot test on .Net since internal constructors (there no public) are different + public class TimerEventSubscriptionCollectionTest + { + [Test] + public void TestCollection () + { + TimerEventSubscriptionCollection col; + + // There is no public constructor for TimerEventSubscriptionCollection + col = (TimerEventSubscriptionCollection) Activator.CreateInstance + (typeof (TimerEventSubscriptionCollection), + BindingFlags.Instance |BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, + null, null, null); + + TimerEventSubscription event1 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2006, 07, 30)); + + TimerEventSubscription event2 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2006, 07, 28)); + + TimerEventSubscription event3 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2006, 08, 28)); + + TimerEventSubscription event4 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2007, 08, 28)); + + TimerEventSubscription event5 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2006, 05, 28)); + + TimerEventSubscription event6 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2008, 02, 28)); + + TimerEventSubscription event7 = new TimerEventSubscription (Guid.NewGuid (), + new DateTime (2005, 05, 28)); + + col.Add (event1); + col.Add (event2); + col.Add (event3); + col.Add (event4); + col.Add (event5); + col.Add (event6); + col.Add (event7); + + Assert.AreEqual (event7.ExpiresAt, col.Peek ().ExpiresAt, "C1#1"); + col.Remove (col.Peek ()); + Assert.AreEqual (event5.ExpiresAt, col.Peek ().ExpiresAt, "C1#2"); + col.Remove (col.Peek ()); + Assert.AreEqual (event2.ExpiresAt, col.Peek ().ExpiresAt, "C1#3"); + col.Remove (col.Peek ()); + Assert.AreEqual (event1.ExpiresAt, col.Peek ().ExpiresAt, "C1#4"); + col.Remove (col.Peek ()); + Assert.AreEqual (event3.ExpiresAt, col.Peek ().ExpiresAt, "C1#5"); + col.Remove (col.Peek ()); + Assert.AreEqual (event4.ExpiresAt, col.Peek ().ExpiresAt, "C1#6"); + + } + + + + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/TimerEventSubscriptionTest.cs b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/TimerEventSubscriptionTest.cs new file mode 100644 index 00000000000..81bd7637d3e --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/TimerEventSubscriptionTest.cs @@ -0,0 +1,90 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using NUnit.Framework; +using System.Collections; +using System.Collections.Generic; +using System.Workflow.Runtime; + +namespace MonoTests.System.Workflow.Runtime +{ + public class ourTimerEventSubscription : TimerEventSubscription + { + public ourTimerEventSubscription () : base () + { + + } + + public void SetQueueName (IComparable name) + { + QueueName = name; + } + } + + [TestFixture] + public class TimerEventSubscriptionTest + { + [Test] + public void Constructor1 () + { + TimerEventSubscription timer; + Guid timerId = Guid.NewGuid (); + Guid workflowInstanceId = Guid.NewGuid (); + DateTime expiresAt = DateTime.Today; + + timer = new TimerEventSubscription (timerId, workflowInstanceId, expiresAt); + + Assert.AreEqual (timerId, timer.SubscriptionId, "C1#1"); + Assert.AreEqual (workflowInstanceId, timer.WorkflowInstanceId, "C1#2"); + Assert.AreEqual (timerId, timer.QueueName, "C1#3"); + } + + [Test] + public void Constructor2 () + { + TimerEventSubscription timer; + Guid workflowInstanceId = Guid.NewGuid (); + DateTime expiresAt = DateTime.Today; + + timer = new TimerEventSubscription (workflowInstanceId, expiresAt); + Assert.AreEqual (workflowInstanceId, timer.WorkflowInstanceId, "C1#1"); + Assert.AreEqual (timer.SubscriptionId, timer.QueueName, "C1#2"); + } + + [Test] + public void Constructor3 () + { + ourTimerEventSubscription timer = new ourTimerEventSubscription (); + Assert.AreEqual (Guid.Empty, timer.WorkflowInstanceId, "C1#1"); + Assert.AreEqual (null, timer.QueueName, "C1#2"); + Assert.AreEqual (Guid.Empty, timer.WorkflowInstanceId, "C1#3"); + + timer.SetQueueName ("OurName"); + Assert.AreEqual ("OurName", timer.QueueName, "C1#4"); + } + + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/WorkflowQueuingServiceTest.cs b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/WorkflowQueuingServiceTest.cs new file mode 100644 index 00000000000..d7edb8b5d15 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/WorkflowQueuingServiceTest.cs @@ -0,0 +1,47 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using NUnit.Framework; +using System.Collections; +using System.Collections.Generic; + +namespace MonoTests.System.Workflow.Runtime +{ + [TestFixture] + public class WorkflowQueuingServiceTest + { + [Test] + public void SetGet () + { + //WorkflowQueuingService qs = new WorkflowQueuingService (); + //CreateWorkflowQueue + //Assert.AreEqual ("Activity", activity.QualifiedName, "C1#6"); + + } + + + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/WorkflowRuntimeTest.cs b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/WorkflowRuntimeTest.cs new file mode 100644 index 00000000000..8bff620b35e --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/System.Workflow.Runtime/WorkflowRuntimeTest.cs @@ -0,0 +1,188 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// + +using System; +using NUnit.Framework; +using System.Workflow.ComponentModel; +using System.Workflow.Runtime.Hosting; +using System.Workflow.Runtime; +using System.Workflow.Activities; +using System.Collections; +using System.Collections.Generic; +using System.Xml; + +namespace MonoTests.System.Workflow.Runtime +{ + public class WorkflowLoaderServiceTest1 : WorkflowLoaderService
+ {
+ public WorkflowLoaderServiceTest1 () + { + + } + + protected override Activity CreateInstance (Type workflowType) + { + return null; + } +
+ protected override Activity CreateInstance (XmlReader workflowDefinitionReader, XmlReader rulesReader) + { + return null; + }
+ } + + public class WorkflowLoaderServiceTest2 : WorkflowLoaderService
+ {
+ public WorkflowLoaderServiceTest2 () + { + + } +
+ protected override Activity CreateInstance (Type workflowType) + { + return null; + } +
+ protected override Activity CreateInstance (XmlReader workflowDefinitionReader, XmlReader rulesReader) + { + return null; + }
+ } + + [TestFixture] + public class WorkflowRuntimeTest + { + + [Test] + public void Services () + { + // By default there are no services + WorkflowRuntime wr = new WorkflowRuntime (); + Assert.AreEqual (0, (wr.GetAllServices (typeof (WorkflowLoaderService))).Count, "C1#1"); + //Assert.AreEqual (0, (wr.GetAllServices (typeof (WorkflowPersistenceService))).Count, "C1#2"); + //Assert.AreEqual (0, (wr.GetAllServices (typeof (WorkflowQueuingService))).Count, "C1#3"); + + // Can have to diferent instances of the same class + WorkflowRuntime wr3 = new WorkflowRuntime (); + WorkflowLoaderServiceTest1 wls = new WorkflowLoaderServiceTest1 (); + wr3.AddService (wls); + Assert.AreEqual (wls, wr3.GetService (typeof (WorkflowLoaderService)), "C1#2"); + + wr3.AddService (new WorkflowLoaderServiceTest1 ()); + + Assert.AreEqual (2, (wr3.GetAllServices (typeof (WorkflowLoaderService))).Count, "C1#3"); + Assert.AreEqual (2, wr3.GetAllServices <WorkflowLoaderService> ().Count, "C1#3"); + + wr.AddService (new WorkflowLoaderServiceTest1 ()); + + //foreach (object t in wr.GetAllServices (typeof (WorkflowLoaderService))) {
+ // Console.WriteLine ("Types {0}", t.GetType ()); + //} + } + + [Test] + public void Start () + { + WorkflowRuntime wr = new WorkflowRuntime (); + wr.StartRuntime (); + + Assert.AreEqual (1, (wr.GetAllServices (typeof (WorkflowLoaderService))).Count, "C1#1"); + + foreach (object t in wr.GetAllServices (typeof (WorkflowLoaderService))) {
+ Console.WriteLine ("Types {0}", t.GetType ()); + } + } + + [Test] + public void CreateGetWorkflow () + { + Guid guid1 = Guid.NewGuid (); + Guid guid2 = Guid.NewGuid (); + + WorkflowRuntime wr = new WorkflowRuntime (); + Assert.AreEqual (false, wr.IsStarted, "C1#1"); + WorkflowInstance wi1 = wr.CreateWorkflow (typeof (SequentialWorkflowActivity), null, guid1); + Assert.AreEqual (wi1.InstanceId, guid1, "C1#2"); + + Assert.AreEqual (true, wr.IsStarted, "C1#3"); + WorkflowInstance wi2 = wr.CreateWorkflow (typeof (SequenceActivity), null, guid2); + Assert.AreEqual (wi2.InstanceId, guid2, "C1#4"); + } + + + // Exceptions + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void AddServiceTwice () + { + WorkflowRuntime wr = new WorkflowRuntime (); + WorkflowLoaderServiceTest1 wl = new WorkflowLoaderServiceTest1 (); + wr.AddService (wl); + wr.AddService (wl); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void RemoveUnexistantService () + { + WorkflowRuntime wr = new WorkflowRuntime (); + WorkflowLoaderServiceTest1 wl = new WorkflowLoaderServiceTest1 (); + wr.RemoveService (wl); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void GetServiceWithTwoA () + { + WorkflowRuntime wr = new WorkflowRuntime (); + WorkflowLoaderServiceTest1 wl = new WorkflowLoaderServiceTest1 (); + WorkflowLoaderServiceTest2 w2 = new WorkflowLoaderServiceTest2 (); + wr.AddService (wl); + wr.AddService (w2); + wr.GetService (typeof (WorkflowLoaderService)); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void GetServiceWithTwoB () + { + WorkflowRuntime wr = new WorkflowRuntime (); + WorkflowLoaderServiceTest1 wl = new WorkflowLoaderServiceTest1 (); + WorkflowLoaderServiceTest2 w2 = new WorkflowLoaderServiceTest2 (); + wr.AddService (wl); + wr.AddService (w2); + wr.GetService <WorkflowLoaderService> (); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void GetInstanceNoRuntimeStarted () + { + // This operation can only be performed with a started WorkflowRuntime + WorkflowRuntime wr = new WorkflowRuntime (); + wr.GetWorkflow (Guid.NewGuid ()); + } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/ChangeLog b/mcs/class/System.Workflow.Runtime/Test/Workflows/ChangeLog new file mode 100644 index 00000000000..e5d29422895 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/ChangeLog @@ -0,0 +1,4 @@ +2006-09-02 Jordi Mas i Hernandez <jordimash@gmail.com> + + * Initial check-in + diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/SimpleWorkFlowDelayTest.cs b/mcs/class/System.Workflow.Runtime/Test/Workflows/SimpleWorkFlowDelayTest.cs new file mode 100644 index 00000000000..17cc4df7d89 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/SimpleWorkFlowDelayTest.cs @@ -0,0 +1,114 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// +// +// This a simple Sequential WorkFlow with a Delay, While and Code activities +// +// + +using System; +using NUnit.Framework; +using System.Workflow.ComponentModel; +using System.Workflow.Activities; +using System.Workflow.Runtime; +using System.Threading; + +namespace MonoTests.System.Workflow.Runtime +{ + + public sealed class SimpleWorkFlowDelay : SequentialWorkflowActivity + { + private WhileActivity WhileFilesToBackup;
+ private CodeActivity BackUpFile;
+ private DelayActivity DelaySystemReady;
+
+ public SimpleWorkFlowDelay ()
+ {
+ CanModifyActivities = true;
+ CodeCondition codecondition1 = new CodeCondition ();
+ BackUpFile = new CodeActivity ();
+ WhileFilesToBackup = new WhileActivity ();
+ DelaySystemReady = new DelayActivity ();
+
+ BackUpFile.ExecuteCode += new EventHandler (BackUpFile_ExecuteCode);
+
+ WhileFilesToBackup.Activities.Add(BackUpFile);
+ codecondition1.Condition += new EventHandler <ConditionalEventArgs>(MoreFiles);
+
+ WhileFilesToBackup.Condition = codecondition1;
+
+ DelaySystemReady.TimeoutDuration = TimeSpan.Parse ("00:00:02");
+
+ Activities.Add (DelaySystemReady);
+ Activities.Add (WhileFilesToBackup);
+ Name = "SimpleWorkFlowDelay";
+ CanModifyActivities = false;
+ }
+
+ private void MoreFiles (object sender, ConditionalEventArgs e)
+ {
+ SimpleWorkFlowDelayTest.files_counted++;
+ if (SimpleWorkFlowDelayTest.files_counted < 3) {
+ e.Result = true;
+ }
+ else {
+ e.Result = false;
+ }
+ }
+
+ private void BackUpFile_ExecuteCode (object sender, EventArgs e)
+ {
+ SimpleWorkFlowDelayTest.backup_executed++;
+ } + } + + [TestFixture] + public class SimpleWorkFlowDelayTest + { + static public int files_counted = 0; + static public int backup_executed = 0; + static AutoResetEvent waitHandle = new AutoResetEvent (false); + + [Test] + public void WorkFlowTest () + { + WorkflowRuntime workflowRuntime = new WorkflowRuntime (); + + Type type = typeof (SimpleWorkFlowDelay);
+ workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; + + workflowRuntime.CreateWorkflow (type).Start ();
+ waitHandle.WaitOne ();
+ workflowRuntime.Dispose (); + + Assert.AreEqual (3, files_counted, "C1#1"); + Assert.AreEqual (3, backup_executed, "C1#2"); + } + + void OnWorkflowCompleted (object sender, WorkflowCompletedEventArgs e)
+ {
+ waitHandle.Set ();
+ } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/SingleActivityCodeTest.cs b/mcs/class/System.Workflow.Runtime/Test/Workflows/SingleActivityCodeTest.cs new file mode 100644 index 00000000000..46ab3f28401 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/SingleActivityCodeTest.cs @@ -0,0 +1,79 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// +// +// This a simple Sequential WorkFlow with a Code Activity +// + +using System; +using NUnit.Framework; +using System.Workflow.ComponentModel; +using System.Workflow.Activities; +using System.Workflow.Runtime; +using System.Threading; + +namespace MonoTests.System.Workflow.Runtime +{ + public sealed class SequentialWorkflow : SequentialWorkflowActivity + { + public SequentialWorkflow () + { + CodeActivity code = new CodeActivity (); + code.ExecuteCode += OnCodeExecute;
+ Activities.Add (code); + } +
+ private void OnCodeExecute (object sender, EventArgs e)
+ {
+ SingleActivityCodeTest.code_execute = true;
+ } + } + + [TestFixture] + public class SingleActivityCodeTest + { + static public bool code_execute = false; + static AutoResetEvent waitHandle = new AutoResetEvent(false); + + [Test] + public void WorkFlowTest () + { + WorkflowRuntime workflowRuntime = new WorkflowRuntime (); + + Type type = typeof (SequentialWorkflow);
+ workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; + + workflowRuntime.CreateWorkflow (type).Start ();
+ waitHandle.WaitOne ();
+ workflowRuntime.Dispose (); + + Assert.AreEqual (true, code_execute, "C1#1"); + } + + void OnWorkflowCompleted (object sender, WorkflowCompletedEventArgs e)
+ {
+ waitHandle.Set ();
+ } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowMachineStatusTest.cs b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowMachineStatusTest.cs new file mode 100644 index 00000000000..8f3f1899b84 --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowMachineStatusTest.cs @@ -0,0 +1,296 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// +// This is a State Machine workflow test +// +// + +using System; +using NUnit.Framework; +using System.Workflow.ComponentModel; +using System.Workflow.Activities; +using System.Workflow.Runtime; +using System.Threading; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace MonoTests.Workflow.Runtime +{ + public sealed class DocumentCreation : StateMachineWorkflowActivity + { + private SetStateActivity DocumentSetState; + private CodeActivity CodeDocument; + private EventDrivenActivity CreateDriven; + private EventDrivenActivity ProofReadEventDriven; + private StateActivity ProofRead; + private SetStateActivity ProofReadSetStateQualityNotOK; + private SetStateActivity ProofReadSetStateQualityOK; + private IfElseBranchActivity ProofReadElseBranchActivity2; + private IfElseBranchActivity ProofReadElseBranch; + private IfElseActivity ProofReadIfElse; + private EventDrivenActivity PrintEventDriven; + private StateActivity Print; + private CodeActivity PrintCode; + private DelayActivity PrintDelay; + private StateActivity End; + private SetStateActivity PrintSetState; + private DelayActivity ProofReadDelay; + private DelayActivity CreateDelay; + private CodeActivity CreateInitCode; + private StateInitializationActivity CreateInitialization; + private CodeActivity PrintFinalizationCode; + private StateFinalizationActivity PrintFinalization; + private StateActivity Create; + + public DocumentCreation () + { + InitializeComponent (); + } + + private void InitializeComponent () + { + CanModifyActivities = true; + CodeCondition codecondition1 = new CodeCondition (); + ProofReadSetStateQualityNotOK = new SetStateActivity (); + ProofReadSetStateQualityOK = new SetStateActivity (); + ProofReadElseBranchActivity2 = new IfElseBranchActivity (); + ProofReadElseBranch = new IfElseBranchActivity (); + PrintFinalizationCode = new CodeActivity (); + PrintSetState = new SetStateActivity (); + PrintCode = new CodeActivity (); + PrintDelay = new DelayActivity (); + ProofReadIfElse = new IfElseActivity (); + ProofReadDelay = new DelayActivity (); + CreateInitCode = new CodeActivity (); + DocumentSetState = new SetStateActivity (); + CodeDocument = new CodeActivity (); + CreateDelay = new DelayActivity (); + PrintFinalization = new StateFinalizationActivity (); + PrintEventDriven = new EventDrivenActivity (); + ProofReadEventDriven = new EventDrivenActivity (); + CreateInitialization = new StateInitializationActivity (); + CreateDriven = new EventDrivenActivity (); + End = new StateActivity (); + Print = new StateActivity (); + ProofRead = new StateActivity (); + Create = new StateActivity (); + + // ProofReadSetStateQualityNotOK + ProofReadSetStateQualityNotOK.Name = "ProofReadSetStateQualityNotOK"; + ProofReadSetStateQualityNotOK.TargetStateName = "Print"; + + // ProofReadSetStateQualityOK + ProofReadSetStateQualityOK.Name = "ProofReadSetStateQualityOK"; + ProofReadSetStateQualityOK.TargetStateName = "End"; + + // ProofReadElseBranchActivity2 + ProofReadElseBranchActivity2.Activities.Add (ProofReadSetStateQualityNotOK); + ProofReadElseBranchActivity2.Name = "ProofReadElseBranchActivity2"; + + // ProofReadElseBranch + ProofReadElseBranch.Activities.Add (ProofReadSetStateQualityOK); + codecondition1.Condition += new EventHandler <ConditionalEventArgs> (ProofReadIfElseConditionFunction); + ProofReadElseBranch.Condition = codecondition1; + ProofReadElseBranch.Name = "ProofReadElseBranch"; + + // PrintFinalizationCode + PrintFinalizationCode.Name = "PrintFinalizationCode"; + PrintFinalizationCode.ExecuteCode += new EventHandler (PrintFinalizationCodeFunction); + + // PrintSetState + PrintSetState.Name = "PrintSetState"; + PrintSetState.TargetStateName = "End"; + + // PrintCode + PrintCode.Name = "PrintCode"; + PrintCode.ExecuteCode += new EventHandler (PrintCodeFunction); + + // PrintDelay + PrintDelay.Name = "PrintDelay"; + PrintDelay.TimeoutDuration = TimeSpan.Parse ("00:00:02"); + + // ProofReadIfElse + ProofReadIfElse.Activities.Add (ProofReadElseBranch); + ProofReadIfElse.Activities.Add (ProofReadElseBranchActivity2); + ProofReadIfElse.Description = "Quality is OK?"; + ProofReadIfElse.Name = "ProofReadIfElse"; + + // ProofReadDelay + ProofReadDelay.Name = "ProofReadDelay"; + ProofReadDelay.TimeoutDuration = TimeSpan.Parse ("00:00:01"); + + // CreateInitCode + CreateInitCode.Name = "CreateInitCode"; + CreateInitCode.ExecuteCode += new EventHandler (CreateInitCodeFunction); + + // DocumentSetState + DocumentSetState.Name = "DocumentSetState"; + DocumentSetState.TargetStateName = "ProofRead"; + + // CodeDocument + CodeDocument.Name = "CodeDocument"; + CodeDocument.ExecuteCode += new EventHandler (CodeDocumentFunction); + + // CreateDelay + CreateDelay.Name = "CreateDelay"; + CreateDelay.TimeoutDuration = TimeSpan.Parse ("00:00:01"); + + // PrintFinalization + PrintFinalization.Activities.Add (PrintFinalizationCode); + PrintFinalization.Name = "PrintFinalization"; + + // PrintEventDriven + PrintEventDriven.Activities.Add (PrintDelay); + PrintEventDriven.Activities.Add (PrintCode); + PrintEventDriven.Activities.Add (PrintSetState); + PrintEventDriven.Name = "PrintEventDriven"; + + // ProofReadEventDriven + ProofReadEventDriven.Activities.Add (ProofReadDelay); + ProofReadEventDriven.Activities.Add (ProofReadIfElse); + ProofReadEventDriven.Name = "ProofReadEventDriven"; + + // CreateInitialization + CreateInitialization.Activities.Add (CreateInitCode); + CreateInitialization.Name = "CreateInitialization"; + + // CreateDriven + CreateDriven.Activities.Add (CreateDelay); + CreateDriven.Activities.Add (CodeDocument); + CreateDriven.Activities.Add (DocumentSetState); + CreateDriven.Name = "CreateDriven"; + + // End + End.Name = "End"; + + // Print + Print.Activities.Add (PrintEventDriven); + Print.Activities.Add (PrintFinalization); + Print.Name = "Print"; + + // ProofRead + ProofRead.Activities.Add (ProofReadEventDriven); + ProofRead.Name = "ProofRead"; + + // Create + Create.Activities.Add (CreateDriven); + Create.Activities.Add (CreateInitialization); + Create.Name = "Create"; + + // DocumentCreation + Activities.Add (Create); + Activities.Add (ProofRead); + Activities.Add (Print); + Activities.Add (End); + CompletedStateName = "End"; + InitialStateName = "Create"; + Name = "DocumentCreation"; + CanModifyActivities = false; + } + + private void PrintCodeFunction (object sender, EventArgs e) + { + WorkFlowMachineStatusTest.Events.Add ("PrintCodeFunction"); + } + + private void ProofReadIfElseConditionFunction (object sender, ConditionalEventArgs e) + { + e.Result = false; + WorkFlowMachineStatusTest.Events.Add ("ProofReadIfElseConditionFunction"); + + Activity activity = (Activity) sender; + while (activity.Parent != null) { + activity = activity.Parent; + } + + DocumentCreation doc = (DocumentCreation) activity; + WorkFlowMachineStatusTest.Events.Add ("State:" + doc.CurrentStateName); + } + + private void CodeDocumentFunction (object sender, EventArgs e) + { + WorkFlowMachineStatusTest.Events.Add ("CodeDocumentFunction"); + } + + private void CreateInitCodeFunction (object sender, EventArgs e) + { + WorkFlowMachineStatusTest.Events.Add ("CreateInitCodeFunction"); + } + + private void PrintFinalizationCodeFunction (object sender, EventArgs e) + { + WorkFlowMachineStatusTest.Events.Add ("PrintFinalizationCodeFunction"); + + Activity activity = (Activity) sender; + while (activity.Parent != null) { + activity = activity.Parent; + } + + DocumentCreation doc = (DocumentCreation) activity; + WorkFlowMachineStatusTest.Events.Add ("State:" + doc.CurrentStateName); + WorkFlowMachineStatusTest.Events.Add ("Previous state:" + doc.PreviousStateName); + } + } + + [TestFixture] + public class WorkFlowMachineStatusTest + { + static public List <string> events; + + static public List <string> Events { + get {return events;} + } + + [Test] + public void WorkFlowTest () + { + events = new List <string> (); + using (WorkflowRuntime workflowRuntime = new WorkflowRuntime ()) + { + AutoResetEvent waitHandle = new AutoResetEvent (false); + workflowRuntime.WorkflowCompleted += delegate (object sender, WorkflowCompletedEventArgs e) {waitHandle.Set ();}; + workflowRuntime.WorkflowTerminated += delegate (object sender, WorkflowTerminatedEventArgs e) + { + Console.WriteLine (e.Exception.Message); + waitHandle.Set (); + }; + + WorkflowInstance instance = workflowRuntime.CreateWorkflow (typeof (DocumentCreation)); + instance.Start (); + + waitHandle.WaitOne (); + } + + Assert.AreEqual ("CreateInitCodeFunction", events[0], "C1#1"); + Assert.AreEqual ("CodeDocumentFunction", events[1], "C1#2"); + Assert.AreEqual ("ProofReadIfElseConditionFunction", events[2], "C1#3"); + Assert.AreEqual ("State:ProofRead", events[3], "C1#4"); + Assert.AreEqual ("PrintCodeFunction", events[4], "C1#5"); + Assert.AreEqual ("PrintFinalizationCodeFunction", events[5], "C1#6"); + Assert.AreEqual ("State:End", events[6], "C1#7"); + Assert.AreEqual ("Previous state:Print", events[7], "C1#8"); + Assert.AreEqual (8, events.Count, "C1#9"); + } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowMachineStatusTest.jpg b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowMachineStatusTest.jpg Binary files differnew file mode 100644 index 00000000000..f668f960eda --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowMachineStatusTest.jpg diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowParallelTest.cs b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowParallelTest.cs new file mode 100644 index 00000000000..faf6e68313e --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowParallelTest.cs @@ -0,0 +1,229 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Authors: +// +// Copyright (C) 2006 Jordi Mas i Hernandez <jordimash@gmail.com> +// +// +// This workflow uses Paralell and Delays activities +// +// + +using System; +using NUnit.Framework; +using System.Workflow.ComponentModel; +using System.Workflow.Activities; +using System.Workflow.Runtime; +using System.Threading; +using System.Collections.Generic; + +namespace MonoTests.System.Workflow.Runtime +{ + public sealed class SequentialWorkflowParallel : SequentialWorkflowActivity + { + private CodeActivity CodeCloseMailProgram2; + private DelayActivity DelayWaitForSentMail2; + private CodeActivity PrepareMail2; + private CodeActivity CodeCloseMailProgram1; + private DelayActivity DelayWaitForSentMail1; + private CodeActivity CodePrepareMail1; + private SequenceActivity SeqSendMail2; + private SequenceActivity SeqSendMail1; + private ParallelActivity Parallel; + private IfElseBranchActivity IfElseBranchActivityNoNeed; + private IfElseBranchActivity IfElseBranchActivityNeedToSendMail; + private TerminateActivity TerminateFinishNoNeedToReadMail; + private IfElseActivity NeedToSendMail; + private CodeActivity CodeCloseMailProgram3; + private DelayActivity DelayWaitForSentMail3; + private CodeActivity PrepareMail3; + private SequenceActivity SeqSendMail3; + + public SequentialWorkflowParallel () + { + InitializeComponent (); + } + + private void InitializeComponent () + { + Console.WriteLine ("1"); + + CanModifyActivities = true; + CodeCondition codecondition1 = new CodeCondition (); + CodeCloseMailProgram2 = new CodeActivity (); + CodeCloseMailProgram3 = new CodeActivity (); + DelayWaitForSentMail2 = new DelayActivity (); + DelayWaitForSentMail3 = new DelayActivity (); + PrepareMail2 = new CodeActivity (); + PrepareMail3 = new CodeActivity (); + CodeCloseMailProgram1 = new CodeActivity (); + DelayWaitForSentMail1 = new DelayActivity (); + CodePrepareMail1 = new CodeActivity (); + SeqSendMail2 = new SequenceActivity (); + SeqSendMail1 = new SequenceActivity (); + SeqSendMail3 = new SequenceActivity (); + TerminateFinishNoNeedToReadMail = new TerminateActivity (); + Parallel = new ParallelActivity (); + IfElseBranchActivityNoNeed = new IfElseBranchActivity (); + IfElseBranchActivityNeedToSendMail = new IfElseBranchActivity (); + NeedToSendMail = new IfElseActivity (); + + PrepareMail3.Name = "PrepareMail3"; + PrepareMail3.ExecuteCode += new EventHandler (PrepareMail3_ExecuteCode); + + CodeCloseMailProgram3.Name = "CodeCloseMailProgram3"; + CodeCloseMailProgram3.ExecuteCode += new EventHandler (CodeCloseMailProgram3_ExecuteCode); + + DelayWaitForSentMail3.Name = "DelayWaitForSentMail3"; + DelayWaitForSentMail3.TimeoutDuration = TimeSpan.Parse ("00:00:03"); + + CodeCloseMailProgram2.Name = "CodeCloseMailProgram2"; + CodeCloseMailProgram2.ExecuteCode += new EventHandler (CodeCloseMailProgram2_ExecuteCode); + + DelayWaitForSentMail2.Name = "DelayWaitForSentMail2"; + DelayWaitForSentMail2.TimeoutDuration = TimeSpan.Parse ("00:00:02"); + + PrepareMail2.Name = "PrepareMail2"; + PrepareMail2.ExecuteCode += new EventHandler (PrepareMail2_ExecuteCode); + + CodeCloseMailProgram1.Name = "CodeCloseMailProgram1"; + CodeCloseMailProgram1.ExecuteCode += new EventHandler (CodeCloseMailProgram_ExecuteCode); + + DelayWaitForSentMail1.Name = "DelayWaitForSentMail1"; + DelayWaitForSentMail1.TimeoutDuration = TimeSpan.Parse ("00:00:05"); + CodePrepareMail1.Name = "CodePrepareMail1"; + CodePrepareMail1.ExecuteCode += new EventHandler (CodeActivity1_ExecuteCode); + + SeqSendMail2.Activities.Add (PrepareMail2); + SeqSendMail2.Activities.Add (DelayWaitForSentMail2); + SeqSendMail2.Activities.Add (CodeCloseMailProgram2); + SeqSendMail2.Name = "SeqSendMail2"; + + SeqSendMail3.Activities.Add (PrepareMail3); + SeqSendMail3.Activities.Add (DelayWaitForSentMail3); + SeqSendMail3.Activities.Add (CodeCloseMailProgram3); + SeqSendMail3.Name = "SeqSendMail3"; + + SeqSendMail1.Activities.Add (CodePrepareMail1); + SeqSendMail1.Activities.Add (DelayWaitForSentMail1); + SeqSendMail1.Activities.Add (CodeCloseMailProgram1); + SeqSendMail1.Name = "SeqSendMail1"; + + TerminateFinishNoNeedToReadMail.Name = "TerminateFinishNoNeedToReadMail"; + + Parallel.Activities.Add (SeqSendMail1); + Parallel.Activities.Add (SeqSendMail2); + Parallel.Activities.Add (SeqSendMail3); + Parallel.Name = "Parallel"; + + IfElseBranchActivityNoNeed.Activities.Add (TerminateFinishNoNeedToReadMail); + IfElseBranchActivityNoNeed.Name = "IfElseBranchActivityNoNeed"; + + IfElseBranchActivityNeedToSendMail.Activities.Add (Parallel); + codecondition1.Condition += new EventHandler <ConditionalEventArgs>(IfElseCondition); + IfElseBranchActivityNeedToSendMail.Condition = codecondition1; + IfElseBranchActivityNeedToSendMail.Name = "IfElseBranchActivityNeedToSendMail"; + + NeedToSendMail.Activities.Add (IfElseBranchActivityNeedToSendMail); + NeedToSendMail.Activities.Add (IfElseBranchActivityNoNeed); + NeedToSendMail.Name = "NeedToSendMail"; + + Activities.Add (NeedToSendMail); + Name = "IfElseParalellWorkFlow"; + CanModifyActivities = false; + } + + private void IfElseCondition (object sender, ConditionalEventArgs e) + { + WorkFlowParallelTest.Events.Add ("IfElseCondition"); + e.Result = true; + } + + private void CodeActivity1_ExecuteCode (object sender, EventArgs e) + { + WorkFlowParallelTest.Events.Add ("PrepareMail1_ExecuteCode"); + } + + private void CodeCloseMailProgram_ExecuteCode (object sender, EventArgs e) + { + WorkFlowParallelTest.Events.Add ("CodeCloseMailProgram1_ExecuteCode"); + } + + private void PrepareMail2_ExecuteCode (object sender, EventArgs e) + { + WorkFlowParallelTest.Events.Add ("PrepareMail2_ExecuteCode"); + } + + private void CodeCloseMailProgram2_ExecuteCode (object sender, EventArgs e) + { + WorkFlowParallelTest.Events.Add ("CodeCloseMailProgram2_ExecuteCode"); + } + + private void PrepareMail3_ExecuteCode (object sender, EventArgs e) + { + WorkFlowParallelTest.Events.Add ("PrepareMail3_ExecuteCode"); + } + + private void CodeCloseMailProgram3_ExecuteCode (object sender, EventArgs e) + { + WorkFlowParallelTest.Events.Add ("CodeCloseMailProgram3_ExecuteCode"); + } + } + + [TestFixture] + public class WorkFlowParallelTest + { + static public List <string> events; + static AutoResetEvent waitHandle = new AutoResetEvent(false); + + [Test] + public void WorkFlowTest () + { + events = new List <string> (); + WorkflowRuntime workflowRuntime = new WorkflowRuntime (); + + Type type = typeof (SequentialWorkflowParallel); + workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; + + workflowRuntime.CreateWorkflow (type).Start (); + + waitHandle.WaitOne (); + workflowRuntime.Dispose (); + + Assert.AreEqual ("IfElseCondition", events[0], "C1#1"); + Assert.AreEqual ("PrepareMail1_ExecuteCode", events[1], "C1#2"); + Assert.AreEqual ("PrepareMail2_ExecuteCode", events[2], "C1#3"); + Assert.AreEqual ("PrepareMail3_ExecuteCode", events[3], "C1#4"); + Assert.AreEqual ("CodeCloseMailProgram2_ExecuteCode", events[4], "C1#8"); + Assert.AreEqual ("CodeCloseMailProgram3_ExecuteCode", events[5], "C1#9"); + Assert.AreEqual ("CodeCloseMailProgram1_ExecuteCode", events[6], "C1#10"); + } + + static public List <string> Events { + get {return events;} + } + + void OnWorkflowCompleted (object sender, WorkflowCompletedEventArgs e) + { + waitHandle.Set (); + } + } +} + diff --git a/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowParallelTest.jpg b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowParallelTest.jpg Binary files differnew file mode 100644 index 00000000000..3e24dea4f1e --- /dev/null +++ b/mcs/class/System.Workflow.Runtime/Test/Workflows/WorkFlowParallelTest.jpg |