Tag: Custom Project Component

OPA – Dynamic Visibility

Dynamic Visibility

In certain situations, it is necessary to display or hide elements of the Policy Automation Interview. The easiest way to obtain this OPA – dynamic visibility is to create rules, whose conclusion can act as a basis for the Visibility. For example, if the color is red, then show the size question. And inversely – If the color is not red, then do not show the size question.

Such a method is simple and the result is attractive to the End User. It can be implemented with the Question displayed during the Interview, referencing the rule you have created. In the following screenshot you can see an example with the relevant Boolean Attribute referenced in the Attribute Input Control properties.

Question-with-Visibility-Rule

Mandatory and Read-Only

A similar approach can be taken to render a Question mandatory, or when a Question should have it’s Value displayed as read-only. The existence of a Boolean Attribute to reflect your business logic is once again a pre-requisite, but the process of aligning it with an Input Control is the same.

Mandatory-Question-using-Dynamic-Boolean

 

List of Values – Dynamic Values

A further area where such dynamic visibility can be useful to make the end user experience more enjoyable, is in the area of Lists of Values. If a Attribute has a List of values, some Values may need to be hidden in certain circumstances. The same dynamic effect can be achieved by associating each Value with a Boolean Attribute in much the same way as the previous examples.

 

Visibility-of-Pick-List-Value

Better for the End User

Simple logic such as this can increase the engagement of an End User – after all, the easier it is to complete something with the minimum of irrelevant questions or data the more likely you are to see happy End Users. Until next time, see you soon.

Rich@ard

 

Policy Automation – Custom Java Libraries #2

Policy Automation – Custom Java Libraries #2

In the previous post we looked at the basic setup of your Policy Automation project so that it can receive a custom Java Library containing some functions, and use them in your Policy Automation Documents like standard functions.

Now we can move on to the first example function. We will use a suitable development environment such as NetBeans or your own choice. We create a simple piece of code like the following :-

package com.oracle.determinations.examples;
//Import Custom Functions and EntityInstances
import com.oracle.determinations.engine.CustomFunction;
import com.oracle.determinations.engine.EntityInstance;
import java.util.*;
/**
 *
 * @author Richard Napier
 */
public class ODECalculate extends CustomFunction {
 @Override
 public Object evaluate(EntityInstance arg0, Object[] arg1) {
 // TODO Auto-generated method stub
 String firstargument = arg1[0].toString();
 String secondargument = arg1[1].toString();
 String combinedargs = firstargument + " " + secondargument;
 StringBuffer bufferedtext = new StringBuffer(combinedargs);
 System.out.println("Reverse String Buffer returns " + bufferedtext.reverse().toString());
return bufferedtext.toString(); }
}

Let us walk through the code. Firstly our new library imports the necessary:

import com.oracle.determinations.engine.CustomFunction;
import com.oracle.determinations.engine.EntityInstance;

Then we extend CustomFunction, overriding the standard evaluate Method with our own code. This simply extracts the two input arguments we defined in our XML file last time, and concatenates them. Then we use a StringBuffer and the built-in reverse() function to reverse the text. So Policy Automation will become yciloP moitamotuA.

Finally we return that as the output of our custom evaluate method. In the code above we have also written the output to the Console, which we will be able to see in Policy Modelling perhaps for debugging purposes.

OPA - Sample Code

Readers will notice that we have also imported some libraries that we have not used in this example, they will be used in a later post. Now that our code has been entered in our chosen development tool, we also need to Build the code into a Jar File.

OPA - Build JAR file

Once we have obtained our JAR file we can place in the correct folder for our Policy Automation Project, which is a child of the folder where we placed our XML file.

OPA - Folder for JAR file in Policy Automation Folder StructureNow we are ready to write our first line of Policy Automation using our new function. Provided we respect the XML definition, the following will compile successfully.

OPA - Example Function Call

