Re: parent heading number roybond - Wed Oct 14 11:35:45 EDT 2009 Peter_Albert - Wed Oct 14 11:04:22 EDT 2009
The old Telelogic DOORS forum had a lengthy discussion on all possible pitfalls associated to this task. What is left in my collection of scripts is the attached routine provided by Tony Goodman, more or less implementing Louie's proposal.
string sectionNumber(Object o)
{ Object oParent =
null
// heading objects are easy
if (o.
"Object Heading"
"" !=
"" && !table(o) && !cell(o))
{
return(number(o))
}
// get parent object oParent = parent(o)
if (
null oParent)
{
// text object at top of hierarchy
return(
"0")
}
// recurse
return(sectionNumber(oParent))
}
Regards,
Peter
I have a similar script which looks for a Parent Object, but given that the immediate Parent may not itself contain a Heading, I have a loop which makes a fixed number of attempts to find the Parent :
Object findSectionHeading (Object o)
{
int maxLoop = 5
// Maximum number of attempts to find a Parent Object with Object Heading text. string oHead = o.
"Object Heading"
if (
null oHead)
{ bool found =
false
int i = 0
while (!found && i != maxLoop)
{ o = parent o
if (
null o)
{ i = maxLoop
}
else
{ oHead = o.
"Object Heading"
if (!
null oHead)
{ found =
true
}
else
{ i++
}
}
}
}
return o
}
All of this does, of course, assume that the Object structure uses Parent and Child Objects (ie. is not Flat).
Roy.
|
Re: parent heading number moonray - Wed Oct 21 08:11:23 EDT 2009 llandale - Tue Oct 20 14:45:43 EDT 2009
po = parent po
getparentheading po
should be just:
po = getparentheading(po)
Also, an empty DOORS object is (strangely) considered a heading in DOORS. Thus its a heading when o."Object Heading" is not null, or when o."Object Text" is null and there is no 'picture' and there is no OLE in the Object text in the object. I don't recall the exact rules regarding empty invisible rich text markup in Object Text. And, of course, table/row/cell objects are not allowed to be headings, even when they have Object Heading.
Forget all that. Parse the paragraph 'number' of the object to determine whether its a heading.
Louie,
I used your abbreviated po = getparentheading(po) while bringing up my function and spent a few hours figuring out why it wouldn't recurse properly. I ended up with the format as originally listed, which works for me in all normal cases. I attribute the non-functionality of the abbreviated form to a DOORS internal bug under recursion, and didn't have time to pursue it any further.
|
Re: parent heading number llandale - Thu Oct 22 15:17:04 EDT 2009 moonray - Wed Oct 21 08:11:23 EDT 2009
Louie,
I used your abbreviated po = getparentheading(po) while bringing up my function and spent a few hours figuring out why it wouldn't recurse properly. I ended up with the format as originally listed, which works for me in all normal cases. I attribute the non-functionality of the abbreviated form to a DOORS internal bug under recursion, and didn't have time to pursue it any further.
Sorry, perhaps you posted the wrong thing, but what you posted could not possibly work, which was this:
Object getparentheading (Object o)
{
if (o ==
null)
return
null Object po = parent(o)
if (po !=
null and po.
"Object Heading" ==
"")
{ po = parent po getparentheading po
}
return po
}
[1] You have an interpret error in line 5 where you compare an attr reference to a null string:
This:
if (po !=
null and po.
"Object Heading" ==
"") should be changed to:
if (po !=
null and po.
"Object Heading"
"" ==
"")
[2] you are invoking your function recursively, but not assigning the returned Object to anything:
This: getparentheading po must surely be changed to something like
this: oResult = getparentheading po
Your code will find the heading if its the next higher object (a normal spec layout), but will otherwise return the one 2 levels higher regardless of whether its a heading.
Well, my suggestion didn't work either.
Try this:
o Display object level and object number.
o Create a module with a long list of text objects 'below' each other: hit cntl-L a few times, then edit each object and insert Text cntl-t.
o Add Heading to the first object.
o Create a new heading 'after' the first object cntl-N, then add heading.
o Insert a table 'below' that new heading.
Select one of the lower objects and run the below. Notice your function finds a text object, but mine (new code) finds the first object. Select a table cell. Notice your function finds the table object but mine finds the heading.
Object getparentheadingMoonray(Object o)
{
if (
null o) print
">>getMoonray: null(o)\n"
else print
">>getMoonray: " identifier(o)
"\n"
if (o ==
null)
return
null Object po = parent(o)
if (po !=
null and po.
"Object Heading"
"" ==
"")
{ po = parent po getparentheadingMoonray(po)
}
return po
}
// end getparentheadingMoonray() Object getparentheadingLandale(Object o)
{
if (
null o) print
">>getLandale: null(o)\n"
else print
">>getLandale: " identifier(o)
"\n"
if (o ==
null)
return(
null) Object po = parent(o)
if (po ==
null)
{
}
// nothing to do elseif(po.
"Object Heading"
"" !=
"")
{
}
// This is a heading, nothing to do
else po = getparentheadingLandale(po)
return po
}
// end getparentheadingLandale()
void Driver(Object oCurr)
{ Object oMoonray = getparentheadingMoonray(oCurr) Object oLandale = getparentheadingLandale(oCurr) print
"** " identifier(oCurr)
"\t" number(oCurr)
"\thas parents:\n"
if (
null oMoonray) print
"\tMoonray: \tnull(parent)\n"
else print
"\tMoonray: \t" identifier(oMoonray)
"\t" number(oMoonray)
"\n"
if (
null oLandale) print
"\tLandale: \tnull(parent)\n"
else print
"\tLandale: \t" identifier(oLandale)
"\t" number(oLandale)
"\n"
}
// end Driver() Driver(current Object)
// **** MAIN ****
Even my function is inadequate, since empty objects are indeed considered 'headings' by DOORS, as evidenced by the fact they display their number in the main column. As I recall, a DOORS 'Heading' is an object either containing non-null raw Heading or containing no raw Text, no Ole in the Text, and no Picture. Somewhere along the way I found some obscure exception to even that (perhaps it had to do with invisible rich text), and then I gave up and went with the parse-the-number method. Below is my function "fIsHead" which determines if the specified object is considered a 'heading' by DOORS. use fIsHead instead of checking null Object Heading in my function above.
// Following buffer is local to fIsHead() Buffer gl_bufIsHeadNum = create(32)
//*********************** bool fIsHead(Object obj)
{
// Does DOORS consider the object a 'Heading' object?
// Heading Objects are those that display the paragraph number in the Main column in DOORS
// DOORS considerations for determining 'Heading Objects':
// [a] Objects that contain some non-null rich Heading text.
// [b] Objects that have no non-null rich Object Text and no Pictures (i.e. empty objects)
// [c] However, Cell, row header, and table header objects are NEVER headings,
// even when they contain Object Heading or are empty.
// [d] Note that invisible rich-text markup only is considered.
// This function looks at the Paragraph number of the object to determine if
// DOORS considers it a Heading.
// Notes:
// [1] Normal Text Object Paragraph Numbers have a ZeroDash and look like this: 3.2.1.0-4.
// Notice there is a dash after the last period.
// [2] Normal Headings Numbers have no dash and look like: 3.2.1.
// [3] When a Heading is (incorrectly) a child of a Text Object, its Para looks like this:
// 3.2.1.0-4.2; notice there is a period after the last dash.
// [4] Level 1 Headings paragraphs have no dashes nor periods, and look like "1".
// [5] Level 1 Text paragraphs have no periods, but do contain a dash, and look like "0-1".
// [6] Objects in tables (cell, row, table) have para numbers like nested text objects: 3-2.0-1.0-1.
// This function would correctly identifies them as Text without an explicit check,
// but to save time and string table space a specific table-row-cell check is made.
// Strategy: Get the paragraph 'number' of the object.
// If its in a table its not a Heading
// If it contains no dash then its a heading.
// If it has a dash but there is a period following the last dash, then its a heading.
// Otherwise (there's a dash with no period after it) then its not a Heading object.
if (
null obj)
return(
false)
int LocDash, LocDashLast, LocDashNext, LocPeriod
// Locations in the paragraph number
if (row(obj) or table(obj) or cell(obj))
return(
false)
// Table-Row-Cell objects are not Headings. gl_bufIsHeadNum = number(obj)
// Put the Paragraph in the buffer LocDash = contains(gl_bufIsHeadNum,
'-', 0)
if (LocDash < 0)
return(
true)
// No dashes at all, must be a heading (e.g. "2" or "3.2.1")
// Find the last dash in the Paragraph Number LocDashLast = LocDash LocDashNext = LocDash
while (LocDashNext > 0)
{ LocDashNext = contains(gl_bufIsHeadNum,
'-', LocDashLast+1)
// print "\t" tempStringOf(gl_bufIsHeadNum) "\t" LocDash "\t" LocDashNext "\n"
if (LocDashNext > 0) LocDashLast = LocDashNext
}
// Find any period after the last dash: LocPeriod = contains(gl_bufIsHeadNum,
'.', LocDashLast+1)
// print "fIsHead\t" (stringOf(gl_bufIsHeadNum)) "\t" LocDash "\t" LocPeriod "\n"
return(LocPeriod > LocDashLast)
// Its a heading if there's a period after the last Dash
}
// end fIsHead()
|