#created on: 4/11/2008 package org.openiaml.model.drools.rules.set_wires #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.*; #declare any global variables here global EcoreCreateElementsHelper handler; global DroolsInsertionQueue queue; global DroolsHelperFunctions functions; rule "Set wires between objects should create set wires between all elements inside each object that matches [set]" when # source : SetWire(overridden == false, eval(functions.connectsSet(source, p1, p2)) ) source : SetWire(overridden == false) p1 : ApplicationElement( ) from source.from p2 : ApplicationElement(this != p1) from source.to e1 : ApplicationElement( eContainer == p1 ) e2 : ApplicationElement( eContainer == p2, eval(functions.syncMatches(e1, e2)) ) not (sw : SetWire( name == "set", eContainer == source, eval(functions.connectsSet( sw, e1, e2)) )) then SetWire sw = handler.generatedSetWire(source, source, e1, e2); handler.setName(sw, "set"); queue.add(sw, drools); end rule "Run instance wire from edit to update [set]" when sw : SetWire(overridden == false) source : ContainsEventTriggers( ) target : ContainsOperations( ) eval(functions.connectsSet(sw, source, target)) event : EventTrigger( eContainer == source, name=="edit" ) operation : Operation( eContainer == target, name=="update" ) not (RunInstanceWire( eContainer == sw, from == event, to == operation, name == "run" )) then RunInstanceWire rw = handler.generatedRunInstanceWire(sw, sw, event, operation); handler.setName(rw, "run"); queue.add(rw, drools); end # Ideally, these two commands would be joined together into one rule "Connect parameter wire to: run instance wire from source.edit to target.update [set]" when sw : SetWire(overridden == false) source : InputTextField( ) from sw.from target : InputTextField( ) from sw.to event : EventTrigger( eContainer == source, name=="edit" ) operation : Operation( eContainer == target, name=="update" ) field : ApplicationElementProperty( eContainer == source, name=="fieldValue" ) wire : RunInstanceWire( from == event, to == operation, name == "run", eContainer == sw ) not (ParameterWire( eContainer == sw, from == field, to == wire )) then ParameterWire pw = handler.generatedParameterWire(sw, sw, field, wire); handler.setName(pw, "[sync] run instance parameter (source.edit)"); queue.add(pw, drools); end rule "Connect parameter wire to: run instance wire from target.edit to source.update [set]" when sw : SetWire(overridden == false) target : InputTextField( ) from sw.from source : InputTextField( ) from sw.to event : EventTrigger( eContainer == source, name=="edit" ) operation : Operation( eContainer == target, name=="update" ) field : ApplicationElementProperty( eContainer == source, name=="fieldValue" ) wire : RunInstanceWire( from == event, to == operation, name == "run", eContainer == sw ) not (ParameterWire( eContainer == sw, from == field, to == wire )) then ParameterWire pw = handler.generatedParameterWire(sw, sw, field, wire); handler.setName(pw, "[sync] run instance parameter (target.edit)"); queue.add(pw, drools); end # Ideally, these two commands would be joined together into one rule "Run instance wire from source.access to source.init, when we have a value to provide as a parameter [set]" when sw : SetWire(overridden == false) source : ContainsEventTriggers( ) from sw.from target : ContainsOperations( ) from sw.to event : EventTrigger( eContainer == source, name=="access" ) operation : Operation( eContainer == source, name=="init" ) field : ApplicationElementProperty( eContainer == target, name=="fieldValue" ) not (RunInstanceWire( eContainer == sw, from == event, to == operation, name == "run" )) then RunInstanceWire rw = handler.generatedRunInstanceWire(sw, sw, event, operation); handler.setName(rw, "run"); queue.add(rw, drools); end rule "Run instance wire from target.access to target.init, when we have a value to provide as a parameter [set]" when sw : SetWire(overridden == false) source : ContainsEventTriggers( ) from sw.from target : ContainsOperations( ) from sw.to event : EventTrigger( eContainer == target, name=="access" ) operation : Operation( eContainer == target, name=="init" ) field : ApplicationElementProperty( eContainer == source, name=="fieldValue" ) not (RunInstanceWire( eContainer == sw, from == event, to == operation, name == "run" )) then RunInstanceWire rw = handler.generatedRunInstanceWire(sw, sw, event, operation); handler.setName(rw, "run"); queue.add(rw, drools); end # Ideally, these two commands would be joined together into one rule "Connect parameter wire to: run instance wire from source.access to source.init [set]" when sw : SetWire(overridden == false) source : InputTextField( ) from sw.from target : InputTextField( ) from sw.to event : EventTrigger( eContainer == source, name=="access" ) operation : Operation( eContainer == source, name=="init" ) field : ApplicationElementProperty( eContainer == target, name=="fieldValue" ) wire : RunInstanceWire( from == event, to == operation, name == "run", eContainer == sw ) not (ParameterWire( eContainer == sw, from == field, to == wire )) then ParameterWire pw = handler.generatedParameterWire(sw, sw, field, wire); handler.setName(pw, "[sync] run instance parameter (source.access)"); queue.add(pw, drools); end rule "Connect parameter wire to: run instance wire from target.access to target.init [set]" when sw : SetWire(overridden == false) source : InputTextField( ) from sw.from target : InputTextField( ) from sw.to event : EventTrigger( eContainer == target, name=="access" ) operation : Operation( eContainer == target, name=="init" ) field : ApplicationElementProperty( eContainer == source, name=="fieldValue" ) wire : RunInstanceWire( from == event, to == operation, name == "run", eContainer == sw ) not (ParameterWire( eContainer == sw, from == field, to == wire )) then ParameterWire pw = handler.generatedParameterWire(sw, sw, field, wire); handler.setName(pw, "[sync] run instance parameter (target.access)"); queue.add(pw, drools); end /** * I think that chained SetWires are generally impossible. Consider: * * page1 <--> page2 <--> unrelated * condition on both SetWires, matching (page1, page2) * * If we allow for chaining, then the condition * condition[page2, unrelated] * will be copied onto * condition[page1, page2] * which means the SetWires will never satisfy all its conditions. * * -- * * I think that chained SetWires are only possible *when* each * SetWires has identical Conditions, so we don't have to combine * the two conditions together into something impossible. * * However, trying to implement this did nothing. I think it is because * without adding more information to the model, you cannot chain. * The information you'd be adding is stuff like ChainedSetWire, but * this defeats the purpose of having it in the model, because this should * be handled by the code generation instead. */ rule "Cascaded SetWires: Conditions from parent to child [set]" when # the containing elements sw : SetWire ( overridden == false ) source : ApplicationElement( ) from sw.from target : ApplicationElement( ) from sw.to # the elements contained e1 : ApplicationElement( eContainer == source ) e2 : ApplicationElement( eContainer == target, eval(functions.syncMatches(e1, e2)) ) esw : SetWire( name == "set", eval(functions.connectsSet(esw, e1, e2)), overridden == false ) # there is a condition on the containing sync wire condition : Condition ( ) cw : ConditionWire( from == condition, to == sw ) # and there isn't one on the element sync wire not (ecw : ConditionWire( from == condition, to == esw )) then ConditionWire ecw = handler.generatedConditionWire( cw, cw, condition, esw ); handler.setName(ecw, "[copied] from: " + cw.getId()); queue.add(ecw, drools); end rule "Cascaded SetWires: Parameters from parent to child [set]" when # the containing elements sw : SetWire ( overridden == false ) source : ApplicationElement( ) from sw.from target : ApplicationElement( ) from sw.to # the elements contained e1 : ApplicationElement( eContainer == source ) e2 : ApplicationElement( eContainer == target, eval(functions.syncMatches(e1, e2)) ) esw : SetWire( name == "set", eval(functions.connectsSet(esw, e1, e2)), overridden == false ) # there is a condition on the containing sync wire condition : Condition ( ) cw : ConditionWire( from == condition, to == sw ) # the generated condition wire ecw : ConditionWire( from == condition, to == esw ) # there is a parameter on the condition wire parameter : WireEdgesSource( ) pw : ParameterWire( from == parameter, to == cw ) # and there isn't one on the element sync wire not (epw : ParameterWire( from == parameter, to == ecw )) then # create it ParameterWire epw = handler.generatedParameterWire( cw, cw, parameter, ecw ); handler.setName(epw, "[copied] from: " + pw.getId()); queue.add(epw, drools); end # SetWires do not connect the fields together; they can _also_ # connect the Pages together. rule "Connect Session.init to incoming SetWires (contained in Pages) [set]" when session : Session ( overridden == false ) sw : SetWire( overridden == false ) sourcePage : ContainsEventTriggers( eval(!functions.containingSessionEquals(sourcePage, session)) ) targetPage : ContainsOperations( eval(functions.containingSessionEquals(targetPage, session)) ) eval( functions.connectsSet(sw, sourcePage, targetPage )) sw2 : SetWire ( eContainer == sw, overridden == false) sourceElement : ContainsEventTriggers( eContainer == sourcePage ) targetElement : ContainsOperations( eContainer == targetPage ) eval( functions.connectsSet(sw2, sourceElement, targetElement )) event : EventTrigger( eContainer == sourceElement, name == "edit" ) operation : Operation( eContainer == targetElement, name == "update" ) rw : RunInstanceWire( eContainer == sw2, from == event, to == operation, name == "run" ) inite : EventTrigger (eContainer == session, name == "init" ) not (RunInstanceWire( eContainer == sw2, from == inite, to == operation, name == "run" )) then RunInstanceWire rw2 = handler.generatedRunInstanceWire(sw2, sw2, inite, operation); handler.setName(rw2, "run"); queue.add(rw2, drools); end rule "Connect parameter for Session.init to incoming SetWires (contained in Pages) [set]" when session : Session ( overridden == false ) sw : SetWire( overridden == false ) sourcePage : ContainsEventTriggers( eval(!functions.containingSessionEquals(sourcePage, session)) ) targetPage : ContainsOperations( eval(functions.containingSessionEquals(targetPage, session)) ) eval( functions.connectsSet(sw, sourcePage, targetPage )) sw2 : SetWire ( eContainer == sw, overridden == false) sourceElement : ContainsEventTriggers( eContainer == sourcePage ) targetElement : ContainsOperations( eContainer == targetPage ) eval( functions.connectsSet(sw2, sourceElement, targetElement )) event : EventTrigger( eContainer == sourceElement, name == "edit" ) operation : Operation( eContainer == targetElement, name == "update" ) rw : RunInstanceWire( eContainer == sw2, from == event, to == operation, name == "run" ) inite : EventTrigger (eContainer == session, name == "init" ) initrw : RunInstanceWire( eContainer == sw2, from == inite, to == operation, name == "run" ) field : ApplicationElementProperty( eContainer == sourceElement, name=="fieldValue" ) pw : ParameterWire( eContainer == sw2, from == field, to == rw ) not( ParameterWire( eContainer == sw2, from == field, to == initrw )) then ParameterWire pw2 = handler.generatedParameterWire(sw, sw, field, initrw); queue.add(pw2, drools); end rule "Refresh New Instance Object mappings (except for generated primary keys) when sync connected to Forms: create text fields [set]" when sync : SetWire( overridden == false ) form : InputForm ( overridden == false ) instance : DomainObjectInstance ( overridden == false ) eval(functions.connectsSet(sync, form, instance)) originalAttribute : DomainAttribute ( primaryKey == false || isGenerated == false ) attribute : DomainAttributeInstance( eContainer == instance ) ExtendsWire ( from == attribute, to == originalAttribute ) not ( tf : InputTextField( eContainer == form, eval(functions.syncMatches( attribute, tf )) ) ) then # create a new one InputTextField text = handler.generatedInputTextField(sync, form); handler.setName(text, attribute.getName()); queue.add(text, drools); end rule "Refresh Domain Object mappings (except for generated primary keys) when sync connected to Forms: create text fields [set]" when sync : SetWire( overridden == false ) form : InputForm ( overridden == false ) object : DomainObject ( overridden == false ) eval(functions.connectsSet(sync, form, object)) attribute : DomainAttribute( eContainer == object, primaryKey == false || isGenerated == false ) not ( tf : InputTextField( eContainer == form, eval(functions.syncMatches( attribute, tf )) ) ) then # create a new one InputTextField text = handler.generatedInputTextField(sync, form); handler.setName(text, attribute.getName()); queue.add(text, drools); end