We can then run the Web Determinations on a java-based platform to see the result. The easiest way is to Build and Run Web Determinations to use the embedded version of Tomcat. Of course our interview is not very interactive so far, with only these two questions.  But the result of the interview should be visible in the Browser, and also in the Embedded Web Server Output.

OPA - Console Output OPA - Reversed Text in Web Determination

Of course writing functions in this way must respect certain basic, well documented principles, in order that we do not interfere with the inference engine. The output of your function must be predictable – that is, providing the same inputs must provide reliably the same outputs. This is not a good place to generate a truly random number, for example.

In the next post, we will further customize our function to use the EntityInstance. See you soon!

 

Policy Automation – Custom Java Libraries

Custom Java Libraries

At some point in time, a Policy Automation project may hit a potential roadblock because there is specific functionality that is used to perform some sort of check or calculation, and this functionality already exists in a Java library, or a Visual Studio DLL. It may be desirable to re-use the functionality in the Policy Automation deployment.

Re-using functions in this way requires specific handling as we will discover. Naturally one must consider the deployment – will Policy Automation be running under Apache or IIS for example (and thus, how will the functionality need to be packaged). A Custom Java Library can be developed to overcome the problem, assuming there are no more standard options. It should also be noted that the concept of Custom Java Libraries is available in a wide variety of situations to extend the Policy Automation engine – both for Web Determimations and Determination Server. Each kind of Custom Java Library requires a different set of programming guidelines or “template” which can be downloaded or copied and pasted from the documentaton.

When building a custom function library for whatever purpose, there are other twists and turns to be watched out for. As an example, when using the Debugger to run the following rulebase (assuming that you have written the necessary Java code to implement a custom function ):-

OPA - Custom Function in Word Document

When you start to Build and Debug (without Screens), you get the following rather interesting message:-

OPA - Custom Function has no .NET Handler Message

The Policy Modeller uses .NET to power it’s debugging, so if you have not created a .NET implementation of your code you will get this. It will also occur in the Regression Tester which uses the same engine.

Using the “With Screens” option pushes your rulebase to the embedded Tomcat installation in your Policy Modelling environment,so you would expect to be able to use your function. There are still things to be aware of as we will see.

But we are getting ahead of ourselves. How do you go about creating a custom function for Policy Automation? It all starts with an XML file called extension.xml which is used to signal the existence of a Java file to Oracle Policy Automation. Here is a simple example, specifying the function that has been created in Java code “ODECalculate”.

<?xml version="1.0" encoding="utf-8"?>
<extension>
 <functions>
 <function name="ODECalculate" return-type="text">
 <arg name="arg1" type="text" />
 <arg name="arg2" type="text" />
 <handler platform="java" class="com.oracle.determinations.ODE.ODECalculate" />
 </function>
 </functions>
</extension>

This file, as you can probably see, defines the functions, their arguments and their implementation – here you can see this is using a Java implementation. If you added another handler for .NET you would probably have a line like this one.

<handler platform="dotnet" class="com.oracle.determinations.ODE.ODECalculate" />

This file is designed to be added to your Policy Automation Project in a folder like this one, inside your Development folders. Note the name of the folder used to contain the XML file as well as the XML file name.

OPA - Extension XML File Location

Now that we have our file in place, we can begin creating a simple example function and actually writing some code. See you in part two!

Policy Automation – Live Substitution in Question Screens

In the Policy Automation training, we discuss (and we have discussed on this Blog) the subject of Substitution. Put simply, if you have created a Customer called “Bob”, you want to see “Bob’s invoice” not “the customer’s invoice” in your Web Determination.

Fresh with this knowledge, students go and create a new
Rulebase and they put 4 attributes on one Screen in their
Screens File, like this:

OPA - Bob in the Screen Editor

They Build and Debug their rulebase and they get terribly
excited because it works, the name is substituted
automatically and Bob is displayed instead of the mournful
“the customer #1”.

OPA - Bob in the Debug Window

