iTasks.dcl 11.5 KB
Newer Older
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
1 2
definition module iTasks

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
3 4
// iTasks library for defining interactive multi-user workflow tasks (iTask) for the web.
// Defined on top of the iData library.
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
5 6 7 8

// (c) iTask & iData Concept and Implementation by Rinus Plasmeijer, 2006,2007 - MJP
// This library is still under construction - MJP

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
9
iTaskVersion :== "0.97 - Februari 2008 - "
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
10

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
11
import iDataSettings, iDataButtons, StdBimap
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
12
derive gForm 	Void, TCl						
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
13 14
derive gUpd 	Void, TCl
derive gPrint 	Void, TCl
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
15
derive gParse 	Void, TCl
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
16
derive gerda 	Void
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
17 18
derive read 	Void, TCl
derive write 	Void, TCl
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
19

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
20
:: *TSt												// abstract task state
21
:: Task a			:== St *TSt a					// an interactive task
22
:: LabeledTask a	:== !(!String,!Task a)			// a Task with a label used for labeling buttons, pull down menu, and the like
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
23
:: UserId			:== !Int						// unique id of iTask user
24 25

:: HtmlCode			:== [BodyTag]					// most programmers will only write bodytags
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
26

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
27
:: Void 			= Void							// for tasks returning non interesting results, won't show up in editors either
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
28 29


Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
30
// *********************************************************************************************************************************
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
31
// Setting options for any collection of iTask workflows:
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
32

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
33 34 35
:: GarbageCollect 	= Collect 						// garbage collect iTask administration
					| NoCollect						// no garbage collection

Peter Achten's avatar
Peter Achten committed
36
class (<<@) infixl 3 b :: !(Task a) !b -> Task a 	// to set iData attribute globally for indicated (composition of) iTask(s) 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
37

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
38 39 40 41
instance <<@		  Lifespan						// default: Session
					, StorageFormat					// default: PlainString
					, Mode							// default: Edit
					, GarbageCollect				// default: Collect
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
42

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
43
:: SubPage			= UseAjax  						// use Ajax technology to update part of a page, only works if Ajax enabled 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
44
					| OnClient 						// use SAPL to update part of a page on the client, only works if Client enabled and Sapl is running...
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
45 46 47 48

class 	(@>>) infixl 7 b ::  !b !(Task a)   -> (Task a) | iData a	

instance @>>		SubPage							// default: the *whole* page will be updated when a form has been modified
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
49

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
50 51
// *********************************************************************************************************************************
/* Initiate the iTask library with an iData server wrapper such as doHtmlServer in combination with one of the following functions:
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
52 53
					
singleUserTask 	:: iTask start function for defining tasks for one, single user
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
54 55 56
multiUserTask 	:: iTask start function for multi-users, with option in window to switch between [0..users - 1]  
workFlowTask	:: iTask start function for a real workflow, expects a login task and the actual task
				   a predefined login task is defined in iTaskLogin.dcl				
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
57
*/
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
58 59
singleUserTask 	:: ![StartUpOptions] !(Task a) 				!*HSt -> (!Bool,Html,*HSt) 	| iCreate a
multiUserTask 	:: ![StartUpOptions] !(Task a)  			!*HSt -> (!Bool,Html,*HSt) 	| iCreate a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
60 61
workFlowTask	:: ![StartUpOptions] !(Task (UserId,a)) 
									 !((UserId,a) -> Task b)!*HSt -> (!Bool,Html,*HSt) 	| iCreate a 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
62

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
63 64 65
:: StartUpOptions	= TraceOn | TraceOff				// for single & multiUser: default = TraceOn
					| ThreadStorage Lifespan			// for Ajax: where to store threadinformation: default = TxtFile
					| ShowUsers Int						// for multiUserTask, toggle between given maximum number of users, default: ShowUser 5 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
66
					| VersionCheck | NoVersionCheck		// for single & multiUser: default = VersionNoCheck 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
