Export Changes

This script exports changes between two baselines as red-lined markup in an HTML table. Object Heading and Text are included in the output, with changes highlighted in the newer baseline. You can select the attribute used to identify the objects and an additional attribute can be included in the output.

 

//

/*

*/

pragma runLim, 0

//<  Export Change Report to HTML

/*
	18-MAR-2011		Tony Goodman
*/

Buffer textBuf2 = create
Buffer tempBuf = create

/***********************************
	getAttr
***********************************/
string getAttr(Object o, string attr)
{
	string s = ""

	if (attr == "Identifier")
	{
		return(identifier(o))
	}

	if (attr == "Level")
	{
		return(level(o) "")
	}

	if (attr == "Number")
	{
		return(number(o) "")
	}

	s = probeAttr_(o, attr)

	if (s "" == "")
	{
		return("<br>")
	}
	else
	{
		return(s)
	}
}

/***********************************
	emitHeader
***********************************/
void emitHeader(Stream out)
{
	out << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
	out << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
	out << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
	out << "<head>\n"

	out << "<style>\n"

	out << ".myCell {\n"
	out << "margin: 0px;\n"
	out << "padding: 5px;\n"
	out << "vertical-align: top;\n"
	out << "font: 11px Arial, sans-serif;\n"
	out << "border: 1px solid #CCCCCC;\n"
	out << "}\n"

	out << ".myTable {\n"
	out << "margin: 0px;\n"
	out << "padding: 0px;\n"
	out << "vertical-align: top;\n"
	out << "}\n"

	out << ".myAnchor {\n"
	out << "text-decoration: none;\n"
	out << "font: 11px Arial, sans-serif;\n"
	out << "color: #000000;\n"
	out << "}\n"

	out << ".myAnchorBold {\n"
	out << "text-decoration: none;\n"
	out << "font: bold 11px Arial, sans-serif, bold;\n"
	out << "color: #000000;\n"
	out << "}\n"

	out << "</style>\n"
	out << "</head>\n"
	out << "<body>\n"
}

/***********************************
	emitFooter
***********************************/
void emitFooter(Stream out)
{
	out << "</body>\n"
	out << "</html>\n"
	out << "\n"
}

/***********************************
	convertRichText
***********************************/
void convertRichText(Buffer& b, string s)
{
	RichTextParagraph rp = null
    RichText rt = null
    bool limitText = false
	int ind = 0
	int i = 0

    setempty(b)

	for rp in s do
	{
		ind = rp.indentLevel

		for (i = 0; i < ind; i += 360) b += "<ul>"

		if (rp.isBullet) b += "<li>"

		for rt in rp do
		{
			setempty(textBuf2)
			textBuf2 += rt.text

			safeHTMLBuffer(textBuf2, true, true)

			if (rt.bold) b += "<b>"

			if (rt.underline)
			{
				b += "<span style='color:blue'>"
				b += "<u>"
			}

			if (rt.italic) b += "<i>"

			if (rt.strikethru)
			{
				b += "<span style='color:red'>"
				b += "<s>"
			}

			if (rt.superscript) b += "<sup>"
			if (rt.subscript) b += "<sub>"
			if (rt.charset == charsetSymbol) b += "<font face=\"Symbol\">"

			b += textBuf2

			if (rt.charset == charsetSymbol) b += "</font>"
			if (rt.subscript) b += "</sub>"
			if (rt.superscript) b += "</sup>"
			if (rt.strikethru)
			{
				b += "</s>"
				b += "</span>"
			}

			if (rt.italic) b += "</i>"
			if (rt.underline)
			{
				b += "</u>"
				b += "</span>"
			}

			if (rt.bold) b += "</b>"

			if (rt.newline) b += "<br>"
		}

		if (rp.isBullet) b += "</li>"

		for (i = 0; i < ind; i += 360) b += "</ul>"
	}
}

