This script was developed to support parallel development on a project where requirements were branched and merged. This used a specific (one-to-one) link module to link master and branched requirements.
This script provides a simple to use dialog that enables you to copy attribute values from the “master” requirement to the local copy. It assumes that each requirement is a branched copy of a master requirement and that they are linked one-to-one.
// Copy Attributes Down /* Copy attribute values from (out) linked requirements to the current module. Provides a dialog to control the update of the local copy of requirements that have been flowed down. Tony Goodman Initial Version */ // Current module Module localModule = null // dialog box elements DB dbMain = null DBE dbeDialogLabel = null DBE dbeFrame = null DBE dbeLocalModuleFrame = null DBE dbeLocalModule = null DBE dbeMasterRequirementsFrame = null DBE dbeRelationships = null DBE dbeSpacer = null DBE dbeMasterModules = null DBE dbeAttributes = null DBE dbeUpdate = null DBE dbeJustCheck = null DBE dbeSelectAll = null DBE dbeClearAll = null string dummy[] = {} Skip skipLocalAttributes = createString Skip skipMasterAttributes = createString Skip skipRelationships = createString Skip skipMasterModules = createString Skip skipSelectedMasterModules = createString Skip skipSelectedAttributes = createString bool relationshipsFound = false string selectedRelationship = "" Buffer errBuf = create int errors = 0 int objectsUpdated = 0 /******************** getAttributes **********************/ string getAttributes() { string mName = "" Module masterModule = null AttrDef ad = null string attr = "" int i = 0 empty(dbeAttributes) if (!relationshipsFound) { inactive(dbeAttributes) return("") } delete(skipMasterAttributes) skipMasterAttributes = createString for mName in skipSelectedMasterModules do { masterModule = read(mName, false) if (null masterModule) { return("Error opening module:\n" mName) } (current ModuleRef__) = masterModule filtering off outlining off for ad in masterModule do { if (!ad.object) continue if (ad.name == "Absolute Number") continue if (ad.system) continue put(skipMasterAttributes, ad.name, ad.name) } } delete(skipLocalAttributes) skipLocalAttributes = createString (current ModuleRef__) = localModule for ad in localModule do { if (!ad.object) continue if (ad.dxl) continue if (ad.name == "Absolute Number") continue if (ad.system) continue if (!find(skipMasterAttributes, ad.name)) continue put(skipLocalAttributes, ad.name, ad.name) } put(skipLocalAttributes, "Object Heading", "Object Heading") put(skipLocalAttributes, "Object Text", "Object Text") // Refresh dialog i = 0 for attr in skipLocalAttributes do { insert(dbeAttributes, i, attr, iconNone) setCheck(dbeAttributes, i, true) i++ } return("") } /******************** getMasterModules *********************/ void getMasterModules() { ModName_ mn = null Object o = null Link l = null string mName = "" int i = 0 empty(dbeMasterModules) if (!relationshipsFound) { return() } delete(skipMasterModules) skipMasterModules = createString delete(skipSelectedMasterModules) skipSelectedMasterModules = createString for o in localModule do { for l in o -> "*" do { if (name(module(l)) != selectedRelationship) continue mn = target(l) put(skipMasterModules, fullName(mn), fullName(mn)) } } i = 0 for mName in skipMasterModules do { insert(dbeMasterModules, i, mName, iconNone) set(dbeMasterModules, i, true) i++ put(skipSelectedMasterModules, mName, mName) } } /********************** getRelationships *********************/ void getRelationships() { Object o = null Link l = null int i = 0 string relationship = "" delete(skipRelationships) skipRelationships = createString for o in localModule do { for l in o -> "*" do { put(skipRelationships, name(module(l)), name(module(l))) relationshipsFound = true } } if (relationshipsFound) { i = 0 for relationship in skipRelationships do { insert(dbeRelationships, i++, relationship) } } else { insert(dbeRelationships, 0, "<no relationships found>") inactive(dbeUpdate) } set(dbeRelationships, 0) selectedRelationship = get(dbeRelationships) } /******************* updateObject *********************/ void updateObject(Object o, Object othero) { string attr = "" for attr in skipSelectedAttributes do { // ignores attributes that do not exist without error copyAttribute_(othero, o, attr) } objectsUpdated++ } /********************* doSelectMasterModules *********************/ void doSelectMasterModules(DBE dbe, int x) { string res = "" string mName = "" delete(skipSelectedMasterModules) skipSelectedMasterModules = createString for mName in dbeMasterModules do { put(skipSelectedMasterModules, mName, mName) } res = getAttributes() if (res != "") { infoBox("ERROR: " res) } } /******************** doSelectRelationship *********************/ void doSelectRelationship(DBE dbe) { string res = "" selectedRelationship = get(dbeRelationships) getMasterModules() res = getAttributes() if (res != "") { infoBox("ERROR: " res) } } /********************* doUpdate *********************/ void doUpdate(DB db) { ModName_ mn = null string res = "" Object o = null Object othero = null Link l = null string attr = "" string mName = "" int i = 0 if (!confirm("You are about to update requirements in the current module with values\n" //- "copied from linked master requirements.\n\nAre you sure you want to continue?")) { return } delete(skipSelectedAttributes) skipSelectedAttributes = createString for (i = 0; i < noElems(dbeAttributes); i++) { if (getCheck(dbeAttributes, i)) { attr = getColumnValue(dbeAttributes, i, 0) put(skipSelectedAttributes, attr, attr) } } for o in localModule do { for l in o -> "*" do { if (name(module(l)) != selectedRelationship) continue mn = target(l) if (!find(skipSelectedMasterModules, fullName(mn))) continue othero = target(l) if (null othero) { errBuf += "Object " identifier(o) " is linked to a null object\n" errors++ continue } if (isDeleted othero) { errBuf += "Object " identifier(o) " is linked to a deleted object\n" errors++ continue } updateObject(o, othero) } } if (errors > 0) { infoBox("Update complete, but with errors:\n" stringOf(errBuf)) } else { infoBox("Update completed successfully.\n" //- objectsUpdated " object" (objectsUpdated == 1 ? " has " : "s have " ) //- "been updated\nPlease remember to save your module.") } release(dbMain) } /********************* doSelectAll *********************/ void doSelectAll(DBE dbe) { int i = 0 for (i = 0; i < noElems(dbeAttributes); i++) { setCheck(dbeAttributes, i, true) } } /******************** doClearAll *********************/ void doClearAll(DBE dbe) { int i = 0 for (i = 0; i < noElems(dbeAttributes); i++) { setCheck(dbeAttributes, i, false) } } /********************* doClose *********************/ void doClose(DB db) { release(dbMain) } /******************** buildDialog *********************/ void buildDialog() { string res = "" dbMain = create(localModule, "Copy Attributes Down", styleCentered) dbeDialogLabel = label(dbMain, "This utility allows you to update attribute values in your local copy of requirements.\n" //- "Values are copied from the master requirements that they are linked to via the selected relationship.\n" //- "Only values for the selected attributes are compared and updated.") dbeFrame = frame(dbMain, "", 450, 460) dbeFrame->"top"->"flush"->dbeDialogLabel dbeFrame->"left"->"form" dbeFrame->"right"->"form" dbeFrame->"bottom"->"form" dbeLocalModuleFrame = frame(dbMain, "Local requirements module", 400, 20) dbeLocalModuleFrame->"top"->"inside"->dbeFrame dbeLocalModuleFrame->"left"->"inside"->dbeFrame dbeLocalModuleFrame->"right"->"inside"->dbeFrame dbeLocalModuleFrame->"bottom"->"unattached" dbeLocalModule = field(dbMain, "", fullName(localModule), 50, true) dbeLocalModule->"top"->"inside"->dbeLocalModuleFrame dbeLocalModule->"left"->"inside"->dbeLocalModuleFrame dbeLocalModule->"right"->"inside"->dbeLocalModuleFrame dbeLocalModule->"bottom"->"inside"->dbeLocalModuleFrame dbeMasterRequirementsFrame = frame(dbMain, "Master requirements", 400, 360) dbeMasterRequirementsFrame->"top"->"flush"->dbeLocalModuleFrame dbeMasterRequirementsFrame->"left"->"inside"->dbeFrame dbeMasterRequirementsFrame->"right"->"inside"->dbeFrame dbeMasterRequirementsFrame->"bottom"->"inside"->dbeFrame dbeRelationships = choice(dbMain, "Relationship:", dummy, 0, 30, false) dbeRelationships->"top"->"inside"->dbeMasterRequirementsFrame dbeRelationships->"left"->"inside"->dbeMasterRequirementsFrame dbeRelationships->"right"->"inside"->dbeMasterRequirementsFrame dbeRelationships->"bottom"->"unattached" dbeMasterModules = listView(dbMain, listViewOptionMultiselect, 400, 5, dummy) dbeMasterModules->"top"->"flush"->dbeRelationships dbeMasterModules->"left"->"inside"->dbeMasterRequirementsFrame dbeMasterModules->"right"->"inside"->dbeMasterRequirementsFrame dbeMasterModules->"bottom"->"unattached" dbeAttributes = listView(dbMain, listViewOptionCheckboxes | listViewOptionMultiselect, 400, 10, dummy) dbeAttributes->"top"->"flush"->dbeMasterModules dbeAttributes->"left"->"inside"->dbeMasterRequirementsFrame dbeAttributes->"right"->"inside"->dbeMasterRequirementsFrame dbeAttributes->"bottom"->"unattached" dbeSelectAll = button(dbMain, "Select All", doSelectAll) dbeSelectAll->"top"->"flush"->dbeAttributes dbeSelectAll->"left"->"inside"->dbeMasterRequirementsFrame dbeSelectAll->"right"->"unattached" dbeSelectAll->"bottom"->"inside"->dbeMasterRequirementsFrame dbeClearAll = button(dbMain, "ClearAll", doClearAll) dbeClearAll->"top"->"flush"->dbeAttributes dbeClearAll->"left"->"flush"->dbeSelectAll dbeClearAll->"right"->"unattached" dbeClearAll->"bottom"->"inside"->dbeMasterRequirementsFrame dbeUpdate = apply(dbMain, "Update", doUpdate) realize(dbMain) insertColumn(dbeAttributes, 0, "Attributes to compare/update", 430, iconNone) insertColumn(dbeMasterModules, 0, "Master requirements modules", 430, iconNone) set(dbeRelationships, doSelectRelationship) set(dbeMasterModules, doSelectMasterModules, doSelectMasterModules, doSelectMasterModules) getRelationships() getMasterModules() getAttributes() block(dbMain) destroy(dbMain) dbMain = null } /*************************** requirementsFlowDown ***************************/ void requirementsFlowDown() { localModule = current Module if (null localModule || !isEdit localModule) { infoBox("This utility can only be run from a formal module open for exclusive edit.") halt } (current ModuleRef__) = localModule buildDialog() } /*************************** MAIN ***************************/ requirementsFlowDown()