67
					| MyHeader HtmlCode					// wil replace standard iTask information line
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
68

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
69
// *********************************************************************************************************************************
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
70
/* Here follow the iTasks combinators:
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
71

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
72
Basic editors:
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
73
editTask		:: create a task editor to edit a value of given type, and add a button with given name to finish the task
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
74
editTask		:: create a task editor (with submit button) to edit a value of given type, finish only if predicate holds 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
75

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
76
Standard monadic combinators on iTasks:
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
77 78 79
(=>>)			:: for sequencing: bind
return_V		:: lift a value to the iTask domain and return it

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
80
Prompting variants:
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
81 82
(?>>)			:: prompt as long as task is active but not finished
(!>>)			:: prompt when task is activated
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
83 84
(<<?)			:: as ?>>, except that prompt is displayed *after* task
(<<!)			:: as !>>, except that prompt is displayed *after* task
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

Assign tasks to user with indicated id:
assignTaskTo 	:: assign task to indicated user, True for verbose reporting

Repetition and loops:
foreverTask		:: infinitely repeating Task
(<!)			:: repeat task (as a loop)   as long as predicate does not hold; also works for tasks that don't require any user interactions (e.g. database access)

Sequencing Tasks:
seqTasks		:: do all iTasks one after another, task completed when all done

Choose the tasks you want to do one forehand:
chooseTask_btn	:: choose ONE task by pressing a button, True for horizontal buttons, else vertical
chooseTask_pdm	:: as chooseTask_btn, depending on pulldownmenu item selected, Int for initial value
chooseTask_radio:: as chooseTask_btn, depending on radio item selected, Int for initial value, htmlcode for option explanation 

chooseTask_cb	:: choice N tasks out of N, order of chosen task depending on first arg
				   (initial setting, effect for all when set, explanation) for each option

Do m Tasks parallel / interleaved and FINISH as soon as SOME Task completes:
orTask2			:: do both iTasks in any order, combined task completed as any subtask is done
andTask2		:: do both iTasks in any order (interleaved), task completed when both done
andTasksCond	:: do tasks in any order until pred holds for finished tasks, string used for naming group of task navigation buttons
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
108 109
*/

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
110 111 112 113 114 115
editTask 		:: !String 	!a 								-> Task a		| iData a 
editTaskPred 	:: 			!a !(a -> (Bool, HtmlCode))		-> Task a		| iData a 

(=>>) infixl 1 	:: !(Task a) !(a -> Task b) 				-> Task b		| iCreateAndPrint b
return_V 		:: !a 										-> Task a 		| iCreateAndPrint a

116 117 118 119
(?>>) infixr 5 	:: !HtmlCode !(Task a) 						-> Task a		| iCreate a
(!>>) infixr 5 	:: !HtmlCode !(Task a) 						-> Task a		| iCreate a
(<<?) infixl 5 	:: !(Task a) !HtmlCode 						-> Task a		| iCreate a
(<<!) infixl 5 	:: !(Task a) !HtmlCode 						-> Task a		| iCreate a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
120

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
121
assignTaskTo 	:: !Bool !UserId !(LabeledTask a) 			-> Task a		| iData a	
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
122

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
123
foreverTask		:: !(Task a) 								-> Task a 		| iData a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
124
(<!)  infixl 6 	:: !(Task a)  !(a -> .Bool) 				-> Task a 		| iCreateAndPrint a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
125

126 127
seqTasks		:: ![LabeledTask a] 						-> Task [a]		| iCreateAndPrint a

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
128
chooseTask_btn 	:: !HtmlCode !Bool![LabeledTask a] 			-> Task a	 	| iCreateAndPrint a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
129 130 131
chooseTask_pdm 	:: !HtmlCode !Int ![LabeledTask a] 			-> Task a	 	| iCreateAndPrint a
chooseTask_radio:: !HtmlCode !Int ![(HtmlCode,LabeledTask a)]
															-> Task a		| iCreateAndPrint a
132

