I’m working on a project with more or less 50 modules and thousands objects for module.
I need to modify the “inherit from parent” field on some objects of each module.
The one way I found to do it is to open each module and run the following dxl script I did… obviously, open all modules is a crazy solution!!!
/*
** Set_Inherit_Attribute_FALSE ***
Remove flag from the attribute "Inherit from Parent"
on each object of each module of the project
*/
// Variable definition
Object o
Module m
string serr
// file name provided by DOORS containing the results
string filename = tempFileName
print "FILE CONTAINING RESULTS - " filename "\n"
// open file in write mode
Stream outputLog = write filename
// Set current project
Project prj = current Project
print "PROJECT - "(name prj) "\n"
outputLog << "-------------------- PROJECT " (name prj) " --------------------\n\n"
// Management of each module in the project
for m in prj do {
// write in outputLog the MODULE name
outputLog << "\n**************** MODULE " (name m) " ****************\n"
// set the "inherited" to false
for o in entire m do {
// The "Inherited" has to be updated just for NOT LEAF object
if (!leaf(o)){
// write in outputLog the obj id modified
outputLog << "OBJ ID " (identifier o) "\n"
serr = specific(o)
// Check if the set of "inherited" failed
if (!null serr){
// inform the user and stop the execution
outputLog << "OBJECT ERROR"
ack "ERROR INHERITED"
// close outputLog
close outputLog
halt
}
}
}
// save modificiation on module m
save m
}
// close outputLog
close outputLog
// Inform the user the execution is ended
ack "EXECTUTION COMPLETED"
Is there a way to do the same modification without open all modules?
Thanks.
The loop 'for m in prj do' will act only on modules that you have previously opened manually in the DOORS graphical user interface.
To solve that, my modification of your code (below) loops through all items (folders, projects, formal and link modules) in each project, and opens any formal modules it finds for itself. It's important to close modules after processing, to free memory, so my modification does that, too.
/*
** Set_Inherit_Attribute_FALSE ***
Remove flag from the attribute "Inherit from Parent"
on each object of each module of the project
*/
// Variable definition
Item i
Object o
Module m
string serr
// file name provided by DOORS containing the results
string filename = tempFileName
print "FILE CONTAINING RESULTS - " filename "\n"
// open file in write mode
Stream outputLog = write filename
// Set current project
Project prj = current Project
print "PROJECT - "(name prj) "\n"
outputLog << "-------------------- PROJECT " (name prj) " --------------------\n\n"
// Management of each module in the project
for i in prj do {
if (type(i) == "Formal")
{
m = edit(fullName(i), false)
// write in outputLog the MODULE name
outputLog << "\n**************** MODULE " (name m) " ****************\n"
// set the "inherited" to false
for o in entire m do {
// The "Inherited" has to be updated just for NOT LEAF object
if (!leaf(o)){
// write in outputLog the obj id modified
outputLog << "OBJ ID " (identifier o) "\n"
serr = specific(o)
// Check if the set of "inherited" failed
if (!null serr){
// inform the user and stop the execution
outputLog << "OBJECT ERROR: " serr
ack "ERROR INHERITED"
// close outputLog
close outputLog
halt
}
}
}
// save modificiation on module m
save(m)
close(m)
}
}
// close outputLog
close outputLog
// Inform the user the execution is ended
ack "EXECUTION COMPLETED"
Also, note that your 'for o in entire m do' loop (quote from the DXL reference manual):
Assigns the variable o to be each successive object in module regardless of its deleted state or the current display set. It includes table and row header objects and the cells.
Are you sure this is what you intend?
In order to modify an object, you do have to open the module. In this case, I would be focused on closing modules after they have been checked to minimize memory load.
/*
** Set_Inherit_Attribute_FALSE ***
Remove flag from the attribute "Inherit from Parent"
on each object of each module of the project
*/
// Variable definition
Object o
Module m
string serr
// file name provided by DOORS containing the results
string filename = tempFileName
print "FILE CONTAINING RESULTS - " filename "\n"
// open file in write mode
Stream outputLog = write filename
// Set current project
Project prj = current Project
print "PROJECT - "(name prj) "\n"
outputLog << "-------------------- PROJECT " (name prj) " --------------------\n\n"
// Management of each module in the project
for m in prj do {
// write in outputLog the MODULE name
outputLog << "\n**************** MODULE " (name m) " ****************\n"
// set the "inherited" to false
for o in entire m do {
// The "Inherited" has to be updated just for NOT LEAF object
if (!leaf(o)){
// write in outputLog the obj id modified
outputLog << "OBJ ID " (identifier o) "\n"
serr = specific(o)
// Check if the set of "inherited" failed
if (!null serr){
// inform the user and stop the execution
outputLog << "OBJECT ERROR"
ack "ERROR INHERITED"
// close outputLog
close outputLog
halt
}
}
}
// save modificiation on module m
save m
Module close_mod = m
close ( close_mod )
}
// close outputLog
close outputLog
// Inform the user the execution is ended
ack "EXECTUTION COMPLETED"
If you look above, I added:
Module close_mod = m
close ( close_mod )
inside the for m in proj loop. If you ran close(m), the DXL loop would throw an error the next time it tried to assign the 'm' variable. So you end up having to declare a separate module handle and running close against that.
This should keep your memory more manageable. I would also consider running the whole thing via an 'eval_' statement, but that may not be needed.
Related
I have following error message :
DEBUG: isBaseline(spec_produit) = true -R-E- DXL: <D:\XXXX.dxl:1234> Un module en cours est requis pour lopération
US traduction = operation requires a current module
line 1234 is the following : print "DEBUG: baseline loaded for " name(module_in_database) " = " major(baseline_open) "." minor(baseline_open) suffix(baseline_open) "\n"
With : baseline_open = baselineInfo(module_in_database) (=true)
I don't understand why I have this message as I already use this kind of coding elsewhere with success.
Here I have the message in a loop that I use to detect if I have still open module after having close all open modules (I don't know why I still have open module but it is another subject)
the loop is :
// display list of open module at then end of the script
for module_in_database in database do
{
logResult = logResult "INFO: open modules at the end the script are " fullName(module_in_database) "\n"
// display more information on open modules : (DEBUG) :
print "DEBUG: isBaseline(" name(module_in_database) ") = " isBaseline(module_in_database) "\n"
baseline_open = baselineInfo(module_in_database)
if (baseline_open != null) {
print "DEBUG: baseline loaded for" name(module_in_database) " = " major(baseline_open) "." minor(baseline_open) suffix(baseline_open) "\n"
} else {
print "DEBUG: " name(module_in_database) " = CURRENT \n"
}
}
Version 1:
Module module_in_database
Baseline baseline_open
string logResult = ""
// display list of open module at then end of the script
for module_in_database in database do
{
logResult = logResult "INFO: open modules at the end the script are " fullName(module_in_database) "\n"
if type (module_in_database) == "Formal" then {
// display more information on open modules : (DEBUG) :
print "DEBUG: isBaseline(" name(module_in_database) ") = " isBaseline(module_in_database) "\n"
baseline_open = baselineInfo(module_in_database)
if (baseline_open != null) {
current = module_in_database // <------ set current module so that the next line works!
print "DEBUG: baseline loaded for" name(module_in_database) " = " major(baseline_open) "." minor(baseline_open) suffix(baseline_open) "\n"
} else {
print "DEBUG: " name(module_in_database) " = CURRENT \n"
}
} else {
print fullName(module_in_database) " is a Link Module. No baselineInfo available\n"
}
}
Version 2:
Module module_in_database
Baseline baseline_open
string logResult = ""
ModuleVersion mv
string version_string
// display list of open module at then end of the script
for module_in_database in database do
{
logResult = logResult "INFO: open modules at the end the script are " fullName(module_in_database) "\n"
if type (module_in_database) == "Formal" then {
// display more information on open modules : (DEBUG) :
print "DEBUG: isBaseline(" name(module_in_database) ") = " isBaseline(module_in_database) "\n"
mv = moduleVersion (module_in_database)
version_string = versionString (mv) // <---- don't use "major" and "minor", instead use version_string, which does not require a "current" module
if (version_string != "") {
print "DEBUG: baseline loaded for" name(module_in_database) " = " version_string "\n"
} else {
print "DEBUG: " name(module_in_database) " = CURRENT \n"
}
} else {
print fullName(module_in_database) " is a Link Module. No baselineInfo available\n"
}
}
P.S: Having read through our thread again, I think that the misunderstanding stems from DOORS' inconsistency when naming things. a "current version" is a Module which is not a baseline. A "current module" in DOORS-speak is a module version that is "the one '''module''' that the user currently interacts with". When you have opened five windows with modules (either current version or baselines or link modules), only one of these windows is at the front - only one of these windows catches your keyboard input - and that window contains the "current" Module. If you have a one-liner like print fullName (current Module) and you open the database explorer (main window), click on Tools->Edit DXL… and paste the code, it will complain that no Module is current. if you then click on one window and in this window click on Tools->Edit DXL…, you will get the SAME DXL window, but now the code will run, because now DOORS knows which Module is the one that you mean when you say fullName (current Module).
Unfortunately, that's still not correctly said: the current Module is not directly related to the window at the front - you might even have opened Modules invisibly. And using DXL you can say "this invisible Module is the current one" although there is a window at the front showing a different Module.
It's complicated but I hope that I explained it correctly now.
Strange.
I have been able to run the script with the following declarations
Module module_in_database
Baseline baseline_open
string logResult = ""
and I got the expected results.
I remember some problems with perms that expect a current module even though they shouldn't.
Perhaps you just need to add some lines to your loop
if type (module_in_database) == "Formal" then {
current = module_in_database
} else {
continue
}
but still, that should not be necessary
I'm new to using DOORS and am trying to create a column/attribute that has the date of the last modification to the Object Text. I found the below code which uses "Last Modified On", but that that includes all attributes and I'm only concerned about the Object Text. Maybe there's a way to specifiy an attribute for this?
Date dMod
dMod = obj."Last Modified On"
dMod = dateAndTime(dMod)
display dMod ""
There's no such attribute on an attribute.
The only way to determine this is via the object's history. Below is the example script from DXL manual. The idea is to loop through the object's history until the history record's typeis modifyObjectand it's attrName equals 'Object Text'. Keep in mind, though, that the history in a module only goes back to the last baseline. So, you may have to browse through all baselines to find the history record you need. See Tony's "Smart History Viewer" at http://www.smartdxl.com/content/?page_id=125 for details.
// history DXL Example
/*
Example history DXL program.
Generate a report of the current Module's
history.
*/
// print a brief report of the history record
void print(History h) {
HistoryType ht = h.type
print h.author "\t" h.date "\t" ht "\t"
if (ht == createType ||
ht == modifyType ||
ht == deleteType) { // attribute type
print h.typeName
} else if (ht == createAttr ||
ht == modifyAttr ||
ht == deleteAttr) {
// attribute definition
print h.attrName
} else if (ht == createObject ||
ht == clipCopyObject ||
ht == modifyObject) { // object
print h.absNo
if (ht==modifyObject) {
// means an attribute has changed
string oldV = h.oldValue
string newV = h.newValue
print " (" h.attrName ":" oldV " -> " newV ")"
}
}
print "\n"
}
// Main program
History h
print "All history\n\n"
for h in current Module do print h
print "\nHistory for current Object\n\n"
for h in current Object do print h
print "\nNon object history\n\n"
for h in top current Module do print h
I'm new on DXL and working on something that is probably quite simple.
I would like to parse the current module, and get the following data for each object that has a given ID (calling IDNUM below) not empty:
IDNUM - Object text - all text with a lower hierarchic level and the same thing for all objects liked to this one.
It will probably be easier to understand with the code. So far, it looks like that:
Object o
Object ol
Link l
Module m = current Module
For o in entire(m) do{
if (o."IDNUM" != ""){
print o."IDNUM" ""
print o."text" ""
//HERE I WOULD LIKE TO ALSO PRINT EVERY TEXT IN OBJECT "LOWER" THAN o
for l in o --> "*" do{
ol = target(l)
print ol."text" ""
//HERE I WOULD LIKE TO ALSO PRINT EVERY TEXT IN OBJECT "LOWER" THAN ol
}
}
}
Basically, I have the ID and title of both an object and the one liked to it, but not the text below. In other words, my code will "mimic" the function right click>copy>copy with hierarchy
How can I do that? Unfortunately I didn't find anything very helpful.
Thanks a lot in advance,
Here is the sketch code you outlined:
Object o
Object ol
Link l
Module m = current Module
For o in entire(m) do{
if (o."IDNUM" != ""){
print o."IDNUM" ""
print o."text" ""
//HERE I WOULD LIKE TO ALSO PRINT EVERY TEXT IN OBJECT "LOWER" THAN o
for l in o --> "*" do{
ol = target(l)
print ol."text" ""
//HERE I WOULD LIKE TO ALSO PRINT EVERY TEXT IN OBJECT "LOWER" THAN ol
}
}
}
There are a few little syntax things that need to be changed here, but the big change is how you are handling linked items. Links 'live' in the source module, but they only store a limited amount of information, mostly the modules that are the source and target of the link, and the absolute numbers of the objects they touch. So you need to check if the module on the other side is open before you try and read text from it.
And since you are trying to go through the entire link structure, you'll need a recursive element to this.
I would probably end up with something like this:
//turn off run limit timer- this might take a bit
pragma runLim , 0
Object o
Module m = current Module
// Recursive function- assumes each object has a text attribute- will error otherwise
void link_print(Object obj) {
print obj."text" "\n"
Link out_link
Object next_obj = null
for out_link in obj -> "*" do {
// Set the next object in the chain
next_obj = target ( out_link )
// This might return null if the module is not loaded
if ( null next_obj ) {
// Load the module in read-only mode, displayed and in standard view
read ( fullName ( ModName_ target ( out_link ) ) , true , true )
// Try and resolve out 'target' again
next_obj = target ( out_link )
// If it doesn't work, print a message so we can figure it out
if ( null next_obj ) {
print "Error Accessing Object " ( targetAbsNo ( out_link ) )""
} else {
//Iterate down structure
link_print ( next_obj )
}
} else {
//Iterate down structure
link_print ( next_obj )
}
}
}
for o in entire(m) do {
// Note that I cast the result of o."IDNUM" to a string type by appending ""
if (o."IDNUM" "" != ""){
print o."IDNUM" "\n"
// Recurse
link_print(o)
print "\n"
}
}
Note! Depending on the size of your link structure, i.e. how many levels you have (and if there are any circular link patterns), this could be a pretty resource intensive task, and would be better solved using something other than "print" commands (like appending it to a word file, for example, so you know how far it got before it errored out)
Good luck!
EDIT:
Rather than head down recursively, this script will now go a single level but should report child objects.
//turn off run limit timer- this might take a bit
pragma runLim , 0
Object o
Module m = current Module
// Recursive function- assumes each object has a text attribute- will error otherwise
void link_print(Object obj) {
print obj."text" "\n"
Link out_link
Object next_obj = null
Object child_obj = null
for out_link in obj -> "*" do {
// Set the next object in the chain
next_obj = target ( out_link )
// This might return null if the module is not loaded
if ( null next_obj ) {
// Load the module in read-only mode, displayed and in standard view
read ( fullName ( ModName_ target ( out_link ) ) , true , true )
// Try and resolve out 'target' again
next_obj = target ( out_link )
// If it doesn't work, print a message so we can figure it out
if ( null next_obj ) {
print "Error Accessing Object " ( targetAbsNo ( out_link ) )""
} else {
// Loop and report on child objects
for child_obj in next_obj do {
print child_obj."text" "\n"
}
}
} else {
// Loop and report on child objects
for child_obj in next_obj do {
print child_obj."text" "\n"
}
}
}
}
for o in entire(m) do {
// Note that I cast the result of o."IDNUM" to a string type by appending ""
if (o."IDNUM" "" != ""){
print o."IDNUM" "\n"
// Recurse
link_print(o)
print "\n"
}
}
Dear Russell (and everyone else)
I've just went through the piece of code you provided me and it works.... but not for what I'm looking for. It seems my explanation wasn't very clear. I'm sorry (I'm not a native speaker).
I'm not looking to get all links, but just the Object text that is written just below the object pointed by the current link.
Here is what my files look like
object1 (with IDNUM) : "Title_doc_1" --> (link) objectA "Title_doc_2"
object2 : "some_text" objectB : "some_text"
object3 : "some_text" objectC : "some_text"
(object1 can point to many other objectA but I already deal with that.)
The code I provided above parses the "doc_1", and print "IDNUM" "Title_doc_1" "Title_doc_2"
What I'm looking for is to get, not only objectA but also objectB and objectC which are hierarchically below objectA (and object2 and object3 too but it will ve the same process).
Hopping I made myself understood...
I'm working on a DXL program in Doors which supposed to output to a csv file all of source module, target, linkset and version of each (source/target) modules. I've succeed to output "source module, target, linkset but I couldn't extract the version of modules. Does anyone know how to do it ?
Here is my code bellow:
The following uses an output file which is in C:\Temp, but you can easily change that.
it works by matching modules using a grep string, again which you can change to suit.
I have different module types, and therefore I can just get the results on the prefix 'STR' in this case. I decided to have multiple scripts for different prefix modules, rather than dynamically pass the STR keyword.
You need to enter your folder and subfolders for the "modPathname"
then adjust the Regexp "GrepString" to suit your naming convention
alternatively you can bypass all this by hardcoding the values.
string filename = "C:\\TEMP\\STR_Baseline_Info.txt"
Stream outFile = write filename
string Modtype = "STR"
void PrintAndOutput ( string s)
{
// print (s) // Enable if you want output
outFile << s
}
void DisplayResults( string Modtype )
{
Item modItem
Module mName
Regexp GrepString = regexp2 "^" Modtype "-[0-8][0-9][0-9]"
Folder modPathname = folder "/EnterYourFolderHere/AnySubFolders/" Modtype ""
string fullModuleName , CommentStr , moduleName
Baseline b
PrintAndOutput "------------------------------------------------------------------------------\n"
CommentStr = "This File is automatically produced via the " Modtype " Baseline Info.dxl script. \n" Modtype " Versions as of : " dateAndTime(today) "\n"
PrintAndOutput CommentStr
PrintAndOutput "-------------------------------------------------------------------------------\n\n"
for modItem in modPathname do
{
if (type (modItem ) == "Formal")
{
moduleName = (name modItem)
if (GrepString moduleName)
{
fullModuleName = (fullName(modItem))
mName = read(fullName modItem , false)
b= getMostRecentBaseline (mName)
if (b != null )
{
PrintAndOutput moduleName " -\tBaseline : "(major b)"."(minor b)(suffix b) " \t " (dateOf b) "\n"
}
else
{
PrintAndOutput moduleName " \t### No Baseline Information ### \t" " \n"
}
}
}
}
}
DisplayResults ( Modtype)
I have the following situation.
I want to count in Module 1, how many objects are having links in links from Module 3.
example:
Module 1 Obj1 <- Module 2 Obj1 <- Module 3.Obj1
Module 1 Obj2 <- Module 2 Obj1 <- Module 3.Obj1
Module 1 Obj3 <- Module 2 Obj1 <- Module 3.Obj1
Module 1 Obj4 <- Module 2 Obj1
Module 1 Obj5 <- Module 2 Obj1
The count should return 3, in the above case.
Is it possible via DXL to follow a link, and then follow another link?
(not using the Wizard or DXL attributes)
Most important for me: knowing if somebody else did this and it's possible to do.
Please try the following DXL from within the module that has the incoming links. Before running the code:
make sure that you open the 'Edit DXL' window from the relevant module
set the string values assigned to global constant STR_LINK_MOD_FULLNAME (line 17) to the full pathname of the link module whose links you are interested in
set the string values assigned to global constant STR_SRC_MOD_FULLNAME (line 18) to the full pathname of the source formal module (Module 3, in your example) whose links you are interested in
You shouldn't need to change anything else to make it work.
N.B. I have not considered the implications of analysing links in all link modules by using the string "*" in place of a specific link module name in line 17 (see point 2, above).
I also haven't gone out of my way to explain the code, though I have tried to be nice and tidy up after myself where DOORS and DXL require it. Please feel free to reply with any questions on what I have done.
Kind regards,
Richard
//<CheckObjectInNestedLink.dxl>
/*
*/
///////////////
// Sanity check
if (null (current Module))
{
print "ERROR: this script must be run from a Formal Module."
}
///////////////////
// Global Constants
const string STR_LINK_MOD_FULLNAME = "/New Family Car Project/Admin/Satisfies" // the fullName of a single link module - results of using "*" have not been considered/tested
const string STR_SRC_MOD_FULLNAME = "/New Family Car Project/Architecture/Architectural Design" // The fullName of the desired source Formal Module
///////////////////
// Global Variables
Module modSource = null
Object objTarget = null
Object objSource = null
Link lkIn = null
Skip skLinkedMods = create()
Skip skObjsWithDesiredSource = create()
int intNoOfLinked = 0
//////////////////////
// Auxiliary Functions
void closeSourceMods ()
{
Module srcMod
for srcMod in skLinkedMods do
{
close(srcMod)
}
}
void openSourceMods (Object objWithLinks)
{
ModName_ srcModRef
Module srcMod
for srcModRef in (objWithLinks <- STR_LINK_MOD_FULLNAME) do
{
srcMod = read(fullName(srcModRef), false)
put(skLinkedMods, srcMod, srcMod)
}
}
void recurseFollowInLinks (Object objWithLinks)
{
openSourceMods(objWithLinks)
for lkIn in objWithLinks <- STR_LINK_MOD_FULLNAME do
{
openSourceMods(objWithLinks)
objSource = source(lkIn)
string strSrcModName = fullName(module(objSource))
if (strSrcModName == STR_SRC_MOD_FULLNAME)
{
bool blNewEntry = put(skObjsWithDesiredSource, objTarget, objTarget)
if (blNewEntry)
{
intNoOfLinked++
}
//print "put(skObjsWithDesiredSource, " identifier(objTarget) ", " identifier(objTarget) ")\n"
}
recurseFollowInLinks(objSource)
}
}
void checkObjectInNestedLink (Module modThis, string strSourceModuleFullname, string strLinkModuleFullName)
{
intNoOfLinked = 0
for objTarget in modThis do
{
recurseFollowInLinks(objTarget)
}
print "The following " intNoOfLinked " objects have direct or indirect links of type " STR_LINK_MOD_FULLNAME " from formal module " STR_SRC_MOD_FULLNAME ":\n"
for objTarget in skObjsWithDesiredSource do
{
print identifier(objTarget)
print "\n"
}
}
///////////////
// Main Program
checkObjectInNestedLink ((current Module), STR_SRC_MOD_FULLNAME, STR_LINK_MOD_FULLNAME)
closeSourceMods()
delete(skLinkedMods)
delete(skObjsWithDesiredSource)