So the students then proceed to Build and Run their Web
Determination. Up pops the Web interface and their faces
drop. The substitution doesn’t work. You just get this:

OPA - Brenda with no Substitution

They ask you what is wrong, why does it not work. Why does it not say Brenda’s order number? And you say, “Well of course it doesn’t! The Web Determination user interface is plain old HTML, without anything fancy, so you can only get a substitution to work if you put the questions on different pages” (Thereby allowing a refresh between pages).

And people are quite unhappy. Well of course they are! If you
have Web, and as we have seen in the previous post you can
use jQuery UI to enhance the Web Determination, why can’t you
have a live substitution when the user enters a key piece
of information?

And so it begins. Let’s think about the challenge. Before we
dive into details, I am not a programmer, so the code I am
about to work through is probably inefficient and clunky. And
I know myself that mixing Apache Velocity and jQuery is messy
and confusing, and I should have make use of Velocity’s
ability to include files in other files using the #parse
directive.

Anyway let us think about the problem. In the screenshot
above, the first question is the important one – what is the
customer’s name. All the other questions should update when
the name is entered. If no name is entered, then the labels
should not be updated. And finally, if you update the Name
but change your mind and enter another Name, then of course
the labels should change again.

And finally, this should be robust enough that it can cope
with the second or the third question, not the first, being
the important one. And it must cope with different questions
and different entities.

At first glance the idea is apparently simple. For example,
use a Regular Expression to replace the baseline text “the
customer” with the Name entered by the user. For example
something like:

var exp = /( + "the customer" + )+/g;

Or you could even just use a simple text search and replace, assuming you have the current label stored in a variable :

var mysubstitute = "the customer";
var fieldvalue = //whatever the user has entered
var newlabel = currentlabel.replace(mysubstitute, 
fieldvalue);

And that would work fine. But it will only work once. For
example, the user changes the Name to Bob. The text gets
updated to “Bob’s Order Number” and so on. Then the user goes
back and changes it to “Steve”. Our replace is still looking
for “the customer” so the replace will not replace anything
as “the customer” does not exist as a substring of the label
any more.

So we have identified two issues. One, when the interview
starts, we need to know what the “baseline” text is – “the
customer” in this case. We can safely use that for the first
Name update. Then, we need to save the new Name “Bob”
somewhere and if the user changes the name again, “Bob” needs
to be our substring to substitute. And we need to save the
new Name “Steve”. And so on.

If the user does not enter any Name (so the text box remains
empty) then it should not result in “the customer’s Order
Number” becoming “‘s Order Number” – their should only be a
substitution when there is something in the text box. And if they have entered a Name but have now deleted it, it should revert to the baseline text.

To achieve something like this we need several steps. We must
identify

  • The Attribute that is the Master Key for our magic.
    In our case it would be the Name Attribute. When the Name
    changes, so should our labels.
  • The Substitution Baseline. When the user enters a Name for
    the first time, what text should be replaced? In our case
    “the customer” should be replaced. So the customer’s Order
    Number should become Bob’s Order Number.

We could expose these pieces of informtion from Policy Modelling to the Browser through Custom Properties. One for
the Screen to identify the Substitution Baseline, and another
on the Control to identify the Substitution Key.

OPA - Custom Screen Property for Substitution Baseline

OPA - Custom Control Property to Indentify Substitution Key

Then we need to consider how to store the new Name (“Bob”) as
the Substitution Baseline. So that if the Name is changed to
“Steve”, we replace “Bob” our new Baseline with “Steve”, and so
on. Custom Properties are static and can be read but we
cannot use them in a dynamic fashion to hold changes in value. So we need another solution.

  • Store the current Substitution Baseline somewhere on the
    page in a hidden attribute. For example, store it using the
    “tag” attribute of Label or the Input Box. We can update it
    and access it but it is not visible. There are other ways to
    achieve the same effect in code. jQuery offers data() which would be a good fit as well.
  • The code should operate on any text question (TextInput).
    In fact the same concept could be extended to any Input Type
    with a little more work, remembering that each InputType is a separate VM file.

