How to copy one line from one attribute to another attribute in DOORs - ibm-doors

I'm trying to copy a line from DOORS one attribute and write that line into another attribute in DOORS.

more or less straight from the DXL manual
Object o = current // might be set in a loop
Regexp line = regexp2 ".*"
string sTextValue = o."Object Text"""
string sLastLine = ""
while (!null sTextValue && line sTextValue) {
sLastLine = sTextValue[match 0]
sTextValue = sTextValue [end 0 + 2:]
}
print "->" sLastLine "<-\n"
o."Other Attribute" = sLastLine

Related

DXL to truncate Object number

I inherited some DXL code to truncate the Object Number to exclude the last “0”
This works fine for paragraphs numbers less than 10 (or a double digit number). I’ll admit to be new to DXL, but this code stumps me as I am not familiar with RegExp. I know that those on this forum will look at this and get the answer and I will then learn and move forward.
Here is the code:
string s = number(obj)
Regexp paraNumExp = regexp2 "[0-9](\\.[0-9])*"
if(paraNumExp s) obj.attrDXLName = s[match 0]
delete paraNumExp
This is what is produces:
AbsNum, ObjNumber, DXL Attribute
Here is the DXL code for the attached file (output from the test module)
(DXL) Paragraph Number 1
string s = number(obj)
Regexp paraNumExp = regexp2 "[1-9](\\.[1-9])*"
if(paraNumExp s) obj.attrDXLName = s[match 0]
delete paraNumExp
(DXL) Paragraph Number 2
string s = number(obj)
Regexp paraNumExp = regexp2 "^[0-9]+\\.[0-9]+"
if(paraNumExp s) obj.attrDXLName = s[match 0]
delete paraNumExp
(DXL) Paragraph Number 4
Regexp reZero = regexp2 "(\\.0)-"
string s = number(obj)
if (reZero s) {
obj.attrDXLName = s[0:start 1-1]
}
delete reZero
DOORS output with what I want
Not super sure, what you are trying to accomplish, or what is the deeper problem here. But to answer your question for "truncating the pending zeros", I would suggest to use "start" and "end" methods here, e.g.:
Regexp reZero = regexp2 "(\\.0)-"
Module m = current
filtering off
Object o
for o in m do {
string strON = number( o )
string strTruncated = strON
if (reZero strON) {
strTruncated = strON[0:start 1-1] "" strON[end 1+1:]
}
print "" identifier( o ) ": " strON " => '" strTruncated "'\n"
}
With your help and a little bugging of a colleague, I got the results I need.
This is the DXL code:
// Define reZero to detect ".0-"
Regexp reZero = regexp2 "(\\.0)-"
// Get the Object Number
string s = number(obj)
if (reZero s) {
// Found ".0-"? Strip off ".0-" and all following that string
obj.attrDXLName = s[0:start 1-1]
} else {
// Did not find ".0-". Use complete object number.
obj.attrDXLName = s
}
delete reZero

String Newline not displaying in Doors

