Monday 22 June 2015

OSLC Resource Selection

Last time I presented idea of OSLC DXL Services which can very powerful and useful.
One can write a DXL services against database, projects or modules, but providing DOORS resources links manually might be very inconvenient.
There is much easier way to select your resource.
DWA server is OSLC RM Provider and as such it provides resource selection delegated UI.
You can find more information on Delegated UI here.
So before I will continue with next more complex examples of OSLC DXL Services or more powerful Node.JS applications I will focus on simple resources selection.
In terms of OSLC you can select Requirement Collection (a Module) or single Requirement (Object/Requirement).

Protocols

There are two protocols which OSLC Consumer could use to select resouce:
  • #oslc-core-postMessage-1.0 - Indicates that the Post Message protocol is to be used
  • #oslc-core-windowName-1.0 - Indicates that the Window Name protocol is to be used
Here I will show how to use post message protocol which works with all modern browsers. OSLC specification provides UI consumer's responsibilities which should be followed:
  1. Include the Delegated UI Dialog via iframe (i.e setting iframe src to the URI of the Delegated UI Dialog) or via an embedded browser. Append the fragment identifier #oslc-core-postMessage-1.0 to the URL to indicate that Post Message is the desired protocol.
  2. Add a 'message' listener to the outer window to receive messages from the Delegated UI Dialog.
  3. Listen for window 'message' events, ignoring events from other sources or not prefixed with "oslc-response:"
  4. When message from Delegated UI Dialog indicates user completed action, free resources and handle action. 

1. Providing an iframe for Delegated UI

Let's look at very basic HTML page:
<!DOCTYPE html>
<html>
<head>
    <title>DWA OSLC Delegated UI test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script type="text/javascript" src="/scripts/delegatedui.js"></script>
</head>

<body >
    <h1>DWA OSLC Delegated UI test</h1>
    <div>
        <button id='buttonSelect' type="button" onclick="delegatedUI.selectResource()">Select module</button>
    </div>
    <div id="OSLCMainDiv"></div>
    <div id="anotherDiv"  >
    </div>
</body>
Here I have just a button and some divs. You can find full source of /scripts/delegatedui.js here.
Button "Select Module" has following callback:

function selectResource() {
        clear();
        
        // Add 'iframe' element dynamically
        var frameName = "";
        frame = createElement("iframe", frameName);
        frame.id = "OSLCContainer";
        frame.width='400px';
        frame.height='500px';

        addEvent(window, "message", onMessageReceived);
        
        var mainDiv = document.getElementById("OSLCMainDiv");
        if (mainDiv) {
            mainDiv.appendChild(frame);
        }

        frame.src = "https://server:port/dwa/rm/calm/v2/selectRequirementCollection" + "#oslc-core-postMessage-1.0";
    }

This simply dynamically adds an iframe, registers its callback and appends "#oslc-core-postMessage-1.0" as chosen protocol.
Of course one should discover OSLC Service Provider selection dialog using Service oslc:selectionDialog property (as defined specification), but I used general DWA schema for requirement collection (a module) selection.

2. Adding message listener

We need to registering 'message' event listener as called from selectResource function:

function addEvent(obj, type, func) {
        if (obj.addEventListener) {
            obj.addEventListener(type, func, false);
        }
        else if (obj.attachEvent) {
            obj.attachEvent("on" + type, func);
        }
        else {
            obj["on" + type] = func;
        }
    } 

3. Listen to events

Once message is registered we have to listen to incoming events ignoring those not prefixed with "oslc-response:" :

 function onMessageReceived(event) {
        if (frame && event.source === frame.contentWindow) {
            var prefix = "oslc-response:";
            if (event.data.substring(0, prefix.length) === prefix) {
                done(event.data.substring(prefix.length));
            }
        }
    }


With 'done' method triggered when 'oslc-response' is found in event data:
function done(data) {
        var title = JSON.parse(data, function(key, value) {
            if (key.equals('rdf:resource')) {
                clear();
                // TODO: add you logic here
                // value contains a link to the resource
                // title is a Module name
            }
        });
    }

4.  Cleanup


Whatever cleanup you require that's the place to do it. I simply remove listener and iframe element

function clear() {
        var mainDiv = document.getElementById("OSLCMainDiv");
        if (mainDiv) {
            // clear any existing child elements
            mainDiv.innerHTML = ''; 
        }

        removeEvent(window, "message", onMessageReceived);
    }

No comments:

Post a Comment

Note: only a member of this blog may post a comment.