So how might we implement it as a sand-box learning example?

Firstly, identify the TextInputControl.vm file for your
Rulebase in the templates folder of your Release.

At the top of the file, we might enter

// Get the Baseline Substitution Text
#set($jqSubstBase = $screen.getProperty("JQSubstitute", 
"nobaseline"))
// Get the Key Question Control
#set($jKey = $control.getProperties().get("jQMaster"))

With these two pieces from Apache Velocity, we can recover
the values of the Custom Properties set in the Policy
Modeller.

Now we seek out the HTML that actually creates the Text Input
boxes:

<input type="text" id="${control.getEncodedID()}" 
tag="${jqSubstBase}" name="${control.getId()}" 
${readOnlyString} value="${control.getDisplayValue()}" 
alt="${control.getText()}" tabindex="#tabIndex()" 
size="${text-control-width}" ${styleAttribute} 
${classAttribute}>

And as shown above, we add a tag to hold the Baseline
Substitution. Note that this method will result in every Text
Input storing the current Baseline as Tag value.

Next we would write some code, in the jQuery(document).ready event of the browser to ensure that we don’t start doing anything before the page is loaded.

In pseudocode, we might

  • Check the control currently being processed to see if it
    is the Key Control
  • if the keycode = 1, then Create an event handler on this textbox for the “blur” event. When the user mouse or keyboard leave the Key Control, run this code:
    • If the Input Box is empty, do nothing
      If the Input Box is not empty, load all the question labels into an array to prepare for substituton

So far so good. The “tag” attribute or the jQuery data() sounds like a reasonable way to store the Baseline Substitution. We could also update
the “tag” with the new Name. But what happens if there has
been a name, say “Steve”, and then the user deletes the Name
from the Text Input. We would want to revert to the baseline,
and again not find ourselves with “‘s Order Number”. If we
have already overwritten the “tag” then we would no longer
have the original Baseline Substitution.

So perhaps we will do it in two parts – when we load the
page, the Input Box will receive the “tag” of the original
Custom Property. If we have updated the Name, we will keep
this “tag” and use the Label instead. Or we will use data() to store old values and work with the new ones.

  • If the Input Box has a tag but the Label does not, then it is
    the first edit of the Name.
  • If the Input Box has a tag and we have a record of the previous data entry it is not the first edit.
  • If the Input Box is emptied by the user, switch to the Baseline text to restore the text to it’s original wording.

Phew – what else?

Aside from the above, we will use jQuery to do the legwork of
actually getting the text strings and updating the Labels and
tags, with code like:

jQuery(this).text(newlabel); //update the Label
jQuery($this).attr('tag', fieldvalue); // update a Tag

We can also use Velocity to help us. Given that this code
will run in the Velocity template called TextInputControl, we
will need to identify which control we are dealing with (if
we have 5 controls for example).

var fv = jQuery("#${control.getEncodedID()}").val();

For clarity in the above example and to avoid conflict you
will notice jQuery (not $) as Velocity uses $ as you can see
in the control.getEncodedID() statement.

Thanks to the the Custom Property we created earlier to
identify the Key Field, it will be easier to create an event
handler on the important Input Box (in our case, the Name)
and not on the other Input Boxes.

// Control Custom Property to identify the Key  Field
 #set($jqkey= $control.getProperties().get("jQMaster"))
 var myjqflag = "${jqkey}";