I have csv file containing some data like:
374,Test Comment multiplelines \n Here's the 2nd line,Other_Data
Where 374 is the object ID from doors, then some commentary and then some other data.
I have a piece of code that reads the data from the CSV file, stores it in the appropriate variables and then writes it to the doors Object.
Module Openend_module = edit("path_to_mod", true,true,true)
Object o ;
Column c;
string attrib;
string oneLine ;
string OBJECT_ID = "";
string Comment = "";
String Other_data = "";
int offset;
string split_text(string s)
{
if (findPlainText(s, sub, offset, len, false))
{
return s[0 : offset -1]
}
else
{
return ""
}
}
Stream input = read("Path_to_Input.txt");
input >> oneLine
OBJECT_ID = split_text(oneLine)
oneLine = oneLine[offset+1:]
Comment = split_text(oneLine)
Other_data = oneLine[offset+1:]
When using print Comment the output in the DXL console is : Test Comment multiplelines \n Here's the 2nd line
for o in Opened_Module do
{
if (o."Absolute Number"""==OBJECT_ID ){
attrib = "Result_Comment " 2
o.attrib = Comment
}
}
But after writing to the doors object, the \n is not taken into consideration and the result is as follows:
I've tried putting the string inside a Buffer and using stringOf() but the escape character just disappeared.
I've also tried adding \r\n and \\n to the input csv text but still no luck
This isn't the most efficient way of handling this, but I have a relatively straightforward fix.
I would suggest adding the following:
Module Openend_module = edit("path_to_mod", true,true,true)
Object o ;
Column c;
string attrib;
string oneLine ;
string OBJECT_ID = "";
string Comment = "";
String Other_data = "";
int offset;
string split_text(string s)
{
if (findPlainText(s, sub, offset, len, false))
{
return s[0 : offset -1]
}
else
{
return ""
}
}
Stream input = read("Path_to_Input.txt");
input >> oneLine
OBJECT_ID = split_text(oneLine)
oneLine = oneLine[offset+1:]
Comment = split_text(oneLine)
Other_data = oneLine[offset+1:]
//Modification to comment string
int x
int y
while ( findPlainText ( Comment , "\\n" , x , y , false ) ) {
Comment = ( Comment [ 0 : x - 1 ] ) "\n" ( Comment [ x + 2 : ] )
}
This will run the comment string through a parser, replacing string "\n" with the char '\n'. Be aware- this will ignore any trailing spaces at the end of a line.
Let me know if that helps.

Match Data In Two Files Then Email Each Person

