Features-_hero

Blog - Engineering Systems & Integration Software

Sodius is committed to providing you with the systems and software to provide continuous information flow across the product development lifecycle.

Creating a Custom DOORS Importer in 5 Minutes

Last updated Thursday, November 29, 2018. 

DOORS, systems engineering tool, provides a generic importer for MS Word. This importer is good for plain text documents, but doesn’t work well when the Word document is structured.

For example, my customer formats his requirements like this:

[001] Instrument length must be less than 30 cm
Attributes  

Revision

Owner

Severity

1

E

A

Category Physical
Description The length of the instrument must be less than 30 cm so that it can fit into the carrying case.

 

[002] Instrument width must be between 5 mm and 1.5 mm
Attributes  

Revision

Owner

Severity

2

E

A

Category Physical
Description The total width of the instrument must be greater than 5 mm, but less than 1.5 mm for ease of use.

 

[003] Instrument build cost must be less than 0.05 USD
Attributes  

Revision

Owner

Severity

1

A

B

Category Cost
Description The total cost of production for the instrument must be less than 5 cents.

Using the DOORS Exporter in Word, DOORS produces this formal module:

 

DOORS Export in Word DOORS Export from Word

 

The information is contained in this formal module, but hardly in the way that my customer would have liked!

The structure of the Word document is :

[ID] Object Short Text value
Attributes  

Attribute Name 1

Attribute Name 2

Attribute Name 3

Attribute Value 1

Attribute Value 2

Attribute Value 3

Category Object attribute “Category” value
Description Object Text value

Therefore each Word table corresponds to 1 DOORS Object, with the other table values used to fill-in attribute values on that Object.

For example, this Word table:

[001] Instrument length must be less than 30 cm
Attributes  

Revision

Owner

Severity

1

E

A

Category Physical
Description The length of the instrument must be less than 30 cm so that it can fit into the carrying case.

should produce this in DOORS:

systems engineering tool snapshot

systems engineering tool screenshot

DOOR systems engineering picture

So how do we solve this problem?

We’ll use the MDWorkbench and its DOORS and Word connectors to map the values into the desired Object structure.

First we need understand how the data is structured in Word so we can know how to get the values out of the document.

MDWorkbench has a Model Viewer that shows us Word document structure.

systems engineering tool

We can see that the Word document has some tables in it, which contain rows, which themselves contain cells.

We can also look at the structure of the DOORS formal module that we’d like to create.

DOORS systems engineering tool

DOORS reporting and systems engineering tool

By looking at the underlying DOORS representation of the Object created for the requirement in Word, we can see that we need to set the objectShortText, objectText, and some instantiatedAttributes.

Now we can write the rules that take the information from Word and create this structure in DOORS.

Creating the Import Rules

The first thing to do is to create a new ruleset in MDWorkbench, and to set the input and output models that we are going to use.

public ruleset WordTableImporter(in word : word, out doors : doors) {
public rule importTablesFromWord() {
}
}

Then I usually start by pulling the information from my source, in this case Word.

// loop through each table in Word
foreach (table : word.Table in word.getInstances("Table")) {
// get the user id from first row, first cell, 3 characters between []
table.row.get(0).cells.get(0).value.substring(1,4);
// get the short text after the user id
table.row.get(0).cells.get(0).value.substring(6);
// get the category from the 4th row, second cell
table.row.get(3).cells.get(1).value;
// get the long description from 5th row, second cell
table.row.get(4).cells.get(1).value;
// user-defined attribute namesare in row 2
var attNameRow : word.Row = table.rows.get(1);
// loop through the user-defined attribute names in row 2
foreach (attNameCell : word.Cell in attNameRow.cells.subList(2, attNameRow.cells.size())) {
// get the attribute values in the same cell in row 3
table.rows.get(2).cells.get(attNameCell.y - 1).value;
}
}

Once I have figured out how to get the values out of Word, I set the values in DOORS. At this point, I start to break the logic into subrules for functions like creating a formal module and creating attributes on the objects.