Peter Achten's avatar
Peter Achten committed
133
:: ChoiceUpdate	:== !Bool [Bool] -> [Bool]									// changed checkbox + current settings -> new settings
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
134

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
135
chooseTask_cbox	:: !([LabeledTask a] -> Task [a])
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
136 137 138
				   !HtmlCode ![((!Bool,!ChoiceUpdate,!HtmlCode),LabeledTask a)] 
															-> Task [a] 	| iData a

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
139 140
orTask2			:: !(Task a,Task b) 						-> Task (EITHER a b) 	
																			| iCreateAndPrint a & iCreateAndPrint b
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
141 142
andTask2		:: !(Task a,Task b) 						-> Task (a,b) 	| iCreateAndPrint a & iCreateAndPrint b
andTasksCond	:: !String !([a] -> Bool) ![LabeledTask a] -> (Task [a]) 	| iData a 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
143

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
144 145 146 147 148 149 150
/* Time and Date management:
waitForTimeTask	:: Task is done when time has come
waitForDateTask	:: Task is done when date has come
*/
waitForTimeTask	:: !HtmlTime								-> Task HtmlTime
waitForDateTask	:: !HtmlDate								-> Task HtmlDate

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
151
/* Experimental department:
152

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
153 154
   May not work when the tasks are garbage collected !!

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
155 156 157 158 159 160 161 162 163 164 165
-!>				:: a task, either finished or interrupted (by completion of the first task) is returned in the closure
				   if interrupted, the work done so far is returned (!) which can be continued somewhere else
channel			:: splits a task in respectively a sender task closure and receiver taskclosure; 
				   when the sender is evaluated, the original task is evaluated as usual;
				   when the receiver task is evaluated, it will wait upon completeion of the sender and then get's its result;
				   Important: Notice that a receiver will never finish if you don't activate the corresponding receiver somewhere.
closureTask		:: The task is executed as usual, but a receiver closure is returned immediately.
				   When the closure is evaluated somewhere, one has to wait until the task is finished.
				   Handy for passing a result to several interested parties.
closureLZTask	:: Same, but now the original task will not be done unless someone is asking for the result somewhere.
*/
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
166
:: TCl a 		= TCl .(Task a)			
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
167

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
168 169 170 171
(-!>) infix 4 	:: (Task stop) (Task a) 					-> Task (Maybe stop,TCl a) 	| iCreateAndPrint stop & iCreateAndPrint a
channel  		:: String (Task a) 							-> Task (TCl a,TCl a) 		| iCreateAndPrint a
closureTask  	:: String (Task a) 							-> Task (TCl a) 			| iCreateAndPrint a
closureLzTask  	:: String (Task a) 							-> Task (TCl a) 			| iCreateAndPrint a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
172

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
173
/* Exception Handling:
174

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
175
<^>				:: Evaluate the task; An exception of type e raised by this task, will be catched by the closest handler.
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
176
				   One can use the function create a proper task value or signal the fact that an exception has occured.  
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
177
Raise 			:: Raises an exception of type e which will be catched by the closest parent handler for this type
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
178
*/
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
179 180
(<^>) infix  1  :: !(e -> a) !(Task a) 						-> Task a 					| iData a   & TC e			// assigns an exception Handler
Raise 			:: e 										-> Task a 					| iCreate a & TC e			// rases an exception
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
181

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
182 183 184 185 186

// *********************************************************************************************************************************
/* Support for user defined combinators
mkTask			:: for making a user defined combinator, name will appear intrace 
newTask			:: same, but optimized: after completion only result will remembered
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
187
Once			:: task will be done only once, the value of the task will be remembered, important for side effecting functions lifted to iData domain
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
188 189 190
*/
mkTask 			:: !String !(Task a) 						-> Task a 		| iCreateAndPrint a
newTask 		:: !String !(Task a) 						-> Task a		| iData a 
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
191
Once 			:: !String !(Task a) 						-> Task a 		| iData a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
192 193 194

// *********************************************************************************************************************************
/* Lifting of other domains to the iTask domain
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
195 196 197
(*>>)			:: lift functions of type (TSt -> (a,TSt)) to iTask domain 
(@>>)			:: lift functions of (TSt -> TSt) to iTask domain 
appIData		:: lift iData editors to iTask domain
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
198
appIData2		:: lift iData editors to iTask domain, and pass iDataTasknumber for naming convenience
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
199 200
appHStOnce		:: lift HSt domain to TSt domain, will be executed only once; string used for tracing
appHSt			:: lift HSt domain to TSt domain, will be executed on each invocation; string used for tracing
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
201
*/
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
202 203 204 205 206 207
(*=>) infix 4 	:: (TSt -> (a,TSt)) (a -> Task b) 			-> Task b
(*#>) infix 4 	:: (TSt -> TSt)     (Task a) 				-> Task a
appIData 		:: (IDataFun a) 							-> Task a 		| iData a
appIData2 		:: (String *HSt -> *(Form a,*HSt)) 			-> Task a		| iData a 
appHStOnce 		:: !String (HSt -> (a,HSt)) 				-> Task a		| iData a
appHSt			:: !String (HSt -> (a,HSt)) 				-> Task a		| iData a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
208 209
appWorldOnce 	:: !String (*World -> *(a,*World)) 			-> Task a		| iData a
appWorld 		:: !String (*World -> *(a,*World)) 			-> Task a		| iData a
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
210

Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
211
// *********************************************************************************************************************************
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
212
/* Operations on Task state
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
213 214
taskId			:: give id of user assigned to task
userId			:: give id of application user
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
215 216 217 218
addHtml			:: add html code
*/
taskId			:: TSt 				-> (Int,TSt)
userId 			:: TSt 				-> (Int,TSt)
219
addHtml 		:: HtmlCode TSt 	-> TSt
Rinus Plasmeijer's avatar
Rinus Plasmeijer committed
220