History over several baselines

does someone have a DXL code fragement/idea on how to create for a dedicated attribute a change history which goes over several baselines?

thank you,
donat
hutterd - Mon Jun 21 03:02:52 EDT 2010

Re: History over several baselines
Peter_Albert - Mon Jun 21 03:35:10 EDT 2010

Tony Goodman's Smart History Viewer might be a good start for you: http://www.smartdxl.com/content/?page_id=125

Peter

Re: History over several baselines
lhall122 - Wed Jun 23 10:14:08 EDT 2010

We put this DXL under the User menu. You have to place in \lib\dxl\addins\user. If you click on an object, you can go to your DOORS User menu and select (whatever you named this DXL) and it will show you the history through all baselines for that object. Hope this helps.
// Show all history records for an object (including baselines)

/*
Copyright (c) 2004-2005 Galactic Solutions Group, LLC

Shows all history records for the current object,
including history records in baselined versions of the module
*/

const string HB_ABOUT = "
Copyright (c) 2004-2005 Galactic Solutions Group, LLC
http://galactic-solutions.com
Author: michael.sutherland@galactic-solutions.com

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or contact http://www.gnu.org

If you find defects with or improve upon this library, please contact
support@galactic-solutions.com
"

/*
1.1.2 05 December 2005 Michael Sutherland - Galactic Solutions Group, LLC
- Fixed error where objects that were soft-deleted in a previous baseline,
and still exist in a current version of module, do not show a deletion record
- Updated HB_populateHistoryListBox() with call to showDeletedObjects( true )

1.1.1 29 November 2004 Michael Sutherland - Galactic Solutions Group, LLC
- Declared variable HB_aboutTextDBE
- Added HB_DB_OFFSET, updated value for HB_DB_HEIGHT

1.1 17 November 2004 Michael Sutherland - Galactic Solutions Group, LLC
- Added "View changes as redlining"
- Added HB_viewChangesAsRedliningDBE
- Added HB_stripRichText()
- Modified HB_onListViewSelect()
- Updated to fix exception error when opening multiple baselines (DOORS bug)
- Updated to standards:
- Added "General" and "About" Tab
- Added constants, globals variables, and functions HB_*
- Added Module close trigger

1.0 18 October 2004 Michael Sutherland - Galactic Solutions Group, LLC
- Initial Release for 2004 Telelogic UGC - "Script Exchange and Competition for DOORS"
Note: Script was deemed "most useful" by the attendees of the 2004 Telelogic UGC.

*/

pragma runLim,0

const string HB_MAIN_TITLE = "History including Baselines"
const string HB_VERSION = "1.1.2"
const string HB_TITLE = HB_MAIN_TITLE " (v" HB_VERSION ") "

const string HB_TAB_LABELS[] = { "General", "About" }
const int HB_GENERAL_TAB = 0
const int HB_ABOUT_TAB = 1

const int HB_TAB_WIDTH = 800
const int HB_TAB_HEIGHT = 525

const int HB_DB_OFFSET = 60
const int HB_DB_WIDTH = HB_TAB_WIDTH
const int HB_DB_HEIGHT = HB_TAB_HEIGHT + HB_DB_OFFSET

const int HB_COLUMN_USER = 0
const int HB_COLUMN_SESSION = 1
const int HB_COLUMN_DATE = 2
const int HB_COLUMN_MODIFICATION = 3
const int HB_COLUMN_BASELINE = 4

const int HB_COLUMN_USER_WIDTH = 100
const int HB_COLUMN_SESSION_WIDTH = 50
const int HB_COLUMN_DATE_WIDTH = 120
const int HB_COLUMN_MODIFICATION_WIDTH = 260
const int HB_COLUMN_BASELINE_WIDTH = 180

const string HB_COLUMN_USER_LABEL = "User"
const string HB_COLUMN_SESSION_LABEL = "Session"
const string HB_COLUMN_DATE_LABEL = "Date"
const string HB_COLUMN_MODIFICATION_LABEL = "Modification"
const string HB_COLUMN_BASELINE_LABEL = "Baseline"

const int HB_historyListViewDBE_options = 0
const int HB_historyListViewDBE_width = 0
const int HB_historyListViewDBE_lines = 10

