Rendering generated Content in Polarion Documents

So far, developing and using Widgets is a standard when displaying aggregated data of Work Items across the whole project or different documents, for stuff like testing reports, traceability matrixes. But these are always external, can of course be opened in a baseline (e.g. for a specific release), but do not have a Workflow or Review abilities like documents or Work Items.

In Documents although, rendering reports is not possible, that means in Polarion, documents are just plain text, tables, images and Work Items. Or are they?

I will use the Weather Station Demo Project for my examples. Especially the “Feature Model” document will be used. Please adapt all examples to your use case and needs.

Introducing Wiki Content

In Documents, it is possible to add custom code with a functionality called “Wiki Content”. These are visible in the Toolbar at the top of each document, assuming you have rights to edit the document:


With Document Macros it is possible to write custom velocity code, just like a simple hello world message. Try it out yourself:

#set($name = "world")
<h1>Hello $name!</h1>
  1. Add the code to your wiki content. (If its not open, click on the small icon on the right of the dotted lines and click on “Edit”)
  2. Click on “OK” to submit the code you have written and save the document.
  3. Enjoy the “Hello World” message

As you can see, adding code to a document is as easy as writing a custom report. Shouldn’t be so difficult to add some more logic right?

Velocity Variables for Wiki Pages

Polarion provides us with several variables, we can use when we write custom reports or wiki pages. The full list is available here (Velocity Variables for Wiki Pages), I will shortly focus on some, which deserve our focus in the following sections:

With these we can do funny things in our test documents just like this:

#set($apiDocument = $transaction.documents.getBy.oldApiObject($document))
$document.getTitleOrName: $apiDocument.render

Which results in the following:

So we are now able to query the Work Items of the current document, check the documents custom fields and display everything of that data inside the document. The data is therefore bound to the documents approval process, rendered correctly when opened in a historic revision and readonly if the document is readonly. Seems perfect right.

Maybe some abstract examples to show what could be done inside this document:

  • Display a simple table, that not only displays ID, Title and Description, but specific custom fields as well.
  • Displaying Work Items with their corresponding links (such as features of the current document and corresponding requirements / variants) in a table directly in the feature document
  • Display a list of Work Items that are in a specific status and need special attention
  • Display inserted Work Item references, that have been frozen and have a newer version available, so that the document author gets informed accordingly.
  • Display Review and Approval Tables, like who needs to sign the document and which Work Items need Review, before the next workflow step could be started.
  • Display Traceability or Test Summaries accross multiple documents you selected in the document custom fields.

But as we gather ideas about what is possible and start writing code, we should realize, that this process has one big problem: maintainability. The code we write to display such things needs to be copy and pasted accross nearly every document. Of course we could cover that with document templates, that get reused over and over, but what happens as soon as we want to make a change, such as adding an additional column to a table, we have across dozends or hundreds of documents. Here another feature of Polarion comes in..

Writing Reusable Velocity Macros

We are able to create macros, which are reusable in the current scope of our velocity code. These are similar to Functions in other programming languages like Java, C# or JavaScript. We can create a macro with the following syntax:

## Definition with one variable
## printHello being the macro name
## $message
#macro(printHello $message)
 <h1>Hello $message!</h1>
#end
## To call our macro with a custom message
#printHello("World")

This will result in the same Hello world message, we have written before. The scope of velocity is always the opened page, we are currently on. This means, that we can create one macro for displaying a table of a list of Work Items with a parameter of custom fields and reuse that across the whole document.

## renderWorkItemTable - renders table of work items
## $workItem - WorkItems of Rendering API
## $fieldNames - Labels for table header
## $fields - Field Ids to render
#macro(renderWorkItemTable $workItems $fieldNames $fields)
    <table style="width: 100%">
        <thead>
            <th>ID</th>
            <th>Title</th>
            #foreach($field in $fieldNames)
                <th>$field</th>
            #end
        </thead>
        <tbody>
            #foreach($workItem in $workItems)
                <tr>
                    <td>$workItem.render.withLinks.openLinksInNewWindow</td>
                    <td>$workItem.fields.title.render</td>
                    #foreach($field in $fields)
                        <td>
                            #if(!$workItem.fields.get($field).is.empty)
                                $workItem.fields.get($field).render
                            #else
                                N/A
                            #end                        
                        </td>
                    #end
                </tr>
            #end
        </tbody>
    </table>    