For simplicity, file1.txt is a log file for which I extract logonIds into an array. File2.txt contains rows of logonID,emailAddress,other,needless,data
I need to take all of the logonIDs read into my array from file1 and extract their email addresses from file2. Once I have this information, I can then send each person in file1 an email. Can't just use file2.txt because it contains users who should not receive an email.
I wrote vbscript that extracts logonIDs from file1.txt into array and pulls logonID and email from file2.txt
inFile1 = "C:\Scripts\testvbs\wscreatestatus.txt"
inFile2 = "C:\Scripts\testvbs\WSBatchCreateBuildsList.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInFile1 = objFSO.OpenTextFile(inFile1, ForReading)
Set objInFile2 = objFSO.OpenTextFile(inFile2, ForReading)
'Creates Array of all DomainIDs for successful deployments
Do Until objInFile1.AtEndOfStream
strNextLine = objInFile1.Readline
arrLogons = Split(strNextLine , vbTab)
If arrLogons(0) = "DEPLOYSUCCESS" Then
arrUserIDList = arrUserIDList & arrLogons(5) & vbCrLf
End If
Loop
Do Until objInFile2.AtEndOfStream
strNextLine = objInFile2.Readline
arrAddressList = Split(strNextLine , ",")
arrMailList = arrMailList & arrAddressList(0) & vbTab & arrAddressList(1) & vbCrLf
Loop
What I need to do next is take my list of user IDs "arrUserIDList", and extract their email address from arrMailList. With this information I can send each user in file1.txt (wscreatestatus.txt) an email.
Thanks!
From the way you construct your arrMailList, I presume you want the selected LogonID's and corresponding email addresses output to a new Tab delimited text file.
If that is the case, I recommend using ArrayList objects to store the values in. ArrayLists have an easy to use Add method and for testing if an item is in an ArrayList, there is the Contains method.
In Code:
Option Explicit
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim inFile1, inFile2, outFile, objFSO, objInFile, objOutFile
Dim strNextLine, fields, arrUserIDList, arrMailList
inFile1 = "C:\Scripts\testvbs\wscreatestatus.txt"
inFile2 = "C:\Scripts\testvbs\WSBatchCreateBuildsList.txt"
outFile = "C:\Scripts\testvbs\WSEmailDeploySuccess.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInFile = objFSO.OpenTextFile(inFile1, ForReading)
'Create an ArrayList of all DomainIDs for successful deployments
Set arrUserIDList = CreateObject( "System.Collections.ArrayList" )
Do Until objInFile.AtEndOfStream
strNextLine = objInFile.Readline
fields = Split(strNextLine , vbTab)
If fields(0) = "DEPLOYSUCCESS" Then
arrUserIDList.Add fields(5)
End If
Loop
'close the first input file
objInFile.Close
'Now read the second file and read the logonID's from it
Set objInFile = objFSO.OpenTextFile(inFile2, ForReading)
'Create an ArrayList of all LogonID's, a TAB character and the EmailAddress
Set arrMailList = CreateObject( "System.Collections.ArrayList" )
Do Until objInFile.AtEndOfStream
strNextLine = objInFile.Readline
fields = Split(strNextLine , ",")
If arrUserIDList.Contains(fields(0)) Then
' store the values in arrMailList as TAB separated values
arrMailList.Add fields(0) & vbTab & fields(1)
End If
Loop
'close the file and destroy the object
objInFile.Close
Set objInFile = Nothing
Set objOutFile = objFSO.OpenTextFile(outFile, ForWriting, True)
For Each strNextLine In arrMailList
objOutFile.WriteLine(strNextLine)
Next
'close the file and destroy the object
objOutFile.Close
Set objOutFile = Nothing
'clean up the other objects
Set objFSO = Nothing
Set arrUserIDList = Nothing
Set arrMailList = Nothing
Hope that helps
This is how I solved my problem, but I think Theo took a better approach.
Const ForReading = 1
Const ForWriting = 2
Dim inFile1, inFile2, strNextLine, arrServiceList, arrUserList
Dim arrUserDeployList, strLine, arrList, outFile, strItem1, strItem2
inFile1 = Wscript.Arguments.Item(0) 'wscreatestatus.txt file (tab delimited)
inFile2 = Wscript.Arguments.Item(1) 'WSBatchCreateBuildsList.txt (comma delimited)
outFile = Wscript.Arguments.Item(2) 'SuccessWSMailList###.txt (for Welcome emails)
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInFile1 = objFSO.OpenTextFile(inFile1, ForReading)
Set objInFile2 = objFSO.OpenTextFile(inFile2, ForReading)
Set objOutFile = objFSO.CreateTextFile(outFile, ForWriting, True)
'Extracts Logon ID's for successfull deployments into an Array
'#================================================================
i = 0
Do Until objInFile1.AtEndOfStream
ReDim Preserve arrUsers(i)
strNextLine = objInFile1.Readline
arrLogons = Split(strNextLine , vbTab)
If arrLogons(0) = "PENDINGREQUESTS" Then
arrUsers(i) = arrLogons(5)
i = i + 1
End If
Loop
'Extracts success deploy email addresses and writes to file
'#================================================================
Do Until objInFile2.AtEndOfStream
ReDim Preserve arrMailList(i)
strNextLine = objInFile2.Readline
arrAddressList = Split(strNextLine , ",")
strItem1 = arrAddressList(0)
strItem2 = arrAddressList(1)
For Each strArrayEntry In arrUsers
If strArrayEntry = strItem1 Then
objOutFile.WriteLine strItem1 & "," & strItem2
End If
Next
i = i + 1
Loop
objOutFile.Close
objInFile1.Close
objInFile2.Close

IBM DOORS Copy text from column