const int HB_oldAttrValueDBE_width = 500
const int HB_oldAttrValueDBE_height = 100
const int HB_newAttrValueDBE_width = 500
const int HB_newAttrValueDBE_height = 100

const string HB_oldAttrValueDBE_label = "From:"
const string HB_newAttrValueDBE_label = "To:"

const string HB_warnNullModule = "Please run in an open Module"
const string HB_warnNullObject = "No Object is selected."
const string HB_warnBaseline = "Please run from the current version of the Module"

const string HB_viewChangesAsRedliningDBE_label = "View changes as redlining"

DB HB_DB = null
DBE HB_TabDBE = null

DBE HB_historyListViewDBE = null
DBE HB_oldAttrValueDBE = null
DBE HB_newAttrValueDBE = null
DBE HB_viewChangesAsRedliningDBE = null
DBE HB_aboutTextDBE = null

Skip HB_TabSkip = null
Skip HB_GeneralTabSkip = null
Skip HB_AboutTabSkip = null

Skip HB_oldAttrValues = null
Skip HB_newAttrValues = null

Trigger HB_Trigger

Buffer HB_stripRichText( string rts ) {
Buffer plainText = create
RichText rt
for rt in rts do {
plainText += rt.text
if ( rt.newline ) plainText += "\n"
}
return plainText
}

void HB_onListViewSelect( DBE x, int i ) {

string newAttrStrValue = ""
if ( find( HB_newAttrValues, i, newAttrStrValue ) ) {
set( HB_newAttrValueDBE, newAttrStrValue )
}
else {
set( HB_newAttrValueDBE, " " )
}

string oldAttrStrValue = ""
if ( find( HB_oldAttrValues, i, oldAttrStrValue ) ) {

if ( get( HB_viewChangesAsRedliningDBE ) ) {
useRTFColour( HB_oldAttrValueDBE, true )

Buffer newAttrBufferValue = create
newAttrBufferValue += HB_stripRichText( newAttrStrValue )

Buffer oldAttrBufferValue = create
oldAttrBufferValue += HB_stripRichText( oldAttrStrValue )

Buffer diffResult = create

diff( diffResult, oldAttrBufferValue, newAttrBufferValue, "\\cf1\\strike ", "\\cf3\\ul " )

set( HB_oldAttrValueDBE, stringOf( diffResult ) )

delete newAttrBufferValue
delete oldAttrBufferValue
delete diffResult
}
else {
useRTFColour( HB_oldAttrValueDBE, false )

set( HB_oldAttrValueDBE, oldAttrStrValue )
}
}
else {
set( HB_oldAttrValueDBE, " " )
}
}

void HB_onListViewDeselect( DBE x, int i ) {}
void HB_onListViewActivate( DBE x, int i ) {}

void HB_populateHistoryListBox( DBE HB_historyListViewDBE, Module m, Object o, Baseline b, int &count ) {

// For baseline Modules, retrieve Object handle by Absolute Number
if ( !null b ) {
( current ModuleRef__ ) = m
showDeletedObjects( true )
o = object( intOf( o."Absolute Number" "" ) )
}
if ( !null o ) {
History h
for h in o do {
insert( HB_historyListViewDBE, -count, h.author "", iconNone )

set( HB_historyListViewDBE, -count, HB_COLUMN_SESSION, h.sessionNo "" )
set( HB_historyListViewDBE, -count, HB_COLUMN_DATE, h.date "" )

string modification = h.type ""
if ( modification == "modifyObject" ) {
modification = modification " attribute '" h.attrName "'"
put( HB_oldAttrValues, -count, removeUnlistedRichText( h.oldValue ) )
put( HB_newAttrValues, -count, removeUnlistedRichText( h.newValue ) )
}
set( HB_historyListViewDBE, -count, HB_COLUMN_MODIFICATION, modification )

string versionInfo = ""
if ( !null b ) {
versionInfo = "baseline " versionString( moduleVersion( m ) ) " - " ( dateOf b ) ""
}
else {
versionInfo = "current " version( m ) ""
}
set( HB_historyListViewDBE, -count, HB_COLUMN_BASELINE, versionInfo )

count--
}
}
}