// setup DOORS
// create a "Imports" folder in DOORS
var folder : doors.Folder = doors.create("Folder");
folder.name = "Imports";
// create the formal module
// use a subrule "createFormalModule" to encapsule that function
var fm : doors.FormalModule = @createFormalModule(folder, "Imported from Word");

// loop through each table in Word
foreach (table : word.Table in word.getInstances("Tables")) {
// create DOORS object
var object : doors.Object = doors.create("Object");
fm.objects.add(object);
// get the user id from first row, first cell, 3 characters betwenn []
@setAttributeValue(object, "User_ID", table.rows.get(0).cells.get(0).value.substring(1,4));
// get the short text after the user id
object.objectShortText = RichText.valueOf(table.rows.get(0).cells.get(0).value.substring(6));
// get the category fromt he 4th row, second cell
@setAttributeValue(object, "Category", table.row.get(3).cells.get(1).value);
// get the object text from the 5th row, second cell
object.objectText = RichText.valueOf(table.rows.get(4).cells.get(1).value));
// use defined attribute names are in row 2
var attNameRow : word.Rox = table.rows.get(1);
// loop through the user define attributes names in row 2
foreach (attNameCell : word.Cell in attNameRow.cells.subList(2, attNameRow.cells.size())) {
// get the attribute values in the same cell in row 3
@setAttributeValue(object, attNameCell.value, table.rows.get(2).cells.get(attNameCell.y - 1).value);
}
}

And then I define the missing subrules:

// Create a formal module with the given name
private rule importTablesFromWord::createFormalModule(folder : doors.Folder, ame : String) : doors.FormalModule {
var fm : doors.FormalModule = doors.create("FormalModule");
// add the formal module to the given folder
folder.ownedItems.add(fm);
// set the name
fm.name = name;
// create base attribute type (only String for now)
var type : doors.Type = doors.create("Type");
type.name = "String";
type.baseType = BaseTypeKind.STRING_LITERAL;
fm.types.add(type);
return fm;
}

// Set the value of the attribute on the object
private rule importTablesFromWord::setAttributeValue(object : doors.Object, attName : String, attValue : String) {
// get the formal module's attribute that we want to set
var attribute : doors.Attribute = @getOrCreateAttribute(object.module, attName);
// create an instantiatedAttribute
var instantiatedAttribute : doors.InstantiatedAttribute = doors.create("InstantiatedAttribute");
instantiatedAttribute.instantiates = attribute;
// set the value
instantiatedAttribute.value = RichText.valueOf(attValue);
// add the attribute value to the Object
object.instantiatedAttributes.add(instantiatedAttribute);
}

// Find the attribute on the formal module or create a new one
private rule setAttributeValue::getOrCreateAttribute(fm : doors.FormalModule, name : String) : doors.Attribute {
// search for the attribute with the correct name
var attribute : doors.Attribute = fm.attributes.detect("name", name);
if (attribute == null) {
// if the attribute is not found, create it
attribute = doors.create("Attribute");
// set the name
attribute.name = name;
// set the type
attribute.type = fm.types.detect("name", "String");
// add the attribute to the formal module
fm.attributes.add(attribute);
}
return attribute;
}

(Here is the ruleset code: WordTableImporter.mqr)

And then I execute:

DOORS systems engineering tool stillshot

The resulting DOORS module is what I want:

DOORS reporting and systems engineering tool picture

Now I deploy, and add as an Add-In in Word.

Here is the full project zip file: DOORSWordTableImporter.zip

Learn More about DOORS

Related posts

Driving Requirements into the Lifecycle

19 Feb 15

Driving Requirements into the Lifecycle with Integration – How Tasktop™ Sync Enables IBM® Rational® DOORS® and DOORS NG to Integrate with...

MDAccess Makes DOORS Integrations Easy

17 Nov 14

Get to Your IBM® Rational® DOORS® Requirements with Java™ – How MDAccess Makes DOORS Integrations Easy If you are using DOORS to manage your...

    strip-bg

    We have a team of experts who have helped countless teams reach success. How can we get you there?