I'm new to DOORS and DXL scripting (not sure if it'll be needed here or not). What I'm looking to do is create a new column in two separate modules that will copy the Absolute Numbers. I know this sounds simple enough, but what I'm running into an issue with is that I use a tool to convert my modules into a PDF and it combines them into one module before doing so. Doing this messes up the Absolute Numbers and I can't afford to have that happen.
More descriptive:
I have a column that contains the following:
'REQ01: 4' where 'REQ01:' represents the module and '4' represents the Absolute Number. Similarly, I have 'REQ02: 4'. I need to copy those in their respective modules and make sure they don't change after the modules have been combined.
I've tried my hand at some DXL scripting and this is what I came up with:
displayRich("REQ01: " obj."Absolute Number" "")
This appropriately shows the column, but again will not work as the Absolute Number ends up changing when I merge the modules.
Thanks in advanced for your help and I apologize if I left any crucial information out.
Here is the code that ultimately worked for me.
// DXL generated on 11 June 2014 by Attribute DXL wizard, Version 1.0
// The wizard will use the following comments on subsequent runs
// to determine the selected options and attributes. It will not
// take account of any manual changes in the body of the DXL code.
// begin parameters (do not edit)
// One attribute/property per line: true
// Show attribute/property names: false
// Include OLE objects in text: true
// Attribute: Object Text
// end parameters (do not edit)
Module m
AttrDef ad
AttrType at
m = module obj
ad = find(m,attrDXLName)
if(!null ad && ad.object)
{
at = ad.type
if(at.type == attrText)
{
string s
Buffer val = create
Buffer temp = create
ad = find(m,"Object Text")
if(!null ad)
{
probeRichAttr_(obj,"Object Identifier", temp, true)
val += tempStringOf temp
}
obj.attrDXLName = richText (tempStringOf val)
delete val
delete temp
}
}
There's a builtin "Copy Attributes" script which does this. At least in the version installed at my company, it's in the PSToolbox, and also available in the menu PSToolbox/attributes/copy.../betweenattributes... Here you go:
// Copy values from one attribute to another
/*
*/
/*
PSToolbox Tools for customizing DOORS with DXL V7.1
-------------------------------------------------
DISCLAIMER:
This programming tool has been thoroughly checked
and tested at all stages of its production.
Telelogic cannot accept any responsibility for
any loss, disruption or damage to your data or
your computer system that may occur while using
this script.
If you do not accept these conditions, do not use
this customised script.
-------------------------------------------------
*/
if ( !confirm "This script copies values from one attribute to another in the same module.\n" //-
"Use this to assist in changing the types of attributes.\n\n" //-
"It asks you to select the source and destination attributes.\n\n" //-
"It works by ... well, copying attribute values!\n\n" //-
"Continue?"
)
{
halt
}
#include <addins/PSToolbox/utensils/dbs.inc>
const int MAXATTRS = 1000
DB copyAttrValsDB = null
DBE copyAttrValsFrom = null
DBE copyAttrValsTo = null
DBE copyAttrValsConfirm = null
DBE copyAttrValsButt = null
string attrListFrom[MAXATTRS]
string attrListTo[MAXATTRS]
string confirmOpts[] = { "Yes", "Yes to all", "No", "No to all", "Cancel" }
bool confirmDataLoss = true
bool noToDataLoss = false
///////////////////////////////////////////////////////////
// Call-backs
void doAttrValsCopy(DB db) {
// check attributes
string fromAn = attrListFrom[get copyAttrValsFrom]
string toAn = attrListTo [get copyAttrValsTo ]
if ( fromAn == toAn ) {
ack "Cannot copy attribute to itself."
return
}
// get confirmation
if ( !confirm "Confirm copy of attribute '" fromAn "' to attribute '" toAn "'." ) {
return
}
confirmDataLoss = get copyAttrValsConfirm
// do copy
Object o
for o in current Module do
{
Buffer oldVal = create()
Buffer newVal = create()
if ( fromAn == "Object Identifier" ) newVal = identifier(o)
else if ( fromAn == "Object Level" ) newVal = level(o) ""
else if ( fromAn == "Object Number" ) newVal = number(o)
else newVal = richText o.fromAn
oldVal = richText o.toAn
if ( confirmDataLoss && !noToDataLoss && length(oldVal) > 0 && oldVal != newVal )
{
current = o
refresh current
int opt = query("About to lose attribute '" toAn "' = '" stringOf(oldVal) "' on current object.", confirmOpts)
if ( opt == 1 ) confirmDataLoss = false
if ( opt == 2 ) continue
if ( opt == 3 ) noToDataLoss = true
if ( opt == 4 ) return
}
if ( !confirmDataLoss || !noToDataLoss || length(oldVal) == 0 ) o.toAn = richText stringOf(newVal)
delete(oldVal)
delete(newVal)
}
hide copyAttrValsDB
}
///////////////////////////////////////////////////////////
// Main program
int numAttrsFrom = 0
int numAttrsTo = 0
AttrDef ad
for ad in current Module do {
if ( ad.module ) continue
string an = ad.name
if ( canRead (current Module, an) ) attrListFrom[numAttrsFrom++] = an
if ( canWrite(current Module, an) ) attrListTo [numAttrsTo++ ] = an
}
attrListFrom[numAttrsFrom++] = "Object Identifier"
attrListFrom[numAttrsFrom++] = "Object Level"
attrListFrom[numAttrsFrom++] = "Object Number"
copyAttrValsDB = create "Copy attribute values"
copyAttrValsFrom = choice(copyAttrValsDB, "From:", attrListFrom, numAttrsFrom, 0)
copyAttrValsTo = choice(copyAttrValsDB, "To:", attrListTo, numAttrsTo, 0)
copyAttrValsButt = apply (copyAttrValsDB, "Copy", doAttrValsCopy)
copyAttrValsConfirm = toggle(copyAttrValsDB, "Confirm on loss of data", true)
show copyAttrValsDB