void HB_onViewChangesAsRedliningToggle( DBE x ) {
HB_onListViewSelect( x, get( HB_historyListViewDBE ) )
}

void HB_TabSelectFn( DBE theTab ) {
int selection = get theTab
showSelectedTab( HB_TabSkip, selection )
}

void HB_doGeneralTab( DB HB_DB,
DBE HB_TabDBE,
Skip HB_GeneralTabSkip
)
{
string dummyList[] = {}
HB_historyListViewDBE = listView( HB_DB,
HB_historyListViewDBE_options,
HB_historyListViewDBE_width,
HB_historyListViewDBE_lines,
dummyList
)
set( HB_historyListViewDBE, HB_onListViewSelect, HB_onListViewDeselect, HB_onListViewActivate )

HB_oldAttrValueDBE = richText( HB_DB, HB_oldAttrValueDBE_label, "", HB_oldAttrValueDBE_width, HB_oldAttrValueDBE_height, true )
HB_newAttrValueDBE = richText( HB_DB, HB_newAttrValueDBE_label, "", HB_newAttrValueDBE_width, HB_newAttrValueDBE_height, true )

HB_viewChangesAsRedliningDBE = toggle( HB_DB, HB_viewChangesAsRedliningDBE_label, false )
set( HB_viewChangesAsRedliningDBE, HB_onViewChangesAsRedliningToggle )

HB_historyListViewDBE->"top"->"inside"->HB_TabDBE
HB_historyListViewDBE->"left"->"inside"->HB_TabDBE

int index = 0
put( HB_GeneralTabSkip, index++, HB_historyListViewDBE )
put( HB_GeneralTabSkip, index++, HB_oldAttrValueDBE )
put( HB_GeneralTabSkip, index++, HB_newAttrValueDBE )
put( HB_GeneralTabSkip, index++, HB_viewChangesAsRedliningDBE )
}

void HB_doAboutTab( DB HB_DB,
DBE HB_TabDBE,
Skip HB_AboutTabSkip
)
{
HB_aboutTextDBE = richText( HB_DB, HB_TITLE, HB_ABOUT, 1, 1, true )

HB_aboutTextDBE->"top"->"inside"->HB_TabDBE
HB_aboutTextDBE->"left"->"inside"->HB_TabDBE
HB_aboutTextDBE->"right"->"inside"->HB_TabDBE

int index = 0
put( HB_AboutTabSkip, index++, HB_aboutTextDBE )
}

bool HB_closeModuleTrigger( Trigger t ) {
hide HB_DB
return true
}

void HB_closeModule( DB x ) {
delete HB_Trigger
hide HB_DB
}

void HB_createBox( Module m, Object o ) {

HB_DB = create( "Object '" identifier( o ) "' - " HB_TITLE, styleFixed )

HB_TabSkip = create

HB_TabDBE = tab( HB_DB, HB_TAB_LABELS, HB_TAB_WIDTH, HB_TAB_HEIGHT, HB_TabSelectFn )

HB_GeneralTabSkip = create
HB_doGeneralTab( HB_DB, HB_TabDBE, HB_GeneralTabSkip )
put( HB_TabSkip, HB_GENERAL_TAB, HB_GeneralTabSkip )

HB_AboutTabSkip = create
HB_doAboutTab( HB_DB, HB_TabDBE, HB_AboutTabSkip )
put( HB_TabSkip, HB_ABOUT_TAB, HB_AboutTabSkip )

close( HB_DB, true, HB_closeModule )

HB_Trigger = trigger( module->( m."Name" "" ), close, 10, HB_closeModuleTrigger )

realize HB_DB

showSelectedTab( HB_TabSkip, HB_GENERAL_TAB )

setSize( HB_DB, HB_DB_WIDTH, HB_DB_HEIGHT )

insertColumn( HB_historyListViewDBE, HB_COLUMN_USER, HB_COLUMN_USER_LABEL, HB_COLUMN_USER_WIDTH, iconNone )
insertColumn( HB_historyListViewDBE, HB_COLUMN_SESSION, HB_COLUMN_SESSION_LABEL, HB_COLUMN_SESSION_WIDTH, iconNone )
insertColumn( HB_historyListViewDBE, HB_COLUMN_DATE, HB_COLUMN_DATE_LABEL, HB_COLUMN_DATE_WIDTH, iconNone )
insertColumn( HB_historyListViewDBE, HB_COLUMN_MODIFICATION, HB_COLUMN_MODIFICATION_LABEL, HB_COLUMN_MODIFICATION_WIDTH, iconNone )
insertColumn( HB_historyListViewDBE, HB_COLUMN_BASELINE, HB_COLUMN_BASELINE_LABEL, HB_COLUMN_BASELINE_WIDTH, iconNone )
}