/***********************************
	emitFileHeader
***********************************/
void emitFileHeader(Stream out, string moduleName, Skip selectedAttributes)
{
	string attr = ""
	bool doneOne = false

	out << "<table class=\"myTable\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n"

	// header row
	out << "<tr>\n"
	out << "<td class=\"myCell\">\n"

	out << "<b>Module:</b> " moduleName "<br>"
	out << "<b>Exported from DOORS on:</b> " stringOf(today) "<br>"

	out << "<b>Showing history of values for attributes:</b> " 

	for attr in selectedAttributes do
	{
		if (doneOne)
		{
			out << ", "
		}

		out << attr ""

		doneOne = true
	}

	out << "</td>\n"
	out << "</tr>\n"

	out << "</table>\n"
}

/***********************************
	emitTableHeader
***********************************/
void emitTableHeader(Stream out, Skip selectedBaselines, string selectedIdentifier, Skip selectedAttributes)
{
	Baseline b = null
	string attr = ""

	out << "<tr>\n"

	out << "<th class=\"myCell\"><b><br></b></th>\n"

	for b in selectedBaselines do
	{
		out << "<th class=\"myCell\" colspan=\"2\"><b>" "Baseline " (major b) "." (minor b) (suffix b "" != "" ? " (" (suffix b) ")" : "") "</b></th>\n"
	}

	out << "<th class=\"myCell\" colspan=\"2\"><b>" "Current version"  "</b></th>\n"

	out << "</tr>\n"

	out << "<tr>\n"

	out << "<th class=\"myCell\"><b>" selectedIdentifier "</b></th>\n"

	for b in selectedBaselines do
	{
		for attr in selectedAttributes do
		{
			if (length(attr) > 8 && attr[0:7] == "DXL for ")
			{
				out << "<th class=\"myCell\"><b>" attr[8:] "</b></th>\n"
			}
			else
			{
				out << "<th class=\"myCell\"><b>" attr "</b></th>\n"
			}
		}
	}

	for attr in selectedAttributes do
	{
		if (length(attr) > 8 && attr[0:7] == "DXL for ")
		{
			out << "<th class=\"myCell\"><b>" attr[8:] "</b></th>\n"
		}
		else
		{
			out << "<th class=\"myCell\"><b>" attr "</b></th>\n"
		}
	}

	out << "</tr>\n"
}

/***********************************
	exportChangeHistory
***********************************/
string exportChangeHistory(Module m, Skip selectedBaselines, string selectedIdentifier, Skip selectedAttributes, string outputFile)
{
	string res = ""
	Module bm = null
	Baseline b = null
	Object o = null
	Object bo = null
	int absno = 0
	string s = ""
	string attr = ""
	AttrDef ad = null
	Skip baselineModules = create

	out = write(outputFile)

	if (null out)
	{
		return("failed to open file for writing: " outputFile "")
	}

	for b in selectedBaselines do
	{
		bm = load(m, b, false)

		put(baselineModules, (int key selectedBaselines), bm)
	}

	emitHeader(out)

	emitFileHeader(out, fullName(m), selectedAttributes)

	out << "<table class=\"myTable\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n"

	emitTableHeader(out, selectedBaselines, selectedIdentifier, selectedAttributes)

	for o in document m do
	{
		//if (isDeleted(o2)) continue
		if (table(o)) continue

			out << "<tr>\n"

			out << "<td class=\"myCell\">" getAttr(o, selectedIdentifier) "</td>\n"

			absno = o."Absolute Number"

			for bm in baselineModules do
			{
				for attr in selectedAttributes do
				{
					out << "<td class=\"myCell\">"

					bo = object(absno, bm)

					if (null bo)
					{
						out << "<br>"
					}
					else
					{
						out <<"<a class=\"myText\"> " 

						if (probeAttr_(bo, attr) == "")
						{
							out << "<br>"
						}
						else
						{
							convertRichText(tempBuf, probeRichAttr_(bo, attr))
							out << tempBuf
						}

						out << "</a>\n"
					}

					out << "</td>\n"
				}
			}

			for attr in selectedAttributes do
			{
				out << "<td class=\"myCell\">"

				out <<"<a class=\"myText\"> " 

				if (probeAttr_(o, attr) == "")
				{
					out << "<br>"
				}
				else
				{
					convertRichText(tempBuf, probeRichAttr_(o, attr))
					out << tempBuf
				}

				out << "</a>\n"

				out << "</td>\n"
			}

			out << "</tr>\n"
	}

	out << "</table>\n"

	emitFooter(out)

	close(out)

	noError
	for bm in baselineModules do
	{
		close(bm)
	}
	lastError

	return("")
}