LPeg Increment for Each Match

I'm making a serialization library for Lua, and I'm using LPeg to parse the string. I've got K/V pairs working (with the key explicitly named), but now I'm going to add auto-indexing.
It'll work like so:
#"value"
#"value2"
Will evaluate to
{
[1] = "value"
[2] = "value2"
}
I've already got the value matching working (strings, tables, numbers, and Booleans all work perfectly), so I don't need help with that; what I'm looking for is the indexing. For each match of #[value pattern], it should capture the number of #[value pattern]'s found - in other words, I can match a sequence of values ("#"value1" #"value2") but I don't know how to assign them indexes according to the number of matches. If that's not clear enough, just comment and I'll attempt to explain it better.
Here's something of what my current pattern looks like (using compressed notation):
local process = {} -- Process a captured value
process.number = tonumber
process.string = function(s) return s:sub(2, -2) end -- Strip of opening and closing tags
process.boolean = function(s) if s == "true" then return true else return false end
number = [decimal number, scientific notation] / process.number
string = [double or single quoted string, supports escaped quotation characters] / process.string
boolean = P("true") + "false" / process.boolean
table = [balanced brackets] / [parse the table]
type = number + string + boolean + table
at_notation = (P("#") * whitespace * type) / [creates a table that includes the key and value]
As you can see in the last line of code, I've got a function that does this:
k,v matched in the pattern
-- turns into --
{k, v}
-- which is then added into an "entry table" (I loop through it and add it into the return table)
Based on what you've described so far, you should be able to accomplish this using a simple capture and table capture.
Here's a simplified example I knocked up to illustrate:
lpeg = require 'lpeg'
l = lpeg.locale(lpeg)
whitesp = l.space ^ 0
bool_val = (l.P "true" + "false") / function (s) return s == "true" end
num_val = l.digit ^ 1 / tonumber
string_val = '"' * l.C(l.alnum ^ 1) * '"'
val = bool_val + num_val + string_val
at_notation = l.Ct( (l.P "#" * whitesp * val * whitesp) ^ 0 )
local testdata = [[
#"value1"
#42
# "value2"
#true
]]
local res = l.match(at_notation, testdata)
The match returns a table containing the contents:
{
[1] = "value1",
[2] = 42,
[3] = "value2",
[4] = true
}

Resources