#created on: 4/11/2008 package org.openiaml.model.drools.rules.login_handler #list any import classes here. import org.openiaml.model.drools.*; import org.openiaml.model.inference.*; import org.openiaml.model.model.*; import org.openiaml.model.model.impl.*; import org.openiaml.model.model.wires.*; import org.openiaml.model.model.visual.*; import org.openiaml.model.model.operations.*; import org.openiaml.model.model.scopes.*; import org.openiaml.model.model.components.*; import org.openiaml.model.model.users.*; #declare any global variables here global EcoreCreateElementsHelper handler; global DroolsInsertionQueue queue; global DroolsHelperFunctions functions; rule "Create 'login' page for LoginHandlers [ApplicationElementContainer]" when container : ApplicationElementContainer( ) scope : Scope( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) not (Page (eContainer == container, name=="login" )) then Page login = handler.generatedPage(login_handler, container); handler.setName(login, "login"); queue.add(login, drools); end rule "Create 'login' page for LoginHandlers [InternetApplication]" when container : InternetApplication( ) scope : Scope( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) not (Page (eContainer == container, name=="login" )) then Page login = handler.generatedPage(login_handler, container); handler.setName(login, "login"); queue.add(login, drools); end rule "Create 'logout' page for LoginHandlers" when scope : Session( ) login_handler : LoginHandler( eContainer == scope ) not (Page (eContainer == scope, name=="logout" )) then Page logout = handler.generatedPage(login_handler, scope); handler.setName(logout, "logout"); queue.add(logout, drools); end rule "Instruct 'logout' page to follow to the actual logout destination if set" when scope : Session( ) login_handler : LoginHandler( eContainer == scope ) logout : Page (eContainer == scope, name=="logout" ) destination : Page ( this != logout ) navigate : NavigateWire ( from == login_handler, to == destination, name == "logout") access : EventTrigger ( eContainer == logout, name == "access" ) not (NavigateWire ( from == access, to == destination )) then NavigateWire wire = handler.generatedNavigateWire(login_handler, logout, access, destination); handler.setName(wire, "redirect to intended logout page"); queue.add(wire, drools); end rule "Create 'key attribute' property for LoginHandler[type = key]s" when scope : Session( ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.SECRET_KEY ) not (ApplicationElementProperty (eContainer == scope, name=="current login key" ) ) # the value may not be called "current login key" not ( exists ( actual_key : ApplicationElementProperty ( ) and SetWire ( name == "set", from == login_handler, to == actual_key ) ) ) then ApplicationElementProperty key = handler.generatedApplicationElementProperty(login_handler, scope); handler.setName(key, "current login key"); # need to set a default value, or else require_session(this) will throw an exception before we can catch it to redirect handler.setValue(key, ModelPackage.eINSTANCE.getApplicationElementProperty_DefaultValue(), ""); queue.add(key, drools); end rule "Connect 'key' property to LoginHandler" when scope : Session( ) login_handler : LoginHandler( eContainer == scope ) key : ApplicationElementProperty (eContainer == scope, name == "current login key") not (SetWire( from == login_handler, to == key, name == "set") ) then SetWire wire = handler.generatedSetWire(login_handler, scope, login_handler, key); handler.setName(wire, "set"); queue.add(wire, drools); end rule "Create 'check key' operation for LoginHandler[type = key]" when scope : Session( ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.SECRET_KEY ) not (Operation( eContainer == scope, name == "check key") ) then CompositeOperation op = handler.generatedCompositeOperation( login_handler, scope ); handler.setName(op, "check key"); queue.add(op, drools); end rule "Connect 'access' event to 'check' operations" when scope : Session( ) page : Page( eContainer == scope ) access : EventTrigger( name == "access", eContainer == page ) check : CompositeOperation( name == "check key" || name == "check instance", eContainer == scope ) not (RunInstanceWire( from == access, to == check )) then RunInstanceWire wire = handler.generatedRunInstanceWire(scope, page, access, check); handler.setName(wire, "run"); handler.setValue(wire, WiresPackage.eINSTANCE.getRunInstanceWire_Priority(), 100); // high priority queue.add(wire, drools); end rule "Connect 'login key' parameter to 'check key' operation run wire" when scope : Session( ) page : Page( eContainer == scope ) access : EventTrigger( name == "access", eContainer == page ) check : CompositeOperation( name == "check key", eContainer == scope ) login_handler : LoginHandler( eContainer == scope ) value : ApplicationElementProperty( ) mySetWire : SetWire( from == login_handler, to == value, name == "set" ) wire : RunInstanceWire( from == access, to == check ) not (ParameterWire( from == value, to == wire )) then ParameterWire param = handler.generatedParameterWire(scope, page, value, wire); handler.setName(param, "[sessions] 'login key' parameter to 'check key'"); queue.add(param, drools); end rule "Connect 'fail' wire from 'check key' or 'check instance' operation to Login Page" when container : ContainsWires( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) login : Page (eContainer == container, name=="login" ) check : CompositeOperation( name == "check key" || name == "check instance", eContainer == scope ) not (CompositeWire( from == check, to == login, name == "fail") ) then NavigateWire fail = handler.generatedNavigateWire(scope, scope, check, login); handler.setName(fail, "fail"); queue.add(fail, drools); end rule "Create contents of 'check key' operation [type=secret_key]" when scope : Session( ) o : CompositeOperation( name == "check key", eContainer == scope ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.SECRET_KEY ) expected : StaticValue( ) expected_param : ParameterWire( from == expected, to == login_handler ) not (StartNode( eContainer == o)) # not (FinishNode( eContainer == o)) - not necessary then Parameter parameter = handler.generatedParameter(o, o); handler.setName(parameter, "current key value"); queue.add(parameter, drools); DecisionOperation op = handler.generatedDecisionOperation(o, o); handler.setName(op, "equal?"); queue.add(op, drools); StartNode start = handler.generatedStartNode(o, o); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(o, o); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(o, o); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "Error: Key check failed. You may need to login."); queue.add(cancel, drools); DataFlowEdge data1 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data1, parameter); handler.setTo(data1, op); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data2, expected); handler.setTo(data2, op); queue.add(data2, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge1, start); handler.setTo(edge1, op); queue.add(edge1, drools); # ok ExecutionEdge edge2 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge2, op); handler.setTo(edge2, finish); queue.add(edge2, drools); # not ok ExecutionEdge edge3 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge3, op); handler.setTo(edge3, cancel); queue.add(edge3, drools); end rule "Create contents of 'check instance' operation [type=domain_object or user]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT || type == LoginHandlerTypes.USER ) instance : DomainObjectInstance ( eContainer == scope ) setWire : SetWire ( from == login_handler, to == instance, name == "set" ) ex : Operation ( eContainer == instance, name == "exists?" ) checkOperation : CompositeOperation ( eContainer == scope, name == "check instance" ) not ( StartNode ( eContainer == checkOperation )) then StartNode start = handler.generatedStartNode(checkOperation, checkOperation); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(checkOperation, checkOperation); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(checkOperation, checkOperation); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "Invalid domain instance, you need to login."); queue.add(cancel, drools); # a virtual operation call # (the 'exists?' operation cannot have more than 2 execution edges out) OperationCallNode call = handler.generatedOperationCallNode(checkOperation, checkOperation); handler.setName(call, "call exists?"); queue.add(call, drools); # connect with a RunInstanceWire RunInstanceWire run = handler.generatedRunInstanceWire(checkOperation, checkOperation, call, ex); handler.setName(run, "virtual operation call"); queue.add(run, drools); ExecutionEdge edge0 = handler.generatedExecutionEdge(checkOperation, checkOperation); handler.setFrom(edge0, start); handler.setTo(edge0, call); queue.add(edge0, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(checkOperation, checkOperation); handler.setFrom(edge1, call); handler.setTo(edge1, finish); queue.add(edge1, drools); ExecutionEdge edge2 = handler.generatedExecutionEdge(checkOperation, checkOperation); handler.setFrom(edge2, call); handler.setTo(edge2, cancel); queue.add(edge2, drools); end /* We don't want the expected login key to connect to the operation: it is already explicitly defined in the Operation itself. rule "Connect expected login key as parameter to check key operation" when scope : Session( ) page : Page( eContainer == scope ) access : EventTrigger( name == "access", eContainer == page ) check : CompositeOperation( name == "check key", eContainer == scope ) wire : RunInstanceWire( from == access, to == check ) login_handler : LoginHandler( eContainer == scope ) expected : StaticValue( ) expected_param : ParameterWire( from == expected, to == login_handler ) not (ParameterWire(from == expected, to == check )) then ParameterWire param = handler.generatedParameterWire(login_handler, page, expected, wire); queue.add(param, drools); end */ rule "Create login form for 'login' pages" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) login : Page (eContainer == container, name=="login" ) not (InputForm( eContainer == login )) then InputForm form = handler.generatedInputForm(login_handler, login); handler.setName(form, "login form"); queue.add(form, drools); Button button = handler.generatedButton(form, form); handler.setName(button, "Login"); queue.add(button, drools); end rule "Connect 'Login' button to 'do login' operation" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) login : Page (eContainer == container, name=="login" ) form : InputForm ( eContainer == login, name == "login form" ) button : Button ( eContainer == form, name == "Login" ) operation : Operation ( eContainer == scope, name == "do login" ) not (RunInstanceWire ( from == button, to == operation, name == "onClick")) then RunInstanceWire run = handler.generatedRunInstanceWire(login_handler, login, button, operation); handler.setName(run, "onClick"); queue.add(run, drools); end rule "Create text fields for login form of 'login' pages [type=secret_key]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.SECRET_KEY ) login : Page (eContainer == container, name=="login" ) form : InputForm( eContainer == login, name == "login form" ) not ( InputTextField ( eContainer == form, name == "login key" )) then InputTextField field = handler.generatedInputTextField(form, form); handler.setName(field, "login key"); # login field name queue.add(field, drools); # field has a value ApplicationElementProperty fieldValue = handler.generatedApplicationElementProperty(field, field); handler.setName(fieldValue, "fieldValue"); queue.add(fieldValue, drools); end rule "Create contents of 'do login' operation [type=secret_key]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.SECRET_KEY ) login : Page (eContainer == container, name=="login" ) value : ApplicationElementProperty( ) mySetWire : SetWire( from == login_handler, to == value, name == "set" ) expected : StaticValue( ) expected_param : ParameterWire( from == expected, to == login_handler ) form : InputForm( eContainer == login, name == "login form" ) button : Button ( eContainer == form, name == "Login" ) field : InputTextField ( eContainer == form, name == "login key" ) fieldValue : ApplicationElementProperty( eContainer == field, name == "fieldValue" ) loginOperation : CompositeOperation ( eContainer == scope, name == "do login" ) runClick : RunInstanceWire ( from == button, to == loginOperation, name == "onClick" ) not ( StartNode ( eContainer == loginOperation )) then # connect field value as parameter ParameterWire clickParam = handler.generatedParameterWire(login_handler, login, fieldValue, runClick); handler.setName(clickParam, "[sessions] field value as param"); queue.add(clickParam, drools); # create contents of login operation Parameter parameter = handler.generatedParameter(loginOperation, loginOperation); handler.setName(parameter, "provided key"); queue.add(parameter, drools); DecisionOperation op = handler.generatedDecisionOperation(loginOperation, loginOperation); handler.setName(op, "equal?"); queue.add(op, drools); StartNode start = handler.generatedStartNode(loginOperation, loginOperation); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(loginOperation, loginOperation); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(loginOperation, loginOperation); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "Invalid key."); queue.add(cancel, drools); DataFlowEdge data1 = handler.generatedDataFlowEdge(loginOperation, loginOperation); handler.setFrom(data1, parameter); handler.setTo(data1, op); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(loginOperation, loginOperation); handler.setFrom(data2, expected); handler.setTo(data2, op); queue.add(data2, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge1, start); handler.setTo(edge1, op); queue.add(edge1, drools); # not ok ExecutionEdge edge2 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge2, op); handler.setTo(edge2, cancel); queue.add(edge2, drools); # ok: set value operation PrimitiveOperation setProperty = handler.generatedPrimitiveOperation(loginOperation, loginOperation); handler.setName(setProperty, "setPropertyToValue"); queue.add(setProperty, drools); DataFlowEdge data3 = handler.generatedDataFlowEdge(loginOperation, loginOperation); handler.setFrom(data3, parameter); handler.setTo(data3, setProperty); queue.add(data3, drools); DataFlowEdge data4 = handler.generatedDataFlowEdge(loginOperation, loginOperation); handler.setFrom(data4, setProperty); handler.setTo(data4, value); queue.add(data4, drools); # ok ExecutionEdge edge3 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge3, op); handler.setTo(edge3, setProperty); queue.add(edge3, drools); # finish ExecutionEdge edge4 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge4, setProperty); handler.setTo(edge4, finish); queue.add(edge4, drools); end rule "Create text fields for login form of 'login' pages [type=domain_object]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT ) login : Page (eContainer == container, name=="login" ) form : InputForm( eContainer == login, name == "login form" ) # from a domain object attribute : DomainAttribute ( ) param : ParameterWire ( from == attribute, to == login_handler ) not ( InputTextField ( eContainer == form, name == attribute.name )) then InputTextField field = handler.generatedInputTextField(form, form); # login field name handler.setName(field, attribute.getName()); queue.add(field, drools); end /** * A LoginHandler[user] uses all of the fields from the given * DomainObject parameter as input fields, except for * any generated primary keys. */ rule "Create text fields for login form of 'login' pages [type=user]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.USER ) login : Page (eContainer == container, name=="login" ) form : InputForm( eContainer == login, name == "login form" ) # from a role role : Role ( ) param : ParameterWire ( from == role, to == login_handler ) # an attribute in that role attribute : DomainAttribute ( eContainer == role, eval(functions.notPrimaryKey(attribute)) ) not ( InputTextField ( eContainer == form, name == attribute.name )) then InputTextField field = handler.generatedInputTextField(form, form); # login field name handler.setName(field, attribute.getName()); queue.add(field, drools); end rule "Connect text fields for login form of 'login' pages to 'do login' run wire [type=domain_object]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT ) login : Page (eContainer == container, name=="login" ) operation : Operation( eContainer == scope, name == "do login" ) form : InputForm( eContainer == login, name == "login form" ) # from a domain object attribute : DomainAttribute ( ) param : ParameterWire ( from == attribute, to == login_handler ) field : InputTextField ( eContainer == form, name == attribute.name ) fieldValue : ApplicationElementProperty ( eContainer == field, name == "fieldValue" ) button : Button ( eContainer == form, name == "Login" ) run : RunInstanceWire ( from == button, to == operation, name == "onClick" ) not ( ParameterWire ( from == fieldValue, to == run, name == attribute.name )) then ParameterWire param2 = handler.generatedParameterWire(login_handler, fieldValue, fieldValue, run); handler.setName(param2, attribute.getName()); queue.add(param2, drools); end rule "Connect text fields for login form of 'login' pages to 'do login' run wire [type=user]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.USER ) login : Page (eContainer == container, name=="login" ) operation : Operation( eContainer == scope, name == "do login" ) form : InputForm( eContainer == login, name == "login form" ) # from a role role : Role ( ) attribute : DomainAttribute ( eContainer == role ) param : ParameterWire ( from == role, to == login_handler ) field : InputTextField ( eContainer == form, name == attribute.name ) fieldValue : ApplicationElementProperty ( eContainer == field, name == "fieldValue" ) button : Button ( eContainer == form, name == "Login" ) run : RunInstanceWire ( from == button, to == operation, name == "onClick" ) not ( ParameterWire ( from == fieldValue, to == run, name == attribute.name )) then ParameterWire param2 = handler.generatedParameterWire(login_handler, fieldValue, fieldValue, run); handler.setName(param2, attribute.getName()); queue.add(param2, drools); end rule "Create 'do login' operation within all login_handlers" when container : InternetApplication( ) session : Session( eContainer == container ) login_handler : LoginHandler( eContainer == session ) not ( Operation ( eContainer == session, name == "do login" )) then CompositeOperation loginOperation = handler.generatedCompositeOperation(login_handler, session); handler.setName(loginOperation, "do login"); queue.add(loginOperation, drools); end rule "Create contents of 'do login' operation [type=domain_object]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT ) instance : DomainObjectInstance ( eContainer == scope ) setWire : SetWire ( from == login_handler, to == instance, name == "set" ) ex : Operation ( eContainer == instance, name == "exists?" ) loginOperation : CompositeOperation ( eContainer == scope, name == "do login" ) not ( StartNode ( eContainer == loginOperation )) then StartNode start = handler.generatedStartNode(loginOperation, loginOperation); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(loginOperation, loginOperation); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(loginOperation, loginOperation); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "No such instance found."); queue.add(cancel, drools); // make a split/join SplitNode split = handler.generatedSplitNode(loginOperation, loginOperation); queue.add(split, drools); JoinNode join = handler.generatedJoinNode(loginOperation, loginOperation); queue.add(join, drools); ExecutionEdge edge0 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge0, start); handler.setTo(edge0, split); queue.add(edge0, drools); // we will leave the other rules to generate the contents # a virtual operation call # (the 'exists?' operation cannot have more than 2 execution edges out) OperationCallNode call = handler.generatedOperationCallNode(loginOperation, loginOperation); handler.setName(call, "call exists?"); queue.add(call, drools); # connect with a RunInstanceWire RunInstanceWire run = handler.generatedRunInstanceWire(loginOperation, loginOperation, call, ex); handler.setName(run, "virtual operation call"); queue.add(run, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge1, join); handler.setTo(edge1, call); queue.add(edge1, drools); # not ok ExecutionEdge edge2 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge2, call); handler.setTo(edge2, cancel); queue.add(edge2, drools); # ok ExecutionEdge edge3 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge3, call); handler.setTo(edge3, finish); queue.add(edge3, drools); end rule "Create parameter for 'do login' operation inside login handler[type=domain_object]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT ) attribute : DomainAttribute ( ) paramWire : ParameterWire( from == attribute, to == login_handler ) instance : DomainObjectInstance ( eContainer == scope ) setWire : SetWire ( from == login_handler, to == instance, name == "set" ) operation : CompositeOperation ( eContainer == scope, name == "do login" ) split : SplitNode ( eContainer == operation ) join : JoinNode ( eContainer == operation ) target : ApplicationElementProperty ( eContainer == scope, eval(functions.loginAttributeMatches(target, attribute))) not ( Parameter ( eContainer == operation, name == attribute.name )) then Parameter param = handler.generatedParameter(operation, operation); handler.setName(param, attribute.getName()); queue.add(param, drools); CompositeOperation setValue = handler.generatedCompositeOperation(operation, operation); handler.setName(setValue, "setPropertyToValue"); queue.add(setValue, drools); // split to set value ExecutionEdge edge1 = handler.generatedExecutionEdge(operation, operation); handler.setFrom(edge1, split); handler.setTo(edge1, setValue); queue.add(edge1, drools); // set value to join ExecutionEdge edge2 = handler.generatedExecutionEdge(operation, operation); handler.setFrom(edge2, setValue); handler.setTo(edge2, join); queue.add(edge2, drools); // flow from param to value DataFlowEdge data1 = handler.generatedDataFlowEdge(operation, operation); handler.setFrom(data1, param); handler.setTo(data1, setValue); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(operation, operation); handler.setFrom(data2, setValue); handler.setTo(data2, target); queue.add(data2, drools); end rule "Create contents of 'do login' operation [type=user]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.USER ) instance : DomainObjectInstance ( eContainer == scope ) setWire : SetWire ( from == login_handler, to == instance, name == "set" ) ex : Operation ( eContainer == instance, name == "exists?" ) loginOperation : CompositeOperation ( eContainer == scope, name == "do login" ) not ( StartNode ( eContainer == loginOperation )) then StartNode start = handler.generatedStartNode(loginOperation, loginOperation); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(loginOperation, loginOperation); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(loginOperation, loginOperation); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "No such user found."); queue.add(cancel, drools); // make a split/join SplitNode split = handler.generatedSplitNode(loginOperation, loginOperation); queue.add(split, drools); JoinNode join = handler.generatedJoinNode(loginOperation, loginOperation); queue.add(join, drools); ExecutionEdge edge0 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge0, start); handler.setTo(edge0, split); queue.add(edge0, drools); // we will leave the other rules to generate the contents # a virtual operation call # (the 'exists?' operation cannot have more than 2 execution edges out) OperationCallNode call = handler.generatedOperationCallNode(loginOperation, loginOperation); handler.setName(call, "call exists?"); queue.add(call, drools); # connect with a RunInstanceWire RunInstanceWire run = handler.generatedRunInstanceWire(loginOperation, loginOperation, call, ex); handler.setName(run, "virtual operation call"); queue.add(run, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge1, join); handler.setTo(edge1, call); queue.add(edge1, drools); # not ok ExecutionEdge edge2 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge2, call); handler.setTo(edge2, cancel); queue.add(edge2, drools); # ok ExecutionEdge edge3 = handler.generatedExecutionEdge(loginOperation, loginOperation); handler.setFrom(edge3, call); handler.setTo(edge3, finish); queue.add(edge3, drools); end rule "Create parameter for 'do login' operation inside login handler[type=user]" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.USER ) role : Role ( ) attribute : DomainAttribute ( eContainer == role ) paramWire : ParameterWire( from == role, to == login_handler ) operation : CompositeOperation ( eContainer == scope, name == "do login" ) split : SplitNode ( eContainer == operation ) join : JoinNode ( eContainer == operation ) target : ApplicationElementProperty ( eContainer == scope, eval(functions.loginAttributeMatches(target, attribute))) not ( Parameter ( eContainer == operation, name == attribute.name )) then Parameter param = handler.generatedParameter(operation, operation); handler.setName(param, attribute.getName()); queue.add(param, drools); CompositeOperation setValue = handler.generatedCompositeOperation(operation, operation); handler.setName(setValue, "setPropertyToValue"); queue.add(setValue, drools); // split to set value ExecutionEdge edge1 = handler.generatedExecutionEdge(operation, operation); handler.setFrom(edge1, split); handler.setTo(edge1, setValue); queue.add(edge1, drools); // set value to join ExecutionEdge edge2 = handler.generatedExecutionEdge(operation, operation); handler.setFrom(edge2, setValue); handler.setTo(edge2, join); queue.add(edge2, drools); // flow from param to value DataFlowEdge data1 = handler.generatedDataFlowEdge(operation, operation); handler.setFrom(data1, param); handler.setTo(data1, setValue); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(operation, operation); handler.setFrom(data2, setValue); handler.setTo(data2, target); queue.add(data2, drools); end /* it's possible in the future that this method should be split up. */ rule "Connect successful 'login' operation to navigate to final 'login' page" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) login : Page (eContainer == container, name=="login" ) login_operation : CompositeOperation( eContainer == scope, name == "do login" ) login_target : Page ( ) login_wire : NavigateWire( from == login_handler, to == login_target, name == "login" ) not (NavigateWire(from == login_operation, to == login_target)) then NavigateWire wire = handler.generatedNavigateWire(login_handler, scope, login_operation, login_target); handler.setName(wire, "navigate on successful login"); queue.add(wire, drools); end rule "Connect failed 'login' operation to navigate back to 'login'" when container : InternetApplication( ) scope : Session( eContainer == container ) login_handler : LoginHandler( eContainer == scope ) login : Page (eContainer == container, name=="login" ) login_operation : CompositeOperation( eContainer == scope, name == "do login" ) not (NavigateWire(from == login_operation, to == login, name == "fail")) then NavigateWire wire = handler.generatedNavigateWire(login_handler, scope, login_operation, login); handler.setName(wire, "fail"); queue.add(wire, drools); end rule "Create 'do logout' operation in session" when container : InternetApplication( ) scope : Session ( ) login_handler : LoginHandler( eContainer == scope ) logout : Page ( eContainer == scope, name == "logout" ) not (CompositeOperation ( eContainer == scope, name == "do logout" )) then CompositeOperation operation = handler.generatedCompositeOperation(login_handler, scope); handler.setName(operation, "do logout"); queue.add(operation, drools); end rule "Connect 'access' operation for logout page to 'do logout' operation" when container : InternetApplication( ) scope : Session ( ) login_handler : LoginHandler( eContainer == scope ) logout : Page ( ) wire : CompositeWire ( from == login_handler, to == logout, name == "logout" ) logout_operation : Operation ( eContainer == scope, name == "do logout" ) access : EventTrigger ( eContainer == logout, name == "access" ) # we can't add it to the end of the 'check key' operation, because then # all operations will have to run it as well. # add it to the end of the access operation chain not (RunInstanceWire( from == access, to == logout_operation )) then RunInstanceWire run = handler.generatedRunInstanceWire(login_handler, logout, access, logout_operation); handler.setName(run, "run logout operation"); queue.add(run, drools); end rule "Connect new navigate wire from logout to logout destination" when container : InternetApplication( ) scope : Session ( ) login_handler : LoginHandler( eContainer == scope ) logout : Page ( eContainer == scope, name == "logout" ) logout_operation : CompositeOperation ( eContainer == scope, name == "do logout" ) # add it at the end of the operation chain (final_operation may == logout_operation) # in this case, we want all accesses to "do logout" to always redirect to "home" (for example) final_operation : CompositeOperation ( eval(final_operation.equals(functions.lastChainedOperation(logout_operation))) ) destination : Page ( ) logout_wire : NavigateWire( from == login_handler, to == destination, name == "logout" ) not (NavigateWire( from == final_operation, to == destination )) then NavigateWire wire = handler.generatedNavigateWire(login_handler, scope, final_operation, destination); handler.setName(wire, "navigate on successful logout"); queue.add(wire, drools); end rule "Create contents of 'do logout' operation [type=secret_key]" when scope : Session( ) o : CompositeOperation( name == "do logout", eContainer == scope ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.SECRET_KEY ) value : ApplicationElementProperty( ) mySetWire : SetWire( from == login_handler, to == value, name == "set" ) not (StartNode( eContainer == o)) not (FinishNode( eContainer == o)) then # create a 'null' value StaticValue myNull = handler.generatedStaticValue(o, o); handler.setName(myNull, "reset value"); handler.setValue(myNull, ModelPackage.eINSTANCE.getStaticValue_Value(), "null"); queue.add(myNull, drools); StartNode start = handler.generatedStartNode(o, o); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(o, o); queue.add(finish, drools); # setPropertyToValue PrimitiveOperation op = handler.generatedPrimitiveOperation(o, o); handler.setName(op, "setPropertyToValue"); queue.add(op, drools); DataFlowEdge data1 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data1, myNull); handler.setTo(data1, op); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data2, op); handler.setTo(data2, value); queue.add(data2, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge1, start); handler.setTo(edge1, op); queue.add(edge1, drools); # ok ExecutionEdge edge2 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge2, op); handler.setTo(edge2, finish); queue.add(edge2, drools); end rule "Create contents (initial) of 'do logout' operation [type=object or user]" when scope : Session( ) o : CompositeOperation( name == "do logout", eContainer == scope ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT || type == LoginHandlerTypes.USER ) not (StartNode( eContainer == o)) not (FinishNode( eContainer == o)) then # create a 'null' value StaticValue myNull = handler.generatedStaticValue(o, o); handler.setName(myNull, "reset value"); handler.setValue(myNull, ModelPackage.eINSTANCE.getStaticValue_Value(), "null"); queue.add(myNull, drools); StartNode start = handler.generatedStartNode(o, o); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(o, o); queue.add(finish, drools); SplitNode split = handler.generatedSplitNode(o, o); queue.add(split, drools); JoinNode join = handler.generatedJoinNode(o, o); queue.add(join, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge1, start); handler.setTo(edge1, split); queue.add(edge1, drools); # ok ExecutionEdge edge2 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge2, join); handler.setTo(edge2, finish); queue.add(edge2, drools); end rule "Create contents (specific keys) of 'do logout' operation [type=object]" when session : Session( ) o : CompositeOperation( name == "do logout", eContainer == session ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.DOMAIN_OBJECT ) attribute : DomainAttribute ( ) paramWire : ParameterWire ( from == attribute, to == login_handler ) key : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(key, attribute) ) ) myNull : StaticValue ( eContainer == o, name == "reset value" ) split : SplitNode ( eContainer == o ) join : JoinNode ( eContainer == o ) not (DataFlowEdge ( eContainer == o, from == key )) then # setPropertyToValue PrimitiveOperation op = handler.generatedPrimitiveOperation(o, o); handler.setName(op, "setPropertyToValue"); queue.add(op, drools); DataFlowEdge data1 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data1, myNull); handler.setTo(data1, op); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data2, op); handler.setTo(data2, key); queue.add(data2, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge1, split); handler.setTo(edge1, op); queue.add(edge1, drools); ExecutionEdge edge2 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge2, op); handler.setTo(edge2, join); queue.add(edge2, drools); end rule "Create contents (specific keys) of 'do logout' operation [type=user]" when session : Session( ) o : CompositeOperation( name == "do logout", eContainer == session ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.USER ) role : Role ( ) attribute : DomainAttribute ( eContainer == role, eval(functions.notPrimaryKey(attribute)) ) paramWire : ParameterWire ( from == role, to == login_handler ) key : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(key, attribute) ) ) myNull : StaticValue ( eContainer == o, name == "reset value" ) split : SplitNode ( eContainer == o ) join : JoinNode ( eContainer == o ) not (DataFlowEdge ( eContainer == o, from == key )) then # setPropertyToValue PrimitiveOperation op = handler.generatedPrimitiveOperation(o, o); handler.setName(op, "setPropertyToValue"); queue.add(op, drools); DataFlowEdge data1 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data1, myNull); handler.setTo(data1, op); queue.add(data1, drools); DataFlowEdge data2 = handler.generatedDataFlowEdge(o, o); handler.setFrom(data2, op); handler.setTo(data2, key); queue.add(data2, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge1, split); handler.setTo(edge1, op); queue.add(edge1, drools); ExecutionEdge edge2 = handler.generatedExecutionEdge(o, o); handler.setFrom(edge2, op); handler.setTo(edge2, join); queue.add(edge2, drools); end rule "Create default login successful page" when scope : Session ( ) login_handler : LoginHandler( eContainer == scope ) not ( wire : CompositeWire (from == login_handler, name == "login" )) then Page page = handler.generatedPage(login_handler, scope); handler.setName(page, "Login Successful"); queue.add(page, drools); NavigateWire wire = handler.generatedNavigateWire(login_handler, login_handler, login_handler, page); handler.setName(wire, "login"); queue.add(wire, drools); end rule "Create default logout successful page" when container : InternetApplication( ) scope : Session ( ) login_handler : LoginHandler( eContainer == scope ) not ( wire : CompositeWire (from == login_handler, name == "logout" )) then Page page = handler.generatedPage(login_handler, container); handler.setName(page, "Logout Successful"); queue.add(page, drools); NavigateWire wire = handler.generatedNavigateWire(login_handler, login_handler, login_handler, page); handler.setName(wire, "logout"); queue.add(wire, drools); end /** * If we have multiple incoming ParameterWires, we need special logic to * only instantiate this rule once (thanks to queued insertions). * * Essentially, we create only SelectWire for each DomainObject * linked by a ParameterWire, and then use Java to generate the * actual query from the Attributes. */ rule "Create Select Wire between Domain Object types [object]" when scope : Session ( ) dobj : DomainObject ( eval(functions.hasDomainAttribute(dobj)) ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.DOMAIN_OBJECT, eval(functions.hasIncomingParameterWiresFrom(login_handler, dobj)) ) instance : DomainObjectInstance ( ) setWire : SetWire ( from == login_handler, to == instance ) not ( SelectWire ( from == dobj, to == instance )) then // find all the attributes as incoming parameter wires for the // given DomainObject String q = ""; for (WireEdge wire : login_handler.getInEdges()) { if (wire.getFrom() instanceof DomainAttribute && dobj.equals(wire.getFrom().eContainer())) { // add this attribute as a query DomainAttribute attribute = (DomainAttribute) wire.getFrom(); if (functions.notPrimaryKey(attribute)) { if (!q.isEmpty()) { q += " and "; } q += attribute.getName() + " = :" + attribute.getName(); } } } SelectWire wire = handler.generatedSelectWire(login_handler, login_handler, dobj, instance); handler.setName(wire, "select"); handler.setQuery(wire, q); queue.add(wire, drools); end rule "Create Select Wire between Domain Object types [user]" when scope : Session ( ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.USER ) role : Role ( ) parameter : ParameterWire( from == role, to == login_handler ) instance : UserInstance ( ) setWire : SetWire ( from == login_handler, to == instance ) not ( SelectWire ( from == role, to == instance )) then // find all the attributes as incoming parameter wires for the // given DomainObject (including superclasses) String q = functions.getUserQueryString(role); SelectWire wire = handler.generatedSelectWire(login_handler, login_handler, role, instance); handler.setName(wire, "select"); handler.setQuery(wire, q); queue.add(wire, drools); end # if the attributes have changed, we need to update the # query string rule "Update Select Wire between Domain Object types [user]" when scope : Session ( ) login_handler : LoginHandler( eContainer == scope, type == LoginHandlerTypes.USER ) role : Role ( ) parameter : ParameterWire( from == role, to == login_handler ) instance : UserInstance ( ) setWire : SetWire ( from == login_handler, to == instance ) select : SelectWire ( from == role, to == instance ) # a new attribute has been inserted (trigger) attribute : DomainAttributeInstance ( eContainer == instance ) not (eval(select.getQuery() != null && select.getQuery().equals(functions.getUserQueryString(role)))) then String q = functions.getUserQueryString(role); handler.setQuery(select, q); end rule "Create 'key attribute' property for LoginHandler[type = object]s" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.DOMAIN_OBJECT ) attribute : DomainAttribute ( ) paramWire : ParameterWire ( from == attribute, to == login_handler ) not ( p : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(p, attribute) ) ) ) then ApplicationElementProperty key = handler.generatedApplicationElementProperty(login_handler, session); handler.setName(key, "current " + attribute.getName()); # need to set a default value, or else require_session(this) will throw an exception before we can catch it to redirect handler.setValue(key, ModelPackage.eINSTANCE.getApplicationElementProperty_DefaultValue(), ""); queue.add(key, drools); end rule "Create 'key attribute' property for LoginHandler[type = user]s" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.USER ) role : Role ( ) attribute : DomainAttribute ( eContainer == role, eval(functions.notPrimaryKey(attribute)) ) paramWire : ParameterWire ( from == role, to == login_handler ) not ( p : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(p, attribute) ) ) ) then ApplicationElementProperty key = handler.generatedApplicationElementProperty(login_handler, session); handler.setName(key, "current " + attribute.getName()); # need to set a default value, or else require_session(this) will throw an exception before we can catch it to redirect handler.setValue(key, ModelPackage.eINSTANCE.getApplicationElementProperty_DefaultValue(), ""); queue.add(key, drools); end rule "Connect key properties to LoginHandler for LoginHandler[type = object]" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.DOMAIN_OBJECT ) object : DomainObject ( ) attribute : DomainAttribute ( eContainer == object ) paramWire : ParameterWire ( from == attribute, to == login_handler ) instance : DomainObjectInstance ( ) setWire : SetWire ( from == login_handler, to == instance ) select : SelectWire ( from == object, to == instance ) key : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(key, attribute) ) ) not ( SetWire ( from == login_handler, to == key )) then SetWire wire = handler.generatedSetWire(login_handler, session, login_handler, key); handler.setName(wire, "set"); queue.add(wire, drools); end rule "Connect key properties to SelectWire for LoginHandler[type = object]" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.DOMAIN_OBJECT ) object : DomainObject ( ) attribute : DomainAttribute ( eContainer == object ) paramWire : ParameterWire ( from == attribute, to == login_handler ) instance : DomainObjectInstance ( ) setWire : SetWire ( from == login_handler, to == instance ) select : SelectWire ( from == object, to == instance ) key : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(key, attribute) ) ) not ( ParameterWire ( from == key, to == select )) then ParameterWire wire = handler.generatedParameterWire(login_handler, session, key, select); handler.setName(wire, attribute.getName()); queue.add(wire, drools); end rule "Connect key properties to SelectWire for LoginHandler[type = user]" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.USER ) role : Role ( ) attribute : DomainAttribute ( eContainer == role ) paramWire : ParameterWire ( from == role, to == login_handler ) instance : UserInstance ( ) setWire : SetWire ( from == login_handler, to == instance ) select : SelectWire ( from == role, to == instance ) key : ApplicationElementProperty ( eContainer == session, eval(functions.loginAttributeMatches(key, attribute) ) ) not ( ParameterWire ( from == key, to == select )) then ParameterWire wire = handler.generatedParameterWire(login_handler, session, key, select); handler.setName(wire, attribute.getName()); queue.add(wire, drools); end rule "Create 'check instance' operation for LoginHandler[type = object or user]" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.DOMAIN_OBJECT || type == LoginHandlerTypes.USER ) not (Operation( eContainer == session, name == "check instance") ) then CompositeOperation op = handler.generatedCompositeOperation( login_handler, session ); handler.setName(op, "check instance"); queue.add(op, drools); end rule "Create 'current instance' for LoginHandler[type=object]" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.DOMAIN_OBJECT ) not (DomainObjectInstance ( eContainer == session )) then DomainObjectInstance instance = handler.generatedDomainObjectInstance( login_handler, session ); handler.setName(instance, "current instance"); queue.add(instance, drools); // connect with SetWire SetWire setWire = handler.generatedSetWire(login_handler, session, login_handler, instance); handler.setName(setWire, "set"); queue.add(setWire, drools); end rule "Create 'current instance' for LoginHandler[type=user]" when session : Session( ) login_handler : LoginHandler( eContainer == session, type == LoginHandlerTypes.USER ) not (UserInstance ( eContainer == session )) then UserInstance instance = handler.generatedUserInstance( login_handler, session ); handler.setName(instance, "current instance"); queue.add(instance, drools); // connect with SetWire SetWire setWire = handler.generatedSetWire(login_handler, session, login_handler, instance); handler.setName(setWire, "set"); queue.add(setWire, drools); end