Presentation is loading. Please wait.

Presentation is loading. Please wait.

I-Tasks - interactive workflow Tasks for the WWWEB ___________ Rinus Plasmeijer University of Nijmegenwww.cs.ru.nl/~clean.

Similar presentations


Presentation on theme: "I-Tasks - interactive workflow Tasks for the WWWEB ___________ Rinus Plasmeijer University of Nijmegenwww.cs.ru.nl/~clean."— Presentation transcript:

1 i-Tasks - interactive workflow Tasks for the WWWEB ___________ Rinus Plasmeijer University of Nijmegenwww.cs.ru.nl/~clean

2 2 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

3 3 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

4 4 Clean  State-Of-The-Art Pure Functional Programming Language  Lazy, pure, higher order functions and types, lots of features  Clean is an extended subset of Haskell – de-facto standard (GHC)  Haskell is an extended subset of Clean  Extra facilities in Clean:  I/O: Uniqueness Typing Monads  Re-usage: Generic programming included Generic Haskell preprocessor  Hybrid typing: Static as well as Dynamic typing poor man's Dynamics  Type safe plug-inns: run-time storing and loading of functions  Sparkle: Cleans dedicated theorem prover  Gast: Cleans test system  Clean Compiler is fast (4 th place language shootout, after 3 C compilers !)  2 third party Haskell -> Clean compilers  Haskell / Clean code can be combined in next Clean release

5 5 Why workflows?  Dutch STW grant “Demand Driven Workflows” New approach on specifying workflows making use of "lazy evaluation" University:TU Eindhoven (Van der Aalst) RadBoud University Nijmegen (Plasmeijer) Industry:Palas Athena (Eindhoven): producer of commercial workflow system ABZ (Utrecht): uses workflow system for developing applications AIA (Nijmegen): produces content management systems  i -Tasks First, "simple" approach to make a quick start  Already offers more functionality than found in commercial systems  “i –Tasks: Executable Specifications of Interactive Workflow Systems for the Web”, R.Plasmeijer, P.Achten, P.Koopman, ICFP  see:

6 6 i -Tasks Approach I  Study “Workflow Patterns” (Van der Aalst, ter Hofstede, Kiepuszewski, Barros)  > 30 products: Staffware, Cosa, InConcert, Eastman Software, FLOWer, Domino Workflow, Meteor, Mobile, MQSeries, Forte Conductor, Verve, Visual WorkFlo, Changengine, I-Flow, SAP R/3 Workflow  patterns: sequence, recursion, exclusive choice, multiple choice, split/merge (parallel or, parallel and, discriminator),...  All Workflow Patterns can "straightforwardly" be implemented in Clean  Using i-Data: Clean library for handling interactive web forms  Using generic functions: highly reusable functions, given a type they  generate an html form  deal with any change made by a user in a form  enable separation between model (value returned) and view (the looks)  automatically store and retrieve info in a file or database

7 7 i -TasksApproach II Disadvantages i –Tasks over Commercial Systems  No nice graphical interface for defining workflows: just Clean code  A first prototype, limited interfaces to real world, lots of additional wishes Advantages i –Tasks over Commercial Systems  Declarative, executable specification  Workflows are statically typed, input type checked as well  Highly reusable code: polymorphic, overloaded, generic  Workflows are dynamically constructed  Flow can depend on the actual contents  Fully compositional  Higher order tasks: shift work flows to someone else  It generates a multi-user web enabled (!) workflow system  < 1000 lines of code based on Clean’s i-Data library for the web

8 8 i -Tasks Approach III  Web applications are not easy to write  Interactive applications for the Web are hard to programme »No direct connection between User on Client Application on Server »Web has no notion of state: application has to store information  Multi-user applications even harder Offer a layer which hides as many annoying details as possible. i –Tasks - Embedded Domain Specific Language: Workflow Specification Language which generates a multi-user system for the web. i –Tasks – Workflow Combinator Library for Clean

9 9 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

10 10 A very small *complete* example I module example import StdEnv, StdHtml Start world = doHtmlServer (singleUserTask 0 True simple) world simple simple :: (Task Int) simple = editTask "Done" createDefault

11 11 Testing an i –Tasks application Changes in Forms i –Tasks Application Browser Http 1.0 Web Server Htmlcode Clean Application

12 12 Final setting of an i –Tasks application Changes in Forms i –Tasks Application 1 Browser Http 1.1 Web Server Htmlcode i –Tasks Application 2i –Tasks Application n

