// Compare current module version with previous baseline /* Display modifications of attributes displayed in current view with respect to a previous baseline. The current view can either be the current module or a baseline version. Modified OLE objects are NOT detected! Modifications are either shown w.r.t to a specified baseline, the last baseline, the last minor baseline or the last major baseline Optionally, the attribute value(s) from the previous baseline can be shown To use the script, create a new column and put the following lines into Layout DXL: #include modifications( bool show_changes_inline, show_only_modifications, string baseType ) Alternatively, the routine call can be like modifications( bool show_changes_inline, show_only_modifications, int bmajor, bminor, string bsuffix ) Options: - show_changes_inline: -- true: show changes in form of underline / strikethrough -- false: just show the attribute values from the respective baseline - show_only_modifications: -- true: Only show modifications, hide creation and deletion of attributes -- false: Show modifications as well as creation and deletion of attributes - baseType -- "Major": Compare with last Major baseline (e.g. 1.0, 2.0, etc) -- "Minor": Compare with last Minor baseline (e.g. 2.1, 2.2, etc) -- "Any": Compare with most recent baseline (e.g. 1.2 test, 2.3 update, etc) Alternatively: - bmajor: Integer variable: Major number of baseline - bminor: Integer: Minor number of baseline - bsuffix: String: Suffix of baseline */ // ============================================================================ // Global variables // ============================================================================ // Object status // Old Module version New module version const string s_identifierObsoleteChanges = "- " string s = s_identifierObsoleteChanges const string c_objectStatusNotExisting = s "Object not existing in both versions" // Null Null const string c_objectStatusObsolete = s "Object created and deleted" // Null Deleted const string c_objectStatusCreated = "Object created" // Null Not deleted const string c_objectStatusPurged = s "Object purged" // Deleted Null const string c_objectStatusBothDeleted = s "Object Deleted in both versions" // Deleted Deleted const string c_objectStatusUndeleted = "Object undeleted" // Deleted Not deleted const string c_objectStatusDeletedPurged = "Object deleted and purged" // Not deleted Null const string c_objectStatusDeleted = "Object deleted" // Not deleted Deleted const string c_objectStatusNormal = "normal " // Not deleted Not deleted // Status of attribute w.r.t. to previous baseline const string c_attStatusNotChanged = "not changed" const string c_attStatusCreated = "created" const string c_attStatusModified = "modified" const string c_attStatusDeleted = "deleted" const string c_attStatusNone = "not existing in both baselines" //bool versionCompare__showDeletions = true bool versionCompare__show_attributeName = true bool versionCompare__use_view = true bool versionCompare__showAllHeadings = false bool versionCompare__showNewObjectsAsNewText = false bool versionCompare__showDeletedObjectsAsDeletedText = false bool versionCompare__hideNewDeletedObjects = false bool versionCompare__displayAllObjects = false Skip versionCompare__attribute_list Skip attList = null // ============================================================================ // Include files for finding an object regardless of display state // ============================================================================ Object fn_object(int absNum, Module mod) { // Replace the "object(int absNum, Module mod)" routine // which only returns objects when they are visible Object loopObj, returnObj = null if (!null mod) { // Module is not null returnObj= object(absNum, mod) if (null returnObj) { // Object not found directly // but the 'object' perm ignores filtered objects for loopObj in entire mod do { // Find object in module if (loopObj."Absolute Number" "" == absNum "") { // Object found returnObj = loopObj break } // Object found } // Find object in baseline }// Object not found directly } // Module is not null return returnObj } // Replace the "object(int absNum, Module mod)" routine // ============================================================================ // Include files for reading the current version of a module // ============================================================================ Module read_module(string modName, bool disp, &wasOpen) { // Return handle to module in read-only mode // Use "disp = true" to display Module Module returnValue = null wasOpen = false if (exists module modName) { if (open module modName && !disp) { // n.B.: (module modName) is of type ModName_, while // item modName is of type module wasOpen = true returnValue = module item modName } else {returnValue = read(modName, disp, true)} } return returnValue } // ============================================================================ // Include files for managing baselines // ============================================================================ // ---------------------------------------------------------------------------- void stringToBaseline(string s, int &iMajor, &iMinor, string &sSuffix) { // Transform a string à la "3.2" or "4.2 test" in the individual baseline specifications Regexp r_Baseline = regexp "([0-9]+).([0-9]+)" iMajor = -1 iMinor = -1 sSuffix = "" if (r_Baseline s) { // String matches specification template iMajor = intOf(s[match 1]) iMinor = intOf(s[match 2]) sSuffix = s[end 2 + 1:] if (length sSuffix > 0){while (sSuffix[0:0] == " "){sSuffix = sSuffix[1:length sSuffix - 1]}} } // String matches specification template } // Transform a string à la "3.2" or "4.2 test" in the individual baseline specifications // ---------------------------------------------------------------------------- bool baselineEqual(Baseline a, Baseline b) { // Check if baselines a and b are identical // For reasons I don't know, (a == b) does not give // the correct result. I therefore compare the major // and minor number and the suffix if (null a && null b){return false} if (null a || null b){return false} bool returnVal = ( major a == major b && minor a == minor b && suffix a == suffix b ) return returnVal } // ---------------------------------------------------------------------------- Baseline getPreviousBaseline(Module m, string baseType) { // Return the previous baseline compared to the current // module version // baseType = "Major" --> find last Major baseline // baseType = "Minor" --> find last Minor baseline // baseType = "Any" --> find the most recent baseline // // N.b.: Here, any baseline without a suffix is considered a minor // baseline. Therefore, is the existing baselines are e.g. // 0.1 // 0.1 mod // 0.2 // 1.0 // 1.0 mod // 1.1 // , the previous minor baseline for 1.1 would be 1.0 and not 0.2. // The main goal for using "Minor" is to surpress suffix baselines Baseline b, prevBase, prevMajor, prevMinor Baseline callBaseline = baseline moduleVersion m prevBase = null prevMajor = null prevMinor = null for b in m do { // Loop through the baselines until we reach the // baseline version of the calling Module. // Thus we don't have to worry if the calling // Module is the current Version (i.e. not baselined). // In that case prevBase will just be the most recent baseline. if (baselineEqual(b, callBaseline)){break} prevBase = b // Any baseline without a suffix is considered a minor baseline if (null suffix b){prevMinor = b} // Any baseline without a suffix and with the minor number zero is // considered a major baseline if (null suffix b && minor b == 0){prevMajor = b} } if (baseType == "Major"){return prevMajor} if (baseType == "Minor"){return prevMinor} if (baseType == "Any") {return prevBase} prevBase = null display "Typo" return prevBase } // ---------------------------------------------------------------------------- Baseline getPreviousBaseline(Module m) { // Overloaded routine: Return previous baseline, regardless of // major number, minor number or suffix return getPreviousBaseline(m, "Any") } // ---------------------------------------------------------------------------- Module read_baseline(string name, int major, minor, string suffix) { // Return handle to specified module baseline Module returnValue = null Module currMod = current if (exists module name) { // Module exists ModuleVersion mv = moduleVersion( module name, baseline(major, minor, suffix) ) if (!baselineExists mv){return null} returnValue = data mv if (null returnValue){returnValue = load(mv, false)} } // Module exists return returnValue } // ============================================================================ // Main include files // ============================================================================ // ---------------------------------------------------------------------------- Skip displayedAttList() { // Return a skip list with the displayed attributes in the order // of the displayed columns // For the main column, add Object Heading and Object Text // Ignore Object Identifier, as this attribute can't be changed // Also ignore attribute "Modifications" if it exists, as this is the // attribute DXL object for displaying this information // // Optionally, a Skip list of attributes to be compared can be provided by // defining and filling the Skip list 'attList' // prior to calling 'modifications()' Skip attSkip = create Column c Module m = current string s_attName int i = 0 bool useAttList = !null attList if (useAttList) { // Use a user-defined list of attributes for s_attName in attList do { // Loop through Skip list with attribute names put(attSkip, i++, s_attName) } // Loop through Skip list with attribute names return attSkip } // Use a user-defined list of attributes else { // Use the attributes currently displayed for c in m do { // Loop through columns if (main(c)) { // Main column put(attSkip, i++, "Object Heading") put(attSkip, i++, "Object Text") } // Main column else { // Any other column s_attName = attrName(c) if (!null s_attName) { // Valid attribute name, i.e. no layout DXL column if (s_attName == "Object Identifier"){continue} if (s_attName == "Modifications"){continue} put(attSkip, i++, s_attName) } // Valid attribute name } // Any other column } // Loop through columns return attSkip } // Use the attributes currently displayed } // Return a skip list with the displayed attributes // ---------------------------------------------------------------------------- bool compare_objects(Object o1, o2, string attr) { // Check whether two objects differ w.r.t to a given attribute // returnValue: true: no differences // false: differences bool returnValue = false string s1, s2 s1 = probeAttr_(o1,attr) s2 = probeAttr_(o2,attr) //if (!versionCompare__showDeletions && s2 == ""){returnValue = true} //else {returnValue = s1 == s2} returnValue = s1 == s2 //display attr ": " returnValue ": " s1 ": " s2 "" return returnValue } // ---------------------------------------------------------------------------- void displayAttributeModifications( // Display modifications of one attribute- Object o1, o2, string attr, string attrStatus, bool show_changes_inline, show_only_modifications ) { bool useHighlight = true Buffer disp Buffer oldValue Buffer newValue Buffer difference string Sdiff disp = create if (versionCompare__show_attributeName){disp = "{\\b " attr ": }"} else {disp = ""} if (show_changes_inline) { // The attribute was changed w.r.t. the other baseline // Display modifications with strikethroughs and underlines oldValue = create newValue = create difference = create if (!null o1) { if (!isDeleted o1){oldValue = probeAttr_(o1,attr)} else {oldValue = ""} } else {oldValue = ""} if (!null o2) { if (!isDeleted o2){newValue = probeAttr_(o2,attr)} else {newValue = ""} } else {oldValue = ""} if (useHighlight) { Sdiff = diff(difference, oldValue, newValue) } else {Sdiff = diff(difference, oldValue, newValue, "\\strike ", "\\ul ")} disp += tempStringOf difference disp += "\n" delete oldValue delete newValue delete difference displayRichWithColor tempStringOf disp } // The attribute was changed w.r.t. the other baseline else { // The attribute was changed w.r.t the previous baseline // but you chose to only display the previous attribute value if (probeAttr_(o1,attr) != "") { disp += richTextWithOle o1.attr displayRichWithColor tempStringOf disp } } // Display the modifications and delete buffer delete disp } // ============================================================================ // Main routine // ============================================================================ // ---------------------------------------------------------------------------- // General routine for module comparison / layout DXL: // Both module handles provided as variables // Overloaded routines including reading the appropriate baseline // provided below void modifications( bool show_changes_inline, show_only_modifications, Module oldModule, newModule ) { Skip displayedAttListSkip string objStatus bool compareObjects string attName, attrStatus AttrDef oldModuleAttrDef, newModuleAttrDef int absno = obj."Absolute Number" Object oldObject Object newObject string oldModuleVersion string newModuleVersion bool effectivelyEqual // Get the list of attributes currently displayed if (versionCompare__showAllHeadings) { // Show the Object Headings in any case if (length obj."Object Heading" "" > 0) { // Object has a Heading displayRichWithColor "{\\b " (number obj) " " obj."Object Heading" "}" } // Object has a Heading } // Show the Object Headings in any case if (versionCompare__use_view){displayedAttListSkip = displayedAttList()} else {displayedAttListSkip = versionCompare__attribute_list} oldObject = fn_object(absno, oldModule) newObject = fn_object(absno, newModule) oldModuleVersion = "baseline " version(oldModule) newModuleVersion = "baseline " version(newModule) if (!isBaseline oldModule) {oldModuleVersion = "current version"} if (!isBaseline newModule) {newModuleVersion = "current version"} // Get Object status if (null oldObject) { // Old object is null if (null newObject) { // New object is null objStatus = c_objectStatusNotExisting } // New object is null else { // New object is not null objStatus = isDeleted(newObject) ? c_objectStatusObsolete : c_objectStatusCreated } // New object is not null } // Old object is null else { // Old object is not null if (null newObject) { // New object is null objStatus = isDeleted(oldObject) ? c_objectStatusPurged : c_objectStatusDeletedPurged } // New object is null else { // New object is not null if (isDeleted oldObject) { // Old object is deleted objStatus = isDeleted(newObject) ? c_objectStatusBothDeleted : c_objectStatusUndeleted } // Old object is deleted else { // Old object is not deleted objStatus = isDeleted(newObject) ? c_objectStatusDeleted : c_objectStatusNormal } // Old object is not deleted } // New object is not null } // Old object is not null // Check whether the objects' attributes are to be compared compareObjects = false if (objStatus == c_objectStatusNormal){compareObjects = true} else if (objStatus == c_objectStatusDeleted) { // Not deleted --> Deleted if (versionCompare__showDeletedObjectsAsDeletedText){compareObjects = true} else {display c_objectStatusDeleted " in " newModuleVersion ""} } // Not deleted --> Deleted else if (objStatus == c_objectStatusDeletedPurged) { // Not deleted --> Purged if (versionCompare__showDeletedObjectsAsDeletedText){compareObjects = true} else {display c_objectStatusDeletedPurged " in " newModuleVersion ""} } // Not deleted --> Purged else if (objStatus == c_objectStatusUndeleted) { // Deleted --> Not deleted if (versionCompare__showNewObjectsAsNewText){compareObjects = true} else {display c_objectStatusUndeleted " after " oldModuleVersion ""} } // Deleted --> Not deleted else if (objStatus == c_objectStatusBothDeleted){display c_objectStatusBothDeleted} else if (objStatus == c_objectStatusPurged) {display c_objectStatusPurged " in " newModuleVersion ""} else if (objStatus == c_objectStatusCreated) { // Null --> Not deleted if (versionCompare__showNewObjectsAsNewText){compareObjects = true} else {display c_objectStatusCreated " after " oldModuleVersion ""} } // Null --> Not deleted else if (objStatus == c_objectStatusObsolete) {if (!versionCompare__hideNewDeletedObjects){display c_objectStatusObsolete " after " oldModuleVersion ""}} else if (objStatus == c_objectStatusNotExisting){if (!versionCompare__hideNewDeletedObjects){display c_objectStatusNotExisting}} if (compareObjects) { // Compare objects' attributes for attName in displayedAttListSkip do { // Loop through attributes if (attName == "Object Level"){continue} oldModuleAttrDef = find(oldModule, attName) newModuleAttrDef = find(newModule, attName) effectivelyEqual = compare_objects(oldObject, newObject, attName) if (null oldModuleAttrDef){attrStatus = null newModuleAttrDef ? c_attStatusNone : c_attStatusCreated} else {attrStatus = null newModuleAttrDef ? c_attStatusDeleted : (effectivelyEqual ? c_attStatusNotChanged : c_attStatusModified)} if (!show_only_modifications && (attrStatus == c_attStatusCreated || attrStatus == c_attStatusDeleted || attrStatus == c_attStatusNone) && !effectivelyEqual){display "Attribute " attName " " attrStatus} if (!effectivelyEqual || versionCompare__displayAllObjects) { displayAttributeModifications( oldObject, newObject, attName, attrStatus, show_changes_inline, show_only_modifications ) } } // Loop through attributes } // Compare objects' attributes delete displayedAttListSkip } // ============================================================================ // Overloaded routine calls // ============================================================================ // ---------------------------------------------------------------------------- // Overloaded routine call: Call with two baseline specifications void modifications( bool show_changes_inline, show_only_modifications, int bmajor1, bminor1, string bsuffix1, int bmajor2, bminor2, string bsuffix2 ) { Module currentMod = current Module oldModule = read_baseline( fullName currentMod, bmajor1, bminor1, bsuffix1) Module newModule = read_baseline( fullName currentMod, bmajor2, bminor2, bsuffix2) string msg = null if (null oldModule || null newModule) {msg = "Failed to load baseline(s) "} if (null oldModule) { msg = msg bmajor1 "." bminor1 "" if (!null bsuffix1){msg = msg " (" bsuffix1 ")"} msg = msg " " } if (null newModule) { msg = msg bmajor2 "." bminor2 "" if (!null bsuffix2){msg = msg " (" bsuffix2 ")"} } if (!null msg){display msg} else { modifications( show_changes_inline, show_only_modifications, oldModule, newModule) } } // ---------------------------------------------------------------------------- // Overloaded routine call: When called with one baseline // sepcification, use the current Module as new Module void modifications( bool show_changes_inline, show_only_modifications, int bmajor1, bminor1, string bsuffix1 ) { Module currentMod = current bool b = true if (isBaseline currentMod){currentMod = read_module(fullName currentMod, false, b)} //if (isBaseline currentMod){currentMod = read(fullName currentMod, false)} Module oldModule = read_baseline( fullName currentMod, bmajor1, bminor1, bsuffix1) string msg = null if (null oldModule) { msg = "Failed to load baseline(s) " msg = msg bmajor1 "." bminor1 "" if (!null bsuffix1){msg = msg " (" bsuffix1 ")"} display msg } else { modifications( show_changes_inline, show_only_modifications, oldModule, currentMod) } } // ---------------------------------------------------------------------------- // Overloaded routine call: Automatically choose last // major, last minor or last repsective baseline // based on "baseType" ["Major" | "Minor" | "Any"] // Always compare to current Module void modifications( bool show_changes_inline, show_only_modifications, string baseType) { Baseline b = getPreviousBaseline(current Module, baseType) if (!null b) { modifications( show_changes_inline, show_only_modifications, major b, minor b, suffix b ) } else {display "No baseline found"} } // ---------------------------------------------------------------------------- // Default when called with no options: // Only modifications, last Baseline void modifications(){modifications(true, true, "Any")} // ---------------------------------------------------------------------------- // Don't use the current view; provide attributes for comparison instead // ---------------------------------------------------------------------------- void modifications__object_text() { // Only display modifications for Object Text versionCompare__use_view = false versionCompare__attribute_list = create() put(versionCompare__attribute_list, 0, "Object Text") //put(versionCompare__attribute_list, 0, "Comments") modifications() //delete versionCompare__attribute_list } // Only display modifications for Object Text // ---------------------------------------------------------------------------- void modifications__compareBaselineWithCurrent() { // Only display modifications for Object Text versionCompare__use_view = false versionCompare__attribute_list = create() put(versionCompare__attribute_list, 0, "Object Text") put(versionCompare__attribute_list, 1, "Last Modified Baseline") Module thisMod = current Module string thisModName = fullName thisMod bool wasOpen = false Module currModVersion = read_module(thisModName, false, wasOpen) modifications(true, true, thisMod, currModVersion) //delete versionCompare__attribute_list } // Only display modifications for Object Text // ---------------------------------------------------------------------------- ------------------