//<  Export Change History Dialog 

/*

	18-MAR-2011		Tony Goodman
*/

DB   dbMain   = null
DBE dbeLabel = null

DBE dbeFrame = null
DBE dbebaselinesFrame = null
DBE dbeBaselines = null

DBE dbeIdentifierFrame = null
DBE dbeAttributeFrame = null
DBE dbeIdentifier = null
DBE dbeAttributes = null

DBE dbeExportFrame = null
DBE dbeFileName  = null
DBE exportBtn    = null

string dummy[] = { }

Skip skipBaselines = create
Skip skipAttributes = createString

/***********************************
	getBaselines
***********************************/
void getBaselines(Module currMod)
{
	Baseline b = null
	int index = 0

	for b in currMod do
	{
		put(skipBaselines, index, b)

		insert(dbeBaselines, index, major(b) "." minor(b) " " suffix(b) " " annotation(b), iconNone)

		index++
	}

	put(skipBaselines, index, null)
	//insert(dbeBaselines, index, "Current", iconNone)

	if (index > 0)
	{
		set(dbeBaselines, index-1, true)
	}
	else
	{
		set(dbeBaselines, index, true)
	}
}

/***********************************
	getAttributes
***********************************/
void getAttributes(Module currMod)
{
	AttrDef ad = null
	string attr = ""
	int index = 0

	for ad in currMod do
	{
		if (!ad.object) continue

		put(skipAttributes, ad.name, ad.name)
	}

	insert(dbeIdentifier, 0, "Identifier", iconNone)

	index = 1

	for attr in skipAttributes do
	{
		insert(dbeIdentifier, index, attr, iconNone)
		insert(dbeAttributes, index, attr, iconNone)
		index++
	}

	set(dbeIdentifier, 0, true)
	set(dbeAttributes, 0, true)
}

/***********************************
	doExport
***********************************/
void doExport(DB db)
{
	Baseline b = null
	string selectedIdentifier = ""
	string selectedAttribute = null
	string outputFile = ""
	string res = ""
	string attr = ""
	int i = 0
	int j = 0
	Skip selectedBaselines = create
	Skip selectedAttributes = createString

	for (i = 0; i < noElems(dbeBaselines); i++)
	{
		if (getCheck(dbeBaselines, i))
		{
			find(skipBaselines, i, b)
			put(selectedBaselines, j++, b)
		}
	}

	selectedIdentifier = get(dbeIdentifier)

	for (i = 0; i < noElems(dbeAttributes); i++)
	{
		if (getCheck(dbeAttributes, i))
		{
			attr = getColumnValue(dbeAttributes, i, 0)
			put(selectedAttributes, attr, attr)
		}
	}
	//selectedAttribute = get(dbeAttributes)

	outputFile = get(dbeFileName)

	res = exportChangeHistory(current Module, selectedBaselines, selectedIdentifier, selectedAttributes, outputFile)

	if (res "" != "")
	{
		infoBox(res)
		return
	}
	else
	{
		infoBox("Export complete\nSee " outputFile)
	}

	release(dbMain)
}

/***********************************
	doClose
***********************************/
void doClose(DB db)
{
	release(dbMain)
}