13 13 A very small *complete* example II module example import StdEnv, StdHtml Start world = doHtmlServer (singleUserTask 0 True simple) world simple simple :: (Task (Int, Real)) simple = editTask "Done" createDefault

14 14 A very small *complete* example III simple simple :: (Task [Int]) simple = editTask "Done" createDefault

15 15 A very small *complete* example IV :: Person = { name :: String, street :: String, number :: Int, zipCode :: String, town :: String, born:: HtmlDate } simple simple :: (Task Person) simple = editTask "Done" createDefault derive gForm Person derive gUpd Person derive gParse Person derive gPrint Person derive gerda Person

16 16 editTask editTask :: String a  (Task a)| iData a// an editor for values of type "a" :: Task a // an interactive task A task consist of an amount of work to be performed by the user involving ≥ 0 interactions It is either not active, active, or finished.

17 17 editTask uses generic functions class iData a | gForm {|*|}, iCreateAndPrint, iParse, iSpecialStore a class iCreateAndPrint a | iCreate, iPrint a class iCreate a | gUpd {|*|} a class iPrint a| gPrint {|*|} a class iParse a| gParse {|*|} a class iSpecialStore a| gerda {|*|}, TC a It requires the instantiation of several generic functions for type "a" e.g. gForm html form creation, gUpd form handling, gParse parsing, gPrint printing, gerda data storage I a relational database, TCConversion to and from Dynamics, option used to store functions which can all, on request, automatically be derived by the compiler !

18 18 Options A task or combination of tasks, can have several options: class infixl 3 b :: (Task a) b  Task a instance default: Session, StorageFormat// default: PlainString, Mode// default: Edit, GarbageCollect// deafult: Collect :: Lifespan= Database | TxtFile | Session | Page | Temp :: StorageFormat= StaticDynamic | PlainString :: Mode= Edit | Submit | Display | NoForm :: GarbageCollect = Collect | NoCollect

19 19 A very small *complete* example IV simple simple :: (Task Person) simple = editTask "Done" createDefault

20 20 A very small *complete* example IV Submit simple simple :: (Task Person) simple = editTask "Done" createDefault Submit

21 21 A very small *complete* example IV, Submit, Database simple simple :: (Task Person) simple = editTask "Done" createDefault Submit Database

22 22 A very small *complete* example IV, Submit, TxtFile simple simple :: (Task Person) simple = editTask "Done" createDefault Submit TxtFile

23 23 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