#end
## So we can now display tables of all Work Items in the document, only headings and only features: 
#set($apiDocument = $transaction.documents.getBy.oldApiObject($document))
#renderWorkItemTable($apiDocument.items ["Description", "Status"] ["description", "status"])
#renderWorkItemTable($apiDocument.items.filtered("type:heading") ["Description", "Status"] ["description", "status"])
#renderWorkItemTable($apiDocument.items.filtered("type:feature") ["Description", "Status"] ["description", "status"])

So now we are again one step closer to reuse one macro across one document, but how can we reuse them across multiple documents?

Organizing Macros in Wiki Pages

Polarion provides LiveReport Pages for using all of the new reporting functionalities in Polarion. Polarion also provides the Classic Wiki Pages, on that most of used must have looked like: “Why are they there? Why should I ever need them?” -> You will need them now:

  • Go to the index of the default space (this is possible with any space, but we want to make it easier for now)
  • Create a new Classic Wiki Page
  • Click on Expand Tools
  • Click on Edit
  • Paste the macro (and only the macro) inside of this page and save.
  • Now you only need the following call in our document to import the functions into it (most times this is at the top of your document, so the import happens before any macro call). You can remove the old call now.
{include-macros:_default.Macros}
## So we can now display tables of all Work Items in the document, only headings and only features: 
#set($apiDocument = $transaction.documents.getBy.oldApiObject($document))
#renderWorkItemTable($apiDocument.items ["Description", "Status"] ["description", "status"])
#renderWorkItemTable($apiDocument.items.filtered("type:heading") ["Description", "Status"] ["description", "status"])
#renderWorkItemTable($apiDocument.items.filtered("type:feature") ["Description", "Status"] ["description", "status"])
  • When you save again you see all tables, you previously saw, instead the code to render them is no longer in your document but in a separate page.

Wow! This means that we can now display that table in every document we want. We can also write other tables, informations or lists, call macros inside macros and so on and so on. And it even works with multiple projects, imaging you have all Macros and Document Templates in a Library project, to which all users have read access, you can import macros with the following call in all documents of the whole system:

{include-page:library/_default.Macros}

Polarion also provides a great help for Wiki Macro Syntax , which you can find in every polarion instance here: polarion/#/wiki/Doc/SyntaxHelp.
Feel free to try this out and use it in your current Polarion projects. You will see, that this will improve reusability and functionality of Polarion documents and the workflow overall.

Points to consider when working with Document macros

Now that you can start to develop everything you need to use directly inside of documents, you may consider the following points:

  • Macros need time to load: Although its nice to display fancy tables, lists and other stuff directly in the document and accross douments in your project, you need to be aware that every little macro needs time. And especcially if macros become more complex or need to cover more data it will result into longer loading and saving times in your document. So please consider carefully, which macros are needed every time the user loads. the document.
  • Write maintainable macros from the start: As you start writing macros and use them in your documents, you will realize how much can be automated with it. Beautiful First Pages can be rendered, a history as well, Approval records and so on. But because most of it wont be available from the start you need to go into each document and add the new macros they need to call. This will get very time consuming in the long run. Instead try to group certain macros, which you need at a certain area in your document. Using something like a Header Macro which contains said First Page, History and Approval records and can then be extended later helps to cover with this maintenance tasks.
  • Organize your macros by topic: Instead of having one huge file, which imports every macro, try to think in topics: Which macro will be used where e.g. there could be workflow related macros or macros that cover traceability. Those could be separated into their own files. To simplify the imports, you could then add an init macro in every project, which has again macro calls to call the different pages. Sounds too complicated? Maybe, but this is only relevant for larger collections of macros. Why should you do that? I increases again performance, because the document does not have to process every macro definition it imports, but only that of the topic it needs.

Outlook

Now that you should have a general idea of what could be done with macros and how it works, you could rethink your current project setup and try to improve some simple parts. Maybe you got already some Widgets in Java and are thinking: What about them? How could I get that logic into Polarion?

Maybe a cliffhanger for my next article: There is a way to reuse custom developed Java Plugins in Polarion and it simplifies your macro calls even more.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website with WordPress.com
Get started
%d bloggers like this: