![]() |
Telelogic DOORS (steve huntington) | ![]() |
new topic :
profile :
search :
help :
dashboard :
calendar :
home
|
||
Latest News:
|
|
Topic Title: Trigger - basic question Topic Summary: Created On: 19-Jun-2007 23:10 Status: Post and Reply |
Linear : Threading : Single : Branch |
![]() |
![]()
|
![]() |
|
Hi All, trig = trigger("Object text changed",attribute->"Object Text", post, modify,1,"#include <triggers/objectChange>") |
|
![]() |
|
![]() |
|
Yes, its playing with fire and having fun. Of course, for some of us playing with fire IS having fun, but I digress....
[1] Your triggers of course need a DXL to create them. That DXL should also be able to delete the trigger, and would look something like this: string NameTrig = "MyTriggerName" if (confirm("Remove Trigger " NameTrig "?")) delete(NameTrig, Priority, yaddy yaddy) if (confirm("Deploy Trigger " NameTrig "/")) trg = trigger(NameTrig, Priority, yaddy yaddy yaddy). [2] using #Include files in Layouts, AttrDXL, and Triggers is real touchy since everyone will need R access to the same network resource. For triggers, the solution is easy: [2a] string DxlOfTrigger = readFile(NameOfFile.dxl) [2b] string DxlOfTrigger = "code of the trigger, being sure to escape all slashes and double quotes" then use DxlOfTrigger in the trigger definition call. Hard coding the code of the trigger is tricky, for example a trigger and issues an 'ack' may look like this: string DxlOfTrigger = " // *** Begin DxlOfTrigger string NameMod = name(current Module) string AckCode = \"Current Module is '\" NameMod \"!\" ack(AckCode) // *** end DxlOfTrigger [3] Looking at your definition; you've defined a post-attribute-modify trigger for Object Text in the current module. What you said you wanted was a pre-module-close trigger that confirms any Object Text changes made during the current session. It would be very difficult to write triggers such that the post-attr-modify trigger leaves information around for the pre-module-close trigger to see and display to the user. Instead, forget the post-attr-modify and code the pre-module-close trigger to get the current 'session', then browse through History of the module looking for entries with that session, then if the history type is modify then check the Attribute name, and if its Object Text accumlate that fact; then display the results. Note that the 'pre' triggers differ from 'post' triggers in that [1] they occur after the event. A post-module-close trigger will not have access to the module since its closed [2] they can stop the event; in this case if your pre-module-close trigger sets the trigger status via "set(trigPreConFail)" then the module will NOT close; and perhaps your trigger close can issue a "close(current Module, true)" which will close the module and prompt to save it first. If you did that, I presume you'd want to "set(trigPreConFail)" to stop the module from closing ..err.. attempting to close after the trigger has actually closed it. .... I wonder it that will work; or would the trigger trigger again when you tried to close it..... - Louie |
|
![]() |
|
![]() |
|
Thanks, Louie, for the elaborate explanation.
I wrote the script that will identify the event if the object text is modified 'today' ( and check if I can add the current user as well as another condition). I will go through the 'mine field' with the helpful hints you gave me. But once I write the code where do I save it? The normal scripts are stored in the lib/dxl/addins folder and are accessed from the menu "dxl library". But a trigger is supposed to act without initiation when this particular module is opened and display a flag if it is attempted to be closed. Does this code go in the same lib/dxl/addins folder along with other scripts? Thanks for any suggestion. - Krishna |
|
![]() |
|
![]() |
|
Once you define the trigger, the trigger code is stored in the trigger itself. I suggested that code avoid any use of "#include" and that you insert the entire code when defining it. That idea has the negative consequence that when you want to change the trigger code you must redefine the trigger.
If you do that, you are the only one who needs access to the source of the trigger code and it doesn't matter where it is. - Louie |
|
![]() |
|
![]() |
|
Thanks again, Louie, for the reply.
Now I get the picture how I should go about it. Hopefully I'd be able to do it. But my question is where do I save the trigger code file? I write the trigger code within the trigger and a dxl file is created. In which folder do I save this file? How do I ensure that this trigger works whenever any user opens the specific module where the trigger is supposed to act? - Krishna |
|
![]() |
|
![]() |
|
The code that deploys and undeploys the trigger is presumably only needed by you, so you can store that on your client. That means only you can deploy (or undeploy) the trigger. You'll need to figure out where for all the rest of your DXL. The install folder ... addins looks like a reasonable place to start. If you use the readFile() command, THAT file likewise only needs to be accessible to you and likewise should be on your client.
Once deployed, the code of the trigger is stored in the trigger somewhere in the database and you don't care where it is actually, even though it 'appears' to be stored in the database-project-module in its scope. If that code uses no '#include' and no other references to files, then everyone who uses the database can invoke the trigger without generating DXL errors. However, if you follow the example in the manual and define a trigger like this: Trigger trg = trigger(module, pre, save, 4, "#include <filename>") then everyone who opens the module must have access to <filename>. That's generally NOT the case although its possible to put <filename> on some network drive that EVERYONE in yoru company can read, and nobody outside the company uses the database; and you don't archive the module and restore it elsewhere. - Louie |
|
![]() |
|
![]() |
|
Thanks again for the tip, Louie. I am sorry for the delayed reply. I'll get back to the forum after I tried the trigger code on the lines suggested.
|
|
![]() |
|
![]() |
|
I found the time to work on this subject again. I wanted the trigger to be applied to a specific test module. I am attaching the code for the trigger and the file that the trigger will perform. |
|
![]() |
|
![]() |
|
The delete function doesn't seem to work and I can't figure out why.
Instead, try the following which does work: for tg in m do { if ((name tg) == "myTrig") { delete(tg) break } } Also, the delete function returns a string which you should check to see if the command failed. Your code to create a trigger is fine, I suspect that the trigger is firing correctly, but the problem is in your objectOpen.dxl file. To test use "infoBox(\"hello\")" as the dxl string rather than including a file. I notice that the expression (tg name) returns the trigger name. This shouldn't work! The correct syntax is (name tg). Interesting. ------------------------- Tony Goodman http://www.smartdxl.com |
|
![]() |
|
![]() |
|
Thanks Tony for the suggestion. I tried the attached code to delete one of the two triggers. This did not work.
I created only one trigger. Where is the second trigger named "B:specific close for Modijy object text 2" coming from? And the number after "...text" changes for repeated operations. The only way I could get rid of the triggers is to delete the module. |
|
![]() |
|
![]() |
|
Perhaps it doesn't like the synonym 'modify'; try type 'save' instead. It might also not like trigger names containing spaces. It perhaps also might not like "tg name"; which seems to work but I don't see it anywhere in the DXL manual; perhaps try name(tg).
Those 'B:Specific' triggers are 'built-in' when you create a module level trigger; I believe their purpose is to make sure the original trigger code stops when the module is closed. Don't worry about them as follows: if (kind(tg) == "builtin") continue. They should be deleted when you delete the original sibling persistent trigger. - Louie |
|
![]() |
|
![]() |
|
Perhaps it doesn't like the synonym 'modify'; try type 'save' instead. It might also not like trigger names containing spaces. It perhaps also might not like "tg name"; which seems to work but I don't see it anywhere in the DXL manual; perhaps try name(tg).
Those 'B:Specific' triggers are 'built-in' when you create a module level trigger; I believe their purpose is to make sure the original trigger code stops when the module is closed. Don't worry about them as follows: if (kind(tg) == "builtin") continue. They should be deleted when you delete the original sibling persistent trigger. - Louie |
|
![]() |
|
![]() |
|
Thanks for the response, Louie. As you pointed out, I found that the second trigger is a built-in trigger. That is getting automatically introduced when I am deploying my trigger.
Secondly, I realized that the code I was using for deleting the triggers is not correct. The corrected code is attached. In the trigger code itself, I am not finding any difference in the operation whether I use "modify" or "save". If I use "pre" event, the Object Text does not get corrected at all ( it goes back to the original text when I move to another object); when I use "post" event, the Object Text remains corrected with the infoBox displaying the message. When I use the "post" trigger, I believe that I cannot use the TriggerStatus constants. What exactly is the purpose of these TriggerStatus constants? What will happen if I do not include them in the code? - Krishna |
|
![]() |
|
![]() |
|
One more question - The code line
tg = trigger(trigName,module->attribute->"Object Text" ,pre, save, 10, myDXL) works well when the Object Text is changed. I understand if "Object Text" is replaced by "all", this applies to all the attributes. If I want to have this trigger for more than one attribute (say three), how can I do it? I tried to read the attribute name (attrdef(trig)) where I am operating and compare it with the required attributes (any one of the three), but that does not work. Do I have to run three separate triggers? - Krishna |
|
![]() |
|
![]() |
|
'Pre' triggers are used to control whether the event actually happens. If a pre-trigger sets trigPreConFail then the event does NOT occur. I prime use of that is a pre-attr-save trigger where the trigger only allows saving the attr value if its valid. I don't know if you must explicitely set(trigPreConPass) in order to let the event occur, but looking at your example I suspect that in fact you do; put it after your infoBox(Entered Comments?). I don't know what trigRunOK or trigError are for.
I'm sure that these statuses are allowed but ignored in post-triggers. The 'set(status)' commands go into the DXL of the trigger, not in the code that defines the trigger. Its obvious, but pre-triggers occur before the event and post-triggers after. e.g. you cannot get a handle on the 'Module' in pre-module-open triggers nor in post-module-close triggers. That means your pre-or-post decision is mostly based on whether you need access to the primary factor in the trigger, an open module or an edited attribute value. That will result in you having some pre-triggers that always set(trigPreConPass) and never fail. e.g. if your trigger needs a module then it must be post-module-open or pre-module-close (or some sort of object or attribute trigger), and it it needs an attribute and value then it must be a pre-attr-save trigger. ... I digress, but I wonder if you can defined a pre-open-module trigger stored in a specific module, since you have to open the module to get the trigger but by then the event has happened... The 'string attribute(Trigger)' perm returns the name of the attribute to which the trigger was defined. This perm will work when some outside DXL is looping through triggers, perhaps 'for trg in module do'. I suspect perhaps it will return 'all' if the trigger applies to all attributes. The 'AttrDef attrdef(Trigger)' perm, I believe, only works inside an attribute trigger and returns the attribute that fired the trigger. That is, MyDXL can use this perm. There is also an undocumented 'string attrdef(Trigger)' that may be more useful. I'm pretty sure these will only work in pre-save-attr triggers, explaining why they didn't work for you. These calls would be preceded with 'Trigger tCurr = current' in MyDXL; which likewise only works inside the body of a trigger. Your strategy of coding the trigger to get the name of the attribute and stop unless its one of the correct three is sound. Define such a trigger as pre-save-attr that applies to all attributes. set(trigPreConPass) Trigger tCurr = current string NameAttr = attrdef(tCurr) if (NameAttr isn't one of my 3) halt string Value = value(tCurr) if (Value isn't compatible with NameAttr) {infoBox(Warn the User); set(trigPreConFail)} I suppose 'pre' triggers could be lumped into three categories: [1] Allow the event unles the trigger can think of a good reason to prevent it: set(trigPreConPass) if (this trigger doesn't apply) halt if (certain bad condition is detected) set(trigPreConFail) [2] Disallow the event unless the trigger can verify its OK to go: set(trigPreConFail) if (this trigger doesn't apply) halt if (certain good condition is detected) set(trigPreConPass) [3] Always allows the event: set(trigPreConPass) check for conditions, perhaps warn the user. Its like Mom said: Triggers, like Bull Fighting, are not for the feint of heart. - Louie |
|
![]() |
|
![]() |
|
Louie, thanks for the detailed response. infoBox(NameAttr) |
|
![]() |
|
![]() |
|
Looking back on the code, the choice of the "else" condition may not be correct. If the first element of the array is not the chosen attribute, the comparison does not proceed further.
|
|
![]() |
Telelogic DOORS
» DXL Exchange
»
Trigger - basic question
|
![]() |
FuseTalk Standard Edition v3.2 - © 1999-2009 FuseTalk Inc. All rights reserved.