// The Custom Property example uses 2 values "1" for the Key Field and "0" for the others

 if (myjqflag == "1") 
{ jQuery("#${control.getEncodedID()}").blur(function (e) {...} 
}

So now we are able to detect the change to the Key Field, and
to manage the different cases (first change, further change,
empty Input Box). Different tools will help us in managing
the different scenarios.

jQuery(".question > label").each(function () {}

In a lot of cases we will need to iterate explicitly through
multiple labels, so we might use the different class names of Policy Automation HTML Pages and perform a nested selection like the one above, to go through each Label

Like I said I definitely am little more than an interested
amateur when it comes to programming, but the examples above
will hopefully give you the right impression – it is easy to
build for one rulebase (since much of your logic can be hard
coded) but it is much harder if you are trying to design a
bullet-proof version that will work in any Screen with any Entity.

If you are interested in the code (at your own risk) you will
find it in the OPA Extras section of your Profile Page.

In the meantime, have a look at the end result in all it’s
glory. [Edit – the video now has audio]

Policy Automation – Value Selections and jQuery

Value Selections and jQuery

A question that often comes up during the Oracle Policy Automation Essentials I and II   training perhaps en route to certification,  concerns the limitations of the Web Determination user interface. In fact many questions come up. The entire standard Web Determination user interface is driven by Apache Velocity. The front page of the Apache Velocity project describes it thus

“Velocity is a Java-based template engine. It permits anyone to use a simple yet powerful template language to reference objects defined in Java code.

When Velocity is used for web development, Web designers can work in parallel with Java programmers to develop web sites …

Well, to put it simply, the pages you see in the Web Determinations are generated from templates (with the file extension VM) that you can find in a standard deployment of a rulebase in the templates folder, unsurprisingly. Here is an extract from one of the standard Templates.

 #if( $control.isReadOnly() )
 #set( $readOnlyString = "readonly" )
 #else
 #set( $readOnlyString = "" )
 #end
 #parse( "investigation/input-style-overrides.vm" )
<div class="question">#parse("investigation/identifier-text.vm")<label for="${control.getEncodedID()}">#parse("investigation/control-text.vm")</label></div>
 <div class="info">
 #if($control.isMandatory() == "true" || $control.isMandatory() == "True")
<span class="mandatory">${mandatory-text}</span> 
#end
&nbsp;

Siebelites and other coders  will see the familiar pattern of HTML “<div>” and application “#parse” and “#if” that is reminiscent of the Web Templates we are used to handling for example in a Siebel project, but other Enterprise Applications use similar patterns to generate standard pages of output via templating.

The basic UI of Web Determinations is pretty, well, basic. The interface is static and rather plain, and almost all data controls are presented as text controls, even dates and numbers.

OPA - Boring Web Interface

 

Of course you can configure high-level visual elements to some degree using the different application properties files which we have covered in our popular blog, and these should be our first port of call, since they permit improvement without any coding or customization.

OPA - Less Boring Web Interface

Even with these changes however, the Web Determinations UI remains a rather plain Web 1.0 world. If you look at the example screenshot above, most of the changes (colors, images, logo text, links) have been achieved without any coding – for example using the appearances.properties file or the messages.properties files for your chosen locale.

OPA - Appearance Properties

OPA - Messages Properties

But looking more closely in the myriad template files we come across a very happy line :-

OPA - jQueryThe sign that jQuery is hanging out in the template files provides us with a new and effective way to improve them. For example, the standard date displays in the Web Determination do not offer the possibility to “choose” a date. The standard and familiar jQuery UI date picker makes things easier for the user even if this requires careful handling if your Web Determination is used in multiple locales. Three lines of <script> and <link> to link to the files and stylesheet, one line to instance the .datepicker and we are done.

 $(function() {
 $( "#date-${control.getEncodedID()}" ).datepicker({
 showOn: "both",
 buttonImage: "http://yourserver.com/calendar.gif",
 buttonImageOnly: true, dateFormat:"dd/mm/yy"
 });

OPA - jQuery Date Picker

We can even go so far as to implement some of the useful features found for example in the Siebel Open UI framework (which itself massively leverages jQuery). This will prove beneficial in the case of an integration between Siebel Open UI and OPA, as the two interfaces may appear together in the same CRM application and the OPA Web Determination will frankly look very ugly in comparison. Another example concerns the dropdown list of options used in the second image above.

Again, leveraging the autocomplete functionality in a combobox is achieved in just a few lines of code. For the sake of maintenance, these lines of code can be placed in files independent of the main templates. Aside from the habitual <script> and <link> tags to reference the necessary javascript files and stylesheet, the effect shown in the image below can be achieved in the following lines.

<script>
jQuery("#${control.getEncodedID()}").combobox(); // Velocity call
//for the correct ID wrapped by jQuery UI combobox call
</script>

The result is much nicer for the end users.

OPA - Combobox Typeahead3

 

 

 

Until next time, have fun!

 

 

Policy Automation – Required *

In Policy Automation, just like our old friend Siebel Enterprise, required base Attributes are highlighted to the user in the form of an asterisk, thus:-

Policy Automation - OPA Required Attribute Asterisk

You will notice that the Policy Automation asterisk is rather small. In fact, it is easy enough to not see it at all. So the question often comes up, how can we rectify this. There are three ways to approach this problem. All will require modification of files used in the Release folder of the Policy Automation Rulebase.

Option One – change the text used for all controls in all situations. Edit the messages.XX.properties files (where XX is the locale you are concerned with in your situation).

Policy Automation - OPA Release Folder Messages File Location

There is a reference in this file as follows, concerning the display of the asterisk. Mandatory text is defined as per the last entry in the section shown below.

Policy Automation - OPA Messages File Mandatory Text Example

So the text can be changed in this file. Upon running the interview again, we can obtain an improved version in this way.

Policy Automation - OPA Required Attribute Improved Version A

The text can include any of the defined authorized HTML tags such as B, I and so on for added formatting. The color of the text is defined in the appearances.properties file, under the heading mandatory-marker-text-color.

However, this solution changes the text for all controls. Suppose you wished to only change it for text controls, or boolean controls and so on?

Option Two therefore is to edit the corresponding VM file from the WEB-INF/classes/templates/controls folder. For example in the following image, the relevant code is highlighted before modification.

Policy Automation - OPA Editing Control VM file for Mandatory Text

Editing the text in the SPAN class=mandatory allows us to change the effect, in this case for a Text Input Control. A demonstration of the effect is below. In the screenshot below, the Boolean Input Control VM file has been modified. The Text Input Control VM file has been left unchanged.

Policy Automation - OPA Required Attribute Changed for Boolean Control

Finally, what if the custom effect is only to be used in certain circumstances? For example, enable the rule designer to optionally use this on certain boolean attributes but not others, in which case the normal asterisk should be shown.

Option Three – To create such an effect (and indeed, a similar technique can be used for many different reasons) requires two steps.  Firstly create a Custom Property within the Rulebase Project for the relevant Object type, in this case Control:

Policy Automation - OPA Create Custom Control Property

Secondly, within the VM template file of the relevant Control, edit in a similar way to the following. In the first part of the file, include a statement such as the example below, in order to get the value of the Custom Property and store it in a variable.

Policy Automation - OPA Boolean Control VM with added Property GetIn the same file, add conditional logic to use the desired text effect when the variable is True or False. The code below is for educational purposes only.

Policy Automation - OPA Custom Boolean Entry VM with Conditional DisplayIn this final case, the developer of the Rulebase can select to use the custom effect just by editing the Custom Property value for the desired control in the relevant Screen, as in the example shown here.

Policy Automation - OPA Custom Property in Screen Editor

So the resulting output looks like this, for False and True values respectively for the Custom Property – which can be managed, moving forward, by the Rulebase designer as needed. No further file modifications are needed to handle the conditional application of our effect.

Policy Automation - OPA Custom Property set to False for Control in Screen Policy Automation - OPA Custom Property set to True for Control in ScreenUntil next time.

 

 

 

 

Worldwide
Logo by Southpaw Projects LLC