Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
571 lines (435 sloc) 19.3 KB
/**
* Completes the functionality and logic of {@model Gate}s within {@model Frame}s and {@model Scope}s.
*/
#created on: 4/11/2008
package org.openiaml.model.drools.rules.gate
#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 OverridableCreateElementsHelper handler;
global DroolsInsertionQueue queue;
global DroolsHelperFunctions functions;
/**
* @inference Gate
* A {@model Gate} referencing a {@model Frame},
* with an outgoing {@model ECARule} named 'first', 'last' or 'fail',
* will create a {@model Button} named 'continue' in the referenced {@model Frame}.
*/
rule "Create 'Continue' button for Frames connected with 'first' or 'last' or 'fail' ECARule"
when
gate : Gate ( )
tf : Frame ( )
nav : ECARule ( trigger == gate, target == tf, name == "first" || name == "last" || name == "fail" )
not (Button ( eContainer == tf, name == "Continue" ))
not (ECARule ( target == gate ))
eval ( handler.veto( gate ))
then
Button button = handler.generatedButton(gate, tf);
handler.setName(button, "Continue");
queue.add(button, drools);
end
/**
* @inference Gate
* The 'continue' {@model Button} generated for a {@model Gate},
* with an outgoing {@model ECARule} named 'first', 'last' or 'fail',
* will execute the {@model Gate}
* when {@model Button#onClick clicked}.
*/
rule "Connect 'click' on 'Continue' button to resume Gate"
when
gate : Gate ( )
tf : Frame ( )
nav : ECARule ( trigger == gate, target == tf, name == "first" || name == "last" || name == "fail" )
button : Button ( eContainer == tf, name == "Continue" )
click : Event ( button.onClick == click, eContainer == button )
not (ECARule ( trigger == click, target == gate ))
eval ( handler.veto( gate ))
then
ECARule wire = handler.generatedECARule(gate, tf, click, gate);
handler.setName(wire, "resume");
queue.add(wire, drools);
end
/**
* @inference Gate
* A {@model Scope} protected by a {@model Gate} {@model Gate#name named} 'XXX',
* with an outgoing {@model ECARule} named 'first' or 'last',
* will contain a <em>flag</em> {@model Value} named 'XXX flag', in order to track the runtime status of the {@model Gate}.
*/
rule "Create '(gate) flag' property when Gate is connected by 'first' or 'last'"
when
session : Scope ( )
gate : Gate ( eContainer == session )
wire : ECARule ( trigger == gate, name == "first" || name == "last" )
not (Value ( eContainer == session, eval( name.equals(gate.getName() + " flag")) ))
eval ( handler.veto( gate ))
then
Value prop = handler.generatedValue(gate, session);
handler.setName(prop, gate.getName() + " flag");
handler.setValue(prop, ModelPackage.eINSTANCE.getValue_DefaultValue(), "false");
queue.add(prop, drools);
end
/**
* TODO can the 'Frame' restriction be relaxed to 'Scope'?
*
* @inference Gate
* A <em>flag</em> {@model Value} generated by a {@model Gate}
* with an outgoing {@model ECARule} named 'first' or 'last' is {@model Frame#onAccess accessed},
* will generate an {@model ActivityOperation} in that {@model Scope} named 'Set gate flag'.
*/
rule "Create 'set flag' operation for Frames connected with 'first' or 'last' ECARule"
when
gate : Gate ( )
tf : Frame ( )
nav : ECARule ( trigger == gate, target == tf, name == "first" || name == "last" )
button : Button ( eContainer == tf, name == "Continue" )
not (ActivityOperation ( eContainer == tf, name == "Set gate flag" ))
eval ( handler.veto( gate ))
then
ActivityOperation op = handler.generatedActivityOperation(gate, tf);
handler.setName(op, "Set gate flag");
queue.add(op, drools);
end
/**
* TODO can the 'Frame' restriction be relaxed to 'Scope'?
*
* @inference Gate
* When a {@model Frame} protected by a {@model Gate}
* with an outgoing {@model ECARule} named 'first' or 'last' is {@model Frame#onAccess accessed},
* the 'Set gate flag' {@model Operation} will be {@model ECARule executed}.
*/
rule "Connect 'access' event with 'set flag' operation"
when
gate : Gate ( )
tf : Frame ( )
nav : ECARule ( trigger == gate, target == tf, name == "first" || name == "last" )
button : Button ( eContainer == tf, name == "Continue" )
op : Operation ( eContainer == tf, name == "Set gate flag" )
access : Event ( eContainer == tf, tf.onAccess == access )
not ( ECARule ( trigger == access, target == op ))
eval ( handler.veto( gate ))
then
ECARule run = handler.generatedECARule(gate, tf, access, op);
handler.setName(run, "run");
queue.add(run, drools);
end
/**
* TODO can the 'Frame' restriction be relaxed to 'Scope'?
*
* @inference Gate,ActivityOperation
* The {@model ActivityOperation} 'Set gate flag' generated for a {@model Gate} protecting a {@model Frame},
* with an outgoing {@model ECARule} named 'first' or 'last',
* will be completed with the {@model ActivityNode contents necessary} to set the <em>flag</em> {@model Value}.
*/
rule "Create contents of 'set flag' operation"
when
session : Scope ( )
gate : Gate ( eContainer == session )
tf : Frame ( )
nav : ECARule ( trigger == gate, target == tf, name == "first" || name == "last" )
button : Button ( eContainer == tf, name == "Continue" )
property : Value ( eContainer == session, eval( name.equals(gate.getName() + " flag")) )
op : ActivityOperation ( eContainer == tf, name == "Set gate flag" )
not (StartNode ( eContainer == op ))
eval ( handler.veto( gate ))
then
StartNode start = handler.generatedStartNode(gate, op);
FinishNode finish = handler.generatedFinishNode(gate, op);
SetNode set = handler.generatedSetNode(gate, op);
Value value = handler.generatedValue(gate, op);
handler.setReadOnly(value, true);
handler.setName(value, "true");
handler.setDefaultValue(value, "true");
queue.add(start, drools);
queue.add(finish, drools);
queue.add(set, drools);
ExternalValue ev_property = handler.generatedExternalValue(gate, op);
handler.setValue(ev_property, property);
queue.add(ev_property, drools);
ExternalValue ev_value = handler.generatedExternalValue(gate, op);
handler.setValue(ev_value, value);
queue.add(ev_value, drools);
ExecutionEdge e1 = handler.generatedExecutionEdge(gate, op, start, set);
ExecutionEdge e2 = handler.generatedExecutionEdge(gate, op, set, finish);
DataFlowEdge d1 = handler.generatedDataFlowEdge(gate, op, ev_value, set);
DataFlowEdge d2 = handler.generatedDataFlowEdge(gate, op, set, ev_property);
queue.add(e1, drools);
queue.add(e2, drools);
queue.add(d1, drools);
queue.add(d2, drools);
end
/**
* @inference Gate,Scope
* A {@model Scope} protected by a {@model Gate} named 'XXX',
* with an outgoing {@model ECARule} named 'first' or 'last',
* will contain an {@model ActivityPredicate}
* named 'check XXX' to check that the {@model Gate} has been satisfied.
*/
rule "Create condition 'check (gate)'"
when
session : Scope ( )
gate : Gate ( eContainer == session )
wire : ECARule ( trigger == gate, name == "first" || name == "last" )
type : EXSDDataType( definition != null,
definition.name == "boolean" )
not ( Function ( eContainer == session, eval( name.equals("check " + gate.getName())) ))
eval ( handler.veto( gate ))
then
ActivityPredicate cond = handler.generatedActivityPredicate(gate, session);
handler.setName(cond, "check " + gate.getName());
handler.setType(cond, type);
queue.add(cond, drools);
end
/**
* @inference Gate,Scope
* The 'check XXX' {@model Function} for a {@model Gate},
* with an outgoing {@model ECARule} named 'first' or 'last',
* will be provided as a
* runtime {@model SimpleCondition} check to that {@model Gate}.
*/
rule "Connect condition 'check (gate)' with gate"
when
session : Scope ( )
gate : Gate ( eContainer == session )
wire : ECARule ( trigger == gate, name == "first" || name == "last" )
cond : Function ( eContainer == session, eval( name.equals("check " + gate.getName())) )
not ( SimpleCondition ( function == cond, conditioned == gate ))
eval ( handler.veto( gate ))
then
SimpleCondition cw = handler.generatedSimpleCondition(gate, session, cond, gate);
handler.setName(cw, "condition");
queue.add(cw, drools);
end
/**
* @inference Gate,Scope,ActivityPredicate
* The 'check XXX' {@model ActivityPredicate} for a {@model Gate},
* with an outgoing {@model ECARule} named 'first' or 'last',
* will be completed with the {@model ActivityNode contents necessary} to evaluate the <em>flag</em> {@model Value}.
*/
rule "Create contents of 'check (gate)' condition"
when
session : Scope ( )
gate : Gate ( eContainer == session )
wire : ECARule ( trigger == gate, name == "first" || name == "last" )
property : Value ( eContainer == session, eval( name.equals(gate.getName() + " flag")) )
cond : ActivityPredicate ( eContainer == session, eval( name.equals("check " + gate.getName())) )
cw : SimpleCondition ( function == cond, conditioned == gate )
not ( StartNode ( eContainer == cond ))
eval ( handler.veto( gate ))
then
StartNode start = handler.generatedStartNode(gate, cond);
FinishNode finish = handler.generatedFinishNode(gate, cond);
CancelNode cancel = handler.generatedCancelNode(gate, cond);
DecisionNode cmp = handler.generatedDecisionNode(gate, cond);
handler.setName(cmp, "true?");
queue.add(start, drools);
queue.add(finish, drools);
queue.add(cancel, drools);
queue.add(cmp, drools);
ExecutionEdge e1 = handler.generatedExecutionEdge(gate, cond, start, cmp);
ExecutionEdge e2 = handler.generatedExecutionEdge(gate, cond, cmp, finish);
handler.setName(e2, "y");
ExecutionEdge e3 = handler.generatedExecutionEdge(gate, cond, cmp, cancel);
handler.setName(e3, "n");
ExternalValue ev_property = handler.generatedExternalValue(gate, cond);
handler.setValue(ev_property, property);
queue.add(ev_property, drools);
DataFlowEdge d1 = handler.generatedDataFlowEdge(gate, cond, ev_property, cmp);
queue.add(e1, drools);
queue.add(e2, drools);
queue.add(e3, drools);
queue.add(d1, drools);
end
/**
* TODO Should the Provides page be placed into a separate Session if the protected
* Scope by the Gate is also a Session? The current implementation requires that if the
* data entered is to be unique, the protected Session will also have to be contained
* within a Session itself, otherwise the generated Provides Frame will allow access
* to the private data explicitly.
*
* @inference Gate,RequiresEdge
* A {@model Gate} protecting a {@model Scope} as an {@model Scope#entryGate entry gate}
* with an incoming {@model RequiresEdge} from an <em>expected input value</em> (represented as a {@model Label})
* -- known as an <em>input entry</em> {@model Gate} --
* will create an <em>input</em> {@model Frame} to allow the user to enter in these expected values.
*/
rule "If an EntryGate requires a Label value, then a Page should be created outside the Scope to enter it"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
not ( provide : Frame ( eContainer == container, name != null,
eval ( functions.getEntryGateFrameNameForProvides(label).equals(provide.getName()) ) ) )
eval ( handler.veto( gate ))
then
Frame provide = handler.generatedFrame(gate, container);
handler.setName(provide, functions.getEntryGateFrameNameForProvides(label));
queue.add(provide, drools);
end
/**
* @inference Gate,RequiresEdge
* An <em>input entry</em> {@model Gate} will create an outgoing {@model ECARule navigation rule}
* from the {@model Gate} named 'fail' to the <em>input</em> {@model Frame}.
*/
rule "For EntryGates that require Label values, connect a NavigateWire to the provides Frame"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
provide : Frame ( eContainer == container, name != null,
eval ( functions.getEntryGateFrameNameForProvides(label).equals(provide.getName()) ) )
# allow other ECARules to override this one
not ( ECARule ( trigger == gate ))
eval ( handler.veto( gate ))
then
ECARule nav = handler.generatedECARule(gate, gate, gate, provide);
handler.setName(nav, "fail");
queue.add(nav, drools);
end
/**
* @inference Gate,RequiresEdge
* An <em>input</em> {@model Frame} generated by an <em>input entry</em> {@model Gate}
* will contain an {@model InputTextField} for every {@model Label} {@model RequiresEdge required}
* by that {@model Gate}.
*/
rule "Create TextFields for all Labels required by an EntryGate"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
provide : Frame ( eContainer == container, name != null,
eval ( functions.getEntryGateFrameNameForProvides(label).equals(provide.getName()) ) )
not ( VisibleThing ( eContainer == provide, name == label.name ) )
eval ( handler.veto( gate ))
then
InputTextField text = handler.generatedInputTextField(gate, provide);
handler.setName(text, label.getName());
handler.setType(text, label.getType());
queue.add(text, drools);
end
/**
* @inference Gate
* An <em>input entry</em> {@model Gate} will check that every {@model Label} is set,
* through the 'fieldValue is set' {@model Function} of each {@model Label}.
*/
rule "If an EntryGate requires a Label value, then the 'is set?' Function in the Label is used as the Gate Condition"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
cond : Function ( eContainer == label, name == "fieldValue is set" )
not ( SimpleCondition ( function == cond, conditioned == gate ))
eval ( handler.veto( gate ))
then
SimpleCondition edge = handler.generatedSimpleCondition(gate, gate, cond, gate);
queue.add(edge, drools);
end
/**
* @inference Gate,ECARule
* An <em>input entry</em> {@model Gate} will {@model ECARule update} the value of each <em>input</em> {@model Label}
* from the value of each similarly named {@model VisibleThing} in the <em>input</em> {@model Frame}
* when the protected {@model Scope} is {@model Scope#onAccess accessed}.
*/
rule "If an EntryGate requires a Label, get the containing Scope to update the Label from the expected external source"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
provide : Frame ( eContainer == container, name != null,
eval ( functions.getEntryGateFrameNameForProvides(label).equals(provide.getName()) ) )
field : VisibleThing ( eContainer == provide, name == label.name )
value : Value ( field.fieldValue == value )
# Scope.onAccess
onAccess : Event ( session.onAccess == onAccess )
# Label.update()
op : Operation ( eContainer == label, name == "update" )
not ( ECARule ( trigger == onAccess, target == op ))
eval ( handler.veto( gate ))
then
ECARule run = handler.generatedECARule(gate, gate, onAccess, op);
handler.setName(run, "run");
queue.add(run, drools);
# connect with Parameter
Parameter param = handler.generatedParameter(gate, gate, value, run);
queue.add(param, drools);
end
/**
* @inference Gate
* An <em>input entry</em> {@model Gate} will only update the value of each <em>input</em> {@model Label}
* from {@model VisibleThing}s in the <em>input</em> {@model Frame} if the source elements {@model Function are set}.
*/
rule "If an EntryGate requires a Label, the Label is only updated externally if the given value has been set"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
provide : Frame ( eContainer == container, name != null,
eval ( functions.getEntryGateFrameNameForProvides(label).equals(provide.getName()) ) )
field : VisibleThing ( eContainer == provide, name == label.name )
# Scope.onAccess
onAccess : Event ( session.onAccess == onAccess )
# Label.update()
op : Operation ( eContainer == label, name == "update" )
# Scope.onAccess --> Label.update()
run : ECARule ( trigger == onAccess, target == op )
# Text.isSet?
condition : Function ( eContainer == field, name == "fieldValue is set" )
not ( SimpleCondition ( function == condition, conditioned == run ))
eval ( handler.veto( gate ))
then
SimpleCondition edge = handler.generatedSimpleCondition(gate, gate, condition, run);
queue.add(edge, drools);
end
/**
* @inference Gate,SimpleCondition
* An <em>input entry</em> {@model Gate} will {@model SimpleCondition only} update the value of each <em>input</em> {@model Label}
* from {@model VisibleThing}s in the <em>input</em> {@model Frame} if the source elements {@model Function can be cast}.
*/
rule "If an EntryGate requires a Label, the Label is only updated externally if the given value can be cast to the target type"
when
container : Scope ( )
session : Scope ( eContainer == container )
gate : Gate ( session.entryGate == gate )
label : Label ( )
requires : RequiresEdge ( from == gate, to == label )
provide : Frame ( eContainer == container, name != null,
eval ( functions.getEntryGateFrameNameForProvides(label).equals(provide.getName()) ) )
field : VisibleThing ( eContainer == provide, name == label.name )
value : Value ( field.fieldValue == value )
# Scope.onAccess
onAccess : Event ( session.onAccess == onAccess )
# Label.update()
op : Operation ( eContainer == label, name == "update" )
# Scope.onAccess --> Label.update()
run : ECARule ( trigger == onAccess, target == op )
# Label.can cast?
condition : Function ( eContainer == label, name == "can cast?" )
not ( SimpleCondition ( function == condition, conditioned == run ))
eval ( handler.veto( gate ))
then
SimpleCondition edge = handler.generatedSimpleCondition(gate, gate, condition, run);
queue.add(edge, drools);
# connect with fieldValue
Parameter param = handler.generatedParameter(gate, gate, value, edge);
queue.add(param, drools);
end
You can’t perform that action at this time.