void HP_populateBox( Module m, Object o ) {

// Looping through and loading baselines in the same loop sometimes causes an exception error
// in DOORS 7.0 SP1 and DOORS 7.1, so buffer the baselines in a Skip list
Skip baselines = create
int baselineCount = 0
Baseline b
for b in m do {
if ( !null b ) {
baselineCount++
put( baselines, baselineCount, b )
}
}

HB_oldAttrValues = create
HB_newAttrValues = create

// Populate History records for Baselines
int historyRecordCount = 0
Module baselineModule
for b in baselines do {
baselineModule = load( b, false )
if ( !null baselineModule ) {
HB_populateHistoryListBox( HB_historyListViewDBE, baselineModule, o, b, historyRecordCount )
}
}
delete baselines

// Populate History records for current Version of Module
( current ModuleRef__ ) = m
HB_populateHistoryListBox( HB_historyListViewDBE, m, o, null, historyRecordCount )
}

if ( !null current Module ) {
if ( !null current Object ) {
if ( !isBaseline( current Module ) ) {

HB_createBox( current Module, current Object )
HP_populateBox( current Module, current Object )
show HB_DB
}
else {
warningBox( HB_warnBaseline )
}
}
else {
warningBox( HB_warnNullObject )
}
}
else {
warningBox( HB_warnNullModule )
}

Re: History over several baselines
hutterd - Thu Jul 29 15:26:34 EDT 2010

thanks for the answers - we made this also available as shared utility.

It is for sure a good starting point for extending with the option to create a change history report just for a dedicated attribute (instead of all changes of an object).

donat

Re: History over several baselines
GaborMoizes - Mon Aug 02 05:21:52 EDT 2010

hutterd - Thu Jul 29 15:26:34 EDT 2010
thanks for the answers - we made this also available as shared utility.

It is for sure a good starting point for extending with the option to create a change history report just for a dedicated attribute (instead of all changes of an object).

donat

I have a problem with this script. For an object, which has around 50 baselines and has an embedded OLE object, this script stops with Out of memory error.
Do you know a workaround for it?

Re: History over several baselines
Mathias Mamsch - Mon Aug 02 07:09:44 EDT 2010

GaborMoizes - Mon Aug 02 05:21:52 EDT 2010
I have a problem with this script. For an object, which has around 50 baselines and has an embedded OLE object, this script stops with Out of memory error.
Do you know a workaround for it?

It is a general flaw of this script, that it will iterate over ALL baselines. When you have too many baselines it will take forever or fail with memory errors.

What I would suggest is, to introduce a field which contains a minimum date before which the script will not open any baselines.

Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: History over several baselines
Pierre Pornin - Mon Apr 11 10:35:47 EDT 2011

Mathias Mamsch - Mon Aug 02 07:09:44 EDT 2010
It is a general flaw of this script, that it will iterate over ALL baselines. When you have too many baselines it will take forever or fail with memory errors.

What I would suggest is, to introduce a field which contains a minimum date before which the script will not open any baselines.

Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

I made some enhancements to Smart History: user can choose start and end dates for limiting the number of baselines that are loaded. This turns out to be quite faster if you know wish period of time you want to look at and you have many baselines.
I also corrected a bug that says "smartHistoryDialog.inc:576> "<Read Locked Data>" is not an int". This occurred in Doors 9.2
By the way, Smart History cannot be ran from a baseline, it has to be ran from the current version otherwise DXL error occurs and Doors could crash.
Full code attached here.
Attachments

attachment_14605001_smartHistory.zip