24 24 Sequencing of tasks Sequencing / composition of tasks (monadic style): (=>>) infix 1 :: (Task a) (a  Task b)  Task b (#>>) infixl 1 :: (Task a) (Task b)  Task b Returning plain values as a Task value return_V :: a  Task a | iData a

25 25 Prompting Returning plain values as a Task value (showing the returned value): return_D :: a  Task a | iData a Prompting as long as / as soon as a task is activated: (?>>) infix 5 :: [BodyTag] (Task a)  Task a| iData a (!>>) infix 5 :: [BodyTag] (Task a)  Task a| iData a

26 26 Html code A Clean Algebraic Data Type (ADT) is defined isomorphic with Html Code  Provides a grammar only allowing syntactic "correct" html code  Type error otherwise  A generic function is used to generate Html code out of it :: BodyTag = A [A_Attr] [BodyTag]// link ancor | Abbr [Std_Attr] String// abbreviation | Acronym[Std_Attr] String// acronym | Address[Std_Attr] String// address | Applet[Applet_Attr] String// applet | Area[Area_Attr]// link area in an image | B [Std_Attr] String// bold … | TxtString // plain text | U[Std_Attr] String// underlined text | Ul [Ul_Attr] [BodyTag]// unordered list | Var[Std_Attr] String// variable text

27 27 Sequence of iTasks sumInt sumInt :: (Task Int) sumInt = editTask "Done" createDefault =>> \v1  editTask "Done" createDefault =>> \v2  [Txt "+", Hr [] ] !>> return_D (v1 + v2)

28 28 Simple Coffeemachine (1/3)Coffeemachine

29 29 Simple Coffeemachine (2/3)Coffeemachine simpleCoffee simpleCoffee = foreverTask SimlpeCoffeeMachine SimlpeCoffeeMachine :: (Task String) SimlpeCoffeeMachine = [Txt "Choose product:",Br,Br] ?>> chooseTask [ ("Coffee", return_V ("Coffee")), ("Tea", return_V ("Tea")) ] =>> \product  [Txt ("Enjoy your " <+++ product)] ?>> chooseTask [ "OK“, return_V product]

30 30 Simple Coffeemachine (3/3)Coffeemachine simpleCoffee simpleCoffee = foreverTask SimlpeCoffeeMachine SimlpeCoffeeMachine :: (Task String) SimlpeCoffeeMachine = [Txt "Choose product:",Br,Br] ?>> chooseTask [ ("Coffee", return_V ("Coffee")), ("Tea", return_V ("Tea")) ] =>> \product  [Txt ("Enjoy your " <+++ product)] ?>> buttonTask "OK" (return_V product)

31 31 All kinds of task combinators Loop: foreverTask:: (Task a)  (Task a) | iData a Choose 1 out of n: chooseTask:: [(String,Task a)]  (Task a) | iData a Choose m out of n: mchoiceTasks :: [(String,Task a)]  (Task [a])| iData a Or task, do all in any order, finish as soon as one completes (-||-) infixr 3:: (Task a) (Task a)  (Task a) | iData a orTasks:: [(String,Task a)]  (Task a) | iData a And task, do all in any order, and finish when all completed (-&&-) infixr 4:: (Task a) (Task b)  (Task (a,b)) | iData a & iData b andTasks:: [(String,Task a)]  (Task [a])| iData a Treat user defined function as a new task: enables recursion newTask :: String (Task a)  (Task a) | iData a

32 32 Coffeemachine Coffeemachine (1/3)

33 33 Coffeemachine (2/3) infCoffee infCoffee = foreverTask CoffeeMachine CoffeeMachine :: Task (String, Int) CoffeeMachine = [Txt "Choose product:", Br, Br] ?>> chooseTask [ ("Coffee: 100", return_V (100,"Coffee")), ("Cappucino: 150",return_V (150,"Cappucino")), ("Tee: 50",return_V (50, "Tee")), ("Choclate: 100",return_V (100,"Choclate")) ] =>> \(toPay, product)  [Txt ("Chosen product: " <+++ product), Br, Br] ?>> getCoins (toPay, 0) =>> \(cancel, returnMoney)  let nproduct = if cancel "Cancelled" product in [Txt ("product = " <+++ nproduct <+++ ", returned money = " <+++ returnMoney), Br, Br] ?>> buttonTask "Thanks" (return_V (nproduct, returnMoney))

34 34 Coffeemachine (3/3) getCoins :: (Int, Int) -> Task (Bool, Int) getCoins (toPay, paid) = newTask "getCoins" getCoins` where getCoins` = [Txt ("To pay: " <+++ toPay), Br, Br] ?>> chooseTask [ (c +++> " cts", return_V (False, c)) \\ c  coins ] -||- buttonTask "Cancel" (return_V (True, 0)) =>> handleMoney handleMoney (cancel, coin) | cancel= return_V (True, paid) | toPay - coin > 0= getCoins (toPay - coin, paid + coin) | otherwise= return_V (False, coin - toPay) coins = [ 5, 10, 20, 50, 100, 200 ]

35 35 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

36 36 Multi-user combinators Multi-user : infix 3 :: (String, Int) (Task a)  (Task a) | iData a infix 3 :: Int (Task a)  (Task a) | iData a

37 37 Multi-User example: Review Task

38 38 Multi-User example: Review Task

39 39 Review Task (1/3) :: Review = Approved | Cancelled | NeedsRework TextArea | Draft reviewTask reviewTask :: a  (Task Review) | iData a reviewTask v = [toHtml v, Br, Br] ?>>chooseTask [ ("Rework", editTask "Done" (NeedsRework createDefault) Submit), ("Approved", return_V Approved), ("Reject", return_V Rejected) ]

40 40 Review Task (2/3) taskToReview :: Int (a, a  Task a)  Task (a, Review) | iData a taskToReview reviewer (val, task) = newTask "taskToReview" taskToReview` where taskToReview` =task val =>> \newval  reviewTask newval =>> \review  [Txt ("Reviewer " <+++ reviewer <+++ " says "), toHtml review, Br] ?>> editTask "OK" Void #>>case review of (NeedsRework _)  taskToReview reviewer (newval, task) else  return_V (newval, review)

41 41 Review Task (3/3) :: QForm = { toComp :: String, startDate :: HtmlDate, endDate :: HtmlDate, estimatedHours :: Int, description:: TextArea, price:: Real } startTask startTask :: Task (QForm, Review) startTask = taskToReview 1 (createDefault, mytask) mytask :: a  (Task a) | iData a mytask v = [Txt "Fill in Form:", Br, Br] ?>> editTask "TaskDone" v Submit

42 42 Higher-Order Tasks Tasks not only deliver values, they may deliver a task under development ! :: TClosure a = TClosure (Task a) :: Maybe a= Just a | Nothing orTask variant: a task is either finished, or interrupted if the stop task is finished sooner (-!>) infix 4 :: (Task stop) (Task a)  (Task (Maybe stop, TClosure a)) | iData stop & iData a

43 43 Multi-User example: delegate a task

44 44 Delegate a Task delegateToSomeone delegateToSomeone :: Int (Task a) [Int]  (Task a) | iData a delegateToSomeone me task set = newTask "delegateToSomeone" doDelegate where doDelegate = orTasks [ ("Waiting for " <+++ who, chooseTask [("I Will Do It“, return_V who)] ) \\ who  set ] =>> \volunteer  stopIt -!> task =>> \(stopped, TClosure task)  if (isJust stopped) (delegateToSomeone me task set) task stopIt = stop -||- stop) stop = chooseTask [("Stop“, return_V True)]

45 45 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

46 46 Login handling types and functions … :: Accounts s:== [Account s] :: Account s = { login :: Login// login info, uniqueId:: Int// unique identifier, state:: s// state } :: Login ={ loginName :: String// Should be unique, password:: PasswordBox// Should remain secret } :: Maybe a = Just a | Nothing addAccount :: (Account s) (Accounts s)  (Accounts s) removeAccount :: (Account s) (Accounts s)  (Accounts s) changeAccount :: (Account s) (Accounts s)  (Accounts s) hasAccount :: Login(Accounts s)  (Maybe (Account s)) invariantLogins :: String [Login]  Maybe (String,String)

47 47 iTasks can be used for persistent storage of information definition module iTaskDB import iTasks :: DBid a mkDBid :: String Lifespan  (DBid a) readDB:: (DBid a)  Task a | iData a writeDB:: (DBid a) a  Task a | iData a

48 48 Creating a database for a login accounts… accountId :: DBid (Accounts a) accountId = mkDBid "loginAccount" TxtFile readAccountsDB :: (Task (Accounts a)) | iData a readAccountsDB = readDB accountId addAccountsDB :: (Account a) (Accounts a)  (Task (Accounts a)) | iData a addAccountsDB acc accs = writeDB accountId (addAccount acc accs)

49 49 Creating a database for a login accounts… accountId :: DBid (Accounts a) accountId = mkDBid "loginAccount" Database readAccountsDB :: (Task (Accounts a)) | iData a readAccountsDB = readDB accountId addAccountsDB :: (Account a) (Accounts a)  (Task (Accounts a)) | iData a addAccountsDB acc accs = writeDB accountId (addAccount acc accs)

50 50 Creating a database for a login accounts… :: Void = Void accountId :: DBid (Accounts Void) accountId = mkDBid "loginAccount" TxtFile readAccountsDB :: (Task (Accounts Void)) readAccountsDB = readDB accountId addAccountsDB :: (Account Void) (Accounts Void)  (Task (Accounts Void)) addAccountsDB acc accs = writeDB accountId (addAccount acc accs)

51 51 Handling login's (1) handleLogin :: (Task (Maybe (Account Void))) handleLogin =[Txt "Type in your name and password...", Br, Br] ?>> loginForm =>> \login  readAccountsDB =>> \accounts  return_V (hasAccount login accounts) loginForm :: (Task Login) loginForm = editTask "Done" createDefault Submit

52 52 Handling login's (2) newLogin :: (Task (Account Void)) newLogin = newTask "newLogin" newLogin` newLogin` =[Br, Br, Txt "Type in name and password you want to use...", Br,Br] ?>> loginForm =>> \login  readAccountsDB =>> \accounts  case (invariantLogins "" [login:[account.login \\ account <- accounts]]) of (Just (_,error))  [Txt error, Br, Br] ?>> newLogin Nothing  let newId = length accounts newAccount = { login = login, uniqueId = newId, state = Void } inaddAccountsDB newAccount accounts =>> \_  [Txt ("You are administrated, your id = " <+++ newId)] ?>> buttonTask "OK" (return_V newAccount)

53 53 Handling login's (3) loginProcedure :: (Task Int) loginProcedure = newTask "loginProcedure" loginProcedure` loginProcedure` =chooseTask [ ("Login", handleLogin), ("New Login", newLogin =>> \account -> return_V (Just account)) ] -||- buttonTask "Cancel" (return_V Nothing) =>> \mbacc ->case mbacc of Nothing  [Txt "Sorry, you have to try again!",Br,Br] ?>> buttonTask "OK" loginProcedure (Just acc)  return_V acc.uniqueId

54 54 Defining a multi-user workflow system (1) Start world = doHtmlServer (singleUserTask -1 True myAppl ) world myAppl =loginProcedure =>> \myid  readAccountsDB =>> \accounts  startNewTask myid True (assignTasks accounts TxtFile) assignTasks accounts = andTasks [ ( acc.login.loginName, assignWork acc.login.loginName acc.uniqueId ) \\ acc <- accounts ] assignWork name i = …

55 55 Defining a multi-user workflow system (2) assignWork :: Bool // traceOn (Task Void) // welcome task (acc  Task acc) // administration task ((String,Int,acc)  (Task a)) // \name uniqueid admin ->  (Task [a]) | iData acc & iData a Examples:  newsgroups newsgroups  marking marking

56 56 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

57 57 Generic programming Some functions are more or less the same: equality, unification, mapping, zipping, folding, pretty printers, parsers, generators, GAST: automatic test system Graphical User Interfaces ??? Define the general case once and for all by induction on the structure of data types. Automatically obtain a concrete function for any concrete data type ! Applicable for quite a large class of algorithms… Exceptions make the rule ! One can define specialized instances for special types…

58 58 Example types :: List a = Nil | Cons a (List a) :: Rose a= Rose a (List (Rose a)) :: Tree a b = Tip a | Bin b (Tree a b) (Tree a b)

59 59 Overloaded equality class == infix 4 t :: t t  Bool instance == (List a) | == a where(==) Nil Nil= True (==) (Cons x xs) (Cons y ys)= x == y && xs == ys (==) _ _= False instance == (Rose a) | == a where(==) (Rose x xs) (Rose y ys)= x == y && xs == ys (==) _ _= False instance == (Tree a b) | == a & == b where(==) (Tip x) (Tip y) = x == y (==) (Bin x ltx rtx) (Bin y lty rty) = x == y && ltx == lty && rtx == rty (==) _ _ = False

60 60 List a The idea of generic programming List b Rose aRose b Map_Rose Map_List

61 61 List a The idea of generic programming List b Rose aRose b Generic aGeneric b Map_Rose Map_Generic Map_List

62 62 List a The idea of generic programming List b Rose aRose b Generic aGeneric b Map_Rose toRosefromRose Map_Generic Map_List fromListtoList

63 63 Generic programming We need a generic representation: a way to represent any value of any type Clean is typed: what is the type of such a representation ? One generic type which can represent all possible types not possible: type correctness of programs becomes undecidable one would obtain a complete different system Solution: use a couple of simple types to represent any type !

64 64 Generic type representation Example types :: List a= Nil | Cons a (List a) :: Rose a = Rose a (List (Rose a)) :: Tree a b = Tip a | Bin b (Tree a b) (Tree a b) Binary sums and products (in generic prelude) :: UNIT = UNIT :: PAIR a b = PAIR a b :: EITHER a b = LEFT a | RIGHT b Generic type representations :: ListG a :== EITHER UNIT (PAIR a (List a)) :: RoseG a :== PAIR a (List (Rose a)) :: TreeG a b :== EITHER a (PAIR b (PAIR (Tree a b) (Tree a b)))

65 65 Generic type representation Conversions to the generic domain can be automatically generated fromList :: (List a)  ListG a fromList Nil = LEFT UNIT fromList (Cons a as)= RIGHT (PAIR a as) fromRose :: (Rose a)  RoseG a fromRose (Rose a list_of_roses) = PAIR a list_of_roses fromTree :: (Tree a b)  TreeG a b fromTree (Tip a) = LEFT a fromTree (Bin b leftTree rightTree) = RIGHT (PAIR b (PAIR leftTree rightTree))

66 66 Generic type representation Conversions back to the user domain can be automatically generated toList :: (ListG a)  List a toList LEFT UNIT= Nil toList (RIGHT (PAIR a as))= Cons a as toRose :: (RoseG a)  Rose a toRose (PAIR a list_of_roses)= Rose a list_of_roses toTree :: (TreeG a b)  Tree a b toTree (LEFT a)= Tip a toTree (RIGHT (PAIR b (PAIR leftTree rightTree))) = Bin b leftTree rightTree

67 67 Generic equality generic gEq a :: a a  Bool gEq {|Int|} x y = x == y gEq {|Char|} x y = x == y gEq {|Bool|} x y = x == y gEq {|Real|} x y = x == y gEq {|String|} x y = x == y gEq {|UNIT|} UNIT UNIT = True gEq {|PAIR|} eqx eqy (PAIR x1 y1) (PAIR x2 y2) = eqx x1 x2 && eqy y1 y2 gEq {|EITHER|} eqx eqy (LEFT x) (LEFT y) = eqx x y gEq {|EITHER|} eqx eqy (RIGHT x) (RIGHT y) = eqy x y gEq {|EITHER|} eqx eqy _ _ = False gEq {|MyType|} …=

68 68 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

69 69 editTask uses generic functions class iData a | gForm {|*|}, iCreateAndPrint, iParse, iSpecialStore a class iCreateAndPrint a | iCreate, iPrint a class iCreate a | gUpd {|*|} a class iPrint a| gPrint {|*|} a class iParse a| gParse {|*|} a class iSpecialStore a| gerda {|*|}, TC a It requires the instantiation of several generic functions for type "a" e.g. gForm html form creation, gUpd form handling, gParse parsing, gPrint printing, gerda data storage I a relational database, TCConversion to and from Dynamics, option used to store functions which can all, on request, automatically be derived by the compiler !

70 70 Implementation architecture v :: T Clean Application

71 71 Implementation architecture Browser Web Server File / Data Base v :: T Clean Application gForm: Html code Html code serialize: gPrint store: gerda

72 72 Implementation architecture Browser Web Server File / Data Base

73 73 Implementation architecture Browser Web Server File / Data Base ∆v :: T ∆v v :: T Clean Application ∆v :: T ∆v de-serialize: gParse retrieve: gerda gUpd: v` :: T

74 74 Implementation architecture Browser Web Server File / Data Base v :: T ∆v :: T ∆v Clean Application ∆v :: T ∆v gForm: Html code Html code serialize: gPrint store: gerda de-serialize: gParse retrieve: gerda v :: T gUpd: v` :: T

75 75 Generic functions used for i-Tasks / i-Data The following generic functions are used: generic gForm a :: (Init, FormId a) *HSt  *(Form a, *HSt) can create an interactive Html form for any value of any type generic gUpd a :: UpdMode a  (UpdMode, a) can update a value of any type given any change made in a form generic gPrint a :: a  String can serialize a value of any (first-order) Clean type to store a form state in a page, file or database generic gParse a :: String  Maybe a can de-serialize a value of any (first-order) Clean type to re-construct a form state

76 76 Generating forms generic gForm a :: (Init, FormId a) *HSt  *(Form a, *HSt) :: FormId a ={ id :: String// id *uniquely* identifying the form, initval:: a // initial value (Init) or new value (Set), mode:: Mode// kind of form, lifespan:: Lifespan// where to store it, and for how long, storage:: StorageFormat // storage format }

77 77 Generating forms generic gForm a :: (Init, FormId a) *HSt  *(Form a, *HSt) :: FormId a ={ id :: String// id *uniquely* identifying the form, initval:: a // initial value (Init) or new value (Set), mode:: Mode// kind of form, lifespan:: Lifespan// where to store it, and for how long, storage:: StorageFormat // storage format } :: Init= Init |Set :: Mode= Edit | Submit | Display | NoForm :: Lifespan= Database | TxtFile | Session | Page | Temp :: StorageFormat= StaticDynamic | PlainString

78 78 Generating forms generic gForm a :: (Init, FormId a) *HSt  *(Form a, *HSt) :: FormId a ={ id :: String// id *uniquely* identifying the form, initval:: a // initial value (Init) or new value (Set), mode:: Mode// kind of form, lifespan:: Lifespan// where to store it, and for how long, storage:: StorageFormat // storage format } :: Init= Init |Set :: Mode= Edit | Submit | Display | NoForm :: Lifespan= Database | TxtFile | Session | Page | Temp :: StorageFormat= StaticDynamic | PlainString :: *HSt// State passed around single threadedly

79 79 Generating forms generic gForm a :: (Init, FormId a) *HSt  *(Form a, *HSt) :: FormId a ={ id :: String// id *uniquely* identifying the form, initval:: a // initial value (Init) or new value (Set), mode:: Mode// kind of form, lifespan:: Lifespan// where to store it, and for how long, storage:: StorageFormat // storage format } :: Init= Init |Set :: Mode= Edit | Submit | Display | NoForm :: Lifespan= Database | TxtFile | Session | Page | Temp :: StorageFormat= StaticDynamic | PlainString :: *HSt// State passed around single threadedly :: Form a ={ changed :: Bool// has the user edited the form ?, value:: a // current value in data domain (feel), form:: [BodyTag] // html code representing view domain (look) }

80 80 Updating a value (1) How can we reconstruct a value that has been changed interactively ? We only need to know 3 things:  Which type was it and what was its original value?  Which parts have been changed in the original value? »We don't need any knowledge about the html code ! »We only need to know which values have been changed »We just need the position in its generic representation  What are the changed values ?  Simple case: only a few basic cases: »Change existing value: Int, Real, String, Bool, … »Create new values: When you select a constructor  Complication : change of form may depend on the change of others

81 81 Updating a value (2) generic gUpd a :: UpdMode a  (UpdMode,a) :: UpdMode= UpdSearch UpdValue Pos // search for position | UpdCreate [ConsPos]// in generic representation | UpdDone// copy the remaining expression :: UpdValue = UpdI Int// new Integer value | UpdR Real // new Real value | UpdB Bool // new Boolean value | UpdS String// new String value | UpdC String // new Constructor value :: ConsPos = ConsLeft | ConsRight :: Pos:== Int

82 82 Updating a value (3) gUpd {|Int|} (UpdSearch (UpdI ni) 0)_ = (UpdDone,ni) gUpd {|Int|} (UpdSearch val cnt) i = (UpdSearch val (cnt - 1), i) gUpd {|Int|} (UpdCreate p) _ = (UpdCreate p, 0) gUpd {|Int|} mode i = (mode, i)

83 83 Snapshot from Clean's CD shop

84 84 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

85 85 What do we need for iTasks ?  We need a notion of “tasks”: inactive, active, and completed  There is only one application for all users  This application starts from scratch each time information is communicated  The web has no notion of state, we have to store all relevant information  We have to be able to find out what we were doing -> functions + iData  We need to invent unique id’s for a form and its corresponding state  Careful: tasks are dynamically created, can be recursive !  We have to find out which tasks are active and deal with them  We have to support all options  If active tasks are completed, we have to activate the next set of tasks  We have to display the tasks in an understandable way  We have to find out who has to do what, and show relevant information only  We have to deal with multi-user aspects  We have to gather trace information  We have to remove unneeded administration of completed tasks

86 86 iTask Administration State :: *TSt ={ tasknr :: [Int] // unique form-id for every task, activated:: Bool // if assigned activate, if returned completed, userId:: Int// id of user who has to do the task, currentUserId:: Int// id of current application user, html:: HtmlTree// accumulator for html code, options:: Options// iData and iTasks options, hst:: *HSt// iData state, trace:: Maybe [Trace]// for displaying task trace }

87 87 iTask Administration State :: *TSt ={ tasknr :: [Int] // unique form-id for every task, activated:: Bool // if assigned activate, if returned completed, userId:: Int// id of user who has to do the task, currentUserId:: Int// id of current application user, html:: HtmlTree// accumulator for html code, options:: Options// iData and iTasks options, hst:: *HSt// iData state, trace:: Maybe [Trace]// for displaying task trace } :: HtmlTree= BT [BodyTag]// html code | infix 0 (Int,String) HtmlTree// code with user id and task name | infix 0 Int HtmlTree// code not to display to user id | (+-+) infixl 1 HtmlTree HtmlTree// place code next to each other | (+|+) infixl 1 HtmlTree HtmlTree// place code below each other

88 88 iTask Administration State :: *TSt ={ tasknr :: [Int] // unique form-id for every task, activated:: Bool // if assigned activate, if returned completed, userId:: Int// id of user who has to do the task, currentUserId:: Int// id of current application user, html:: HtmlTree// accumulator for html code, options:: Options// iData and iTasks options, hst:: *HSt// iData state, trace:: Maybe [Trace]// for displaying task trace } :: HtmlTree= BT [BodyTag]// html code | infix 0 (Int,String) HtmlTree// code with user id and task name | infix 0 Int HtmlTree// code not to display to user id | (+-+) infixl 1 HtmlTree HtmlTree// place code next to each other | (+|+) infixl 1 HtmlTree HtmlTree// place code below each other :: Options ={ tasklife:: Lifespan// default: Session, taskstorage:: StorageFormat// default: PlainString, taskmode:: Mode// default: Edit, gc:: GarbageCollect// default: Collect }

89 89 Activating a task (simplified) :: Task a:== *TSt  *(a,*TSt)

90 90 Activating a task (simplified) :: Task a:== *TSt  *(a,*TSt)  Each task is assumed to call doTask  increment task number, such that this number is unique;  when activated call the task, create a default value otherwise;  when a task is finished, activate is returned True, False otherwise.

91 91 Activating a task (simplified) :: Task a:== *TSt  *(a,*TSt)  Each task is assumed to call doTask  increment task number, such that this number is unique;  when activated call the task, create a default value otherwise;  when a task is finished, activate is returned True, False otherwise. doTask :: String (Task a)  (Task a) | iCreateAndPrint a doTask taskname thistask = mkTaskNoInc taskname thistask o incTaskNr where mkTaskNoInc taskname thistask tst=:{activated, tasknr, options} | not activated= (createDefault, tst) # (val,tst)= thistask tst = (val, {tst & tasknr = tasknr, options = options}) incTaskNr tst = {tst & tasknr = incNr tst.tasknr} whereincNr [] = [0] incNr [i:is] = [i+1:is]

92 92 The bind is now easy... a standard bind can be used (=>>) infix 1 :: (Task a) (a  Task b)  Task b (=>>) taska taskb = bind where bind tst # (a, tst) = taska tst = taskb a tst (#>>) infix 1 :: (Task a) (Task b)  Task b (#>>) taska taskb = bind where bind tst # (_, tst) = taska tst = taskb tst

93 93 A simple combinator: ?>> (?>>) infix 5 :: [BodyTag] (Task a) -> (Task a) | iCreate a (?>>) prompt thistask = myTask where myTask tst=:{html, activated} | not activated= (createDefault, tst) # (a, tst=:{activated, html = nhtml}) = thistask {tst & html = BT []} | activated = (a, {tst & html = html}) = (a, {tst & html = html +|+ BT prompt +|+ nhtml})

94 94 A simple combinator: -&&- (-&&-) infixr 4 :: (Task a) (Task b)  (Task (a,b)) | iCreateAndPrint a & iCreateAndPrint b (-&&-) taska taskb = mkTask "-&&-" (doAndTask (taska, taskb)) doAndTask (taska, taskb) tst=:{tasknr, html} # (a, tst=:{activated = adone, html = ahtml}) = mkParSubTask "andTask" 0 taska {tst & html = BT []} # (b, tst=:{activated = bdone, html = bhtml}) = mkParSubTask "andTask" 1 taskb {tst & tasknr = tasknr, html = BT []} = ((a,b), {tst & activated = adone && bdone, html = html +|+ ahtml +|+ bhtml})

95 95 A simple combinator: -&&- (-&&-) infixr 4 :: (Task a) (Task b)  (Task (a,b)) | iCreateAndPrint a & iCreateAndPrint b (-&&-) taska taskb = mkTask "-&&-" (doAndTask (taska, taskb)) doAndTask (taska, taskb) tst=:{tasknr, html} # (a, tst=:{activated = adone, html = ahtml}) = mkParSubTask "andTask" 0 taska {tst & html = BT []} # (b, tst=:{activated = bdone, html = bhtml}) = mkParSubTask "andTask" 1 taskb {tst & tasknr = tasknr, html = BT []} = ((a,b), {tst & activated = adone && bdone, html = html +|+ ahtml +|+ bhtml}) mkParSubTask name i task tst = task (newSubTaskNr (setActivated (subTaskNr i tst))) subTaskNr i tst= { tst & tasknr = [ i : tst.tasknr] } newSubTaskNr tst = { tst & tasknr = [-1 : tst.tasknr] } setActivated tst = { tst & activated = True }

96 96 Clean  Introduction  Defining Interactive Multi-user Workflow Systems for the web  Defining a simple task: an editor for a web form  Combinators for constructing tasks  Assigning tasks to users  Logging in to a Multi-user Workflow System  Implementation  Basic idea of generic programming  Generic functions for handling web forms: i-Data  Implementation of i-Tasks  Conclusion & Future Research

97 97 Conclusions  Compact specification, many details are handled automatically  very intuitive  All "standard" workflows patterns offered  but we are lacking a graphical editor...  Offers a lot of additional expressive power  Typed  Workflows are dynamically generated  Additional Workflow Patterns: lazy send / receive, -!>  Higher Order Workflows  Highly re-usable code  First industrial real-world application has been made (Car Damage Negotiation System, ABZ)

98 98 Future Work  Show applicability via more, large real world applications  Combine with Client site evaluation  Fast Clean interpreter (Jan-Martin Jansen) running in browser  add “Ajax” technology  Integrate with main stream web development tools (Dreamweaver)  Improve performance  Practical issues: What is the ideal set of combinators ?  Can we exploit lazy evaluation ?  Theoretical issues: What is the minimal set of combinators ?  How does it compare with other approaches: Petri Nets, Process Algebra, μCRL ?  Can we prove properties of a workflow system ?  What kind of static properties can we analyse ?


Download ppt "I-Tasks - interactive workflow Tasks for the WWWEB ___________ Rinus Plasmeijer University of Nijmegenwww.cs.ru.nl/~clean."

Similar presentations


Ads by Google