/***********************************
	buildDialog
***********************************/
void buildDialog(Module currMod)
{
	dbMain = create(currMod, "Export Change History", styleCentered|styleFixed)

	dbeLabel = label(dbMain, "This utility exports change history for selected attributes to an HTML file.\n" //-
	                                   "The values of the selected attributes are shown in a separate columns for each baseline.")

	dbeFrame = frame(dbMain, "", 400, 450)
	dbeFrame->"top"->"flush"->dbeLabel
	dbeFrame->"left"->"form"
	dbeFrame->"right"->"form"
	dbeFrame->"bottom"->"form"

	dbeBaselinesFrame = frame(dbMain, "Baselines to include", 400, 100)
	dbeBaselinesFrame->"top"->"inside"->dbeFrame
	dbeBaselinesFrame->"left"->"inside"->dbeFrame
	dbeBaselinesFrame->"right"->"inside"->dbeFrame
	dbeBaselinesFrame->"bottom"->"unattached"

	dbeBaselines = listView(dbMain, listViewOptionCheckboxes | listViewOptionMultiselect, 390, 5, dummy)
	dbeBaselines->"top"->"inside"->dbeBaselinesFrame
	dbeBaselines->"left"->"inside"->dbeBaselinesFrame
	dbeBaselines->"right"->"inside"->dbeBaselinesFrame
	dbeBaselines->"bottom"->"inside"->dbeBaselinesFrame

	dbeIdentifierFrame = frame(dbMain, "Identifier for each object", 400, 100)
	dbeIdentifierFrame->"top"->"flush"->dbeBaselinesFrame
	dbeIdentifierFrame->"left"->"inside"->dbeFrame
	dbeIdentifierFrame->"right"->"inside"->dbeFrame
	dbeIdentifierFrame->"bottom"->"unattached"	

	dbeIdentifier = listView(dbMain, 0, 390, 5, dummy)
	dbeIdentifier->"top"->"inside"->dbeIdentifierFrame
	dbeIdentifier->"left"->"inside"->dbeIdentifierFrame
	dbeIdentifier->"right"->"inside"->dbeIdentifierFrame
	dbeIdentifier->"bottom"->"inside"->dbeIdentifierFrame

	dbeAttributeFrame = frame(dbMain, "Attributes to display", 400, 100)
	dbeAttributeFrame->"top"->"flush"->dbeIdentifierFrame
	dbeAttributeFrame->"left"->"inside"->dbeFrame
	dbeAttributeFrame->"right"->"inside"->dbeFrame
	dbeAttributeFrame->"bottom"->"unattached"

	dbeAttributes = listView(dbMain, listViewOptionCheckboxes | listViewOptionMultiselect, 390, 5, dummy)
	dbeAttributes->"top"->"inside"->dbeAttributeFrame
	dbeAttributes->"left"->"inside"->dbeAttributeFrame
	dbeAttributes->"right"->"inside"->dbeAttributeFrame
	dbeAttributes->"bottom"->"inside"->dbeAttributeFrame

	dbeFileName = fileName(dbMain, "Export to:", "U:\\" name(currMod) "_history.html", "*.html", "HTML Files", false)
	dbeFileName->"top"->"flush"->dbeAttributeFrame
	dbeFileName->"left"->"inside"->dbeFrame
	dbeFileName->"right"->"unattached"
	dbeFileName->"bottom"->"inside"->dbeFrame

	exportBtn = apply(dbMain, "Export", doExport)

	realize(dbMain)

	insertColumn(dbeBaselines, 0, "Baselines", 350, iconNone)

	insertColumn(dbeIdentifier, 0, "Identifier", 350, iconNone)
	insertColumn(dbeAttributes, 0, "Attributes", 350, iconNone)

	getBaselines(currMod)

	getAttributes(currMod)

	block(dbMain)
	destroy(dbMain)
	dbMain = null
}

/***********************************
	exportChangeHistory
***********************************/
void exportChangeHistory()
{
	Module currMod = null

	currMod = current Module

	if (null currMod)
	{
		infoBox("This utility can only be run from a formal module.")
		return
	}

	buildDialog(currMod)
}

exportChangeHistory()