Welcome to the OPA Hub!


Category Archives: Tutorials

Fun with Aliases and Strings #2

Fun with Aliases and Strings #2

Returning to the ” Aliases and Strings”  theme of the previous post, where we looked into an example of String concatenation. Just a reminder, in the previous article you created the entity model and set up a couple of relationships, before using a rule to decide if the ticker tape instance is a member of a relationship called  the next ticker tapes.

So here is the continuation of the document you saw in the previous steps:

Aliases and Strings #2

The first part should look reasonably familiar, since it builds on the example with the next ticker tapes. But is uses the second relationship, called the closest ticker tape. Note the wording closest ticker tape not ticker tapes. We are aiming for the closest one, or if you prefer, the next one in line. So for ticker tape number 3, the closest would be number 4.

Dodgey Ticker

We again use an alias, but things get a bit sticky in the following parts. Where did the further ticker tape come from? Well, perhaps unsurprisingly, it’s another alias. You see, we already used the other ticker tape in the conclusion so we need to use another word : in this case further was my personal choice, but it could have been another word that meant something in this context. So by now we have the following, expressed in conversational style :

Compare ticker tape A (with other tapes, let’s say B, C and D). B,C or D will be called the closest ticker tape if the following is true.

  1. B,C or D have an ID that is higher than the ID for A
  2. Using the next ticker tapes as your starting point (so, B C and D)
  3. Compare them (so B compared to C, B compared to D etc) to this rule
  4. Is B’s ID is less than or equal to C (for example)?

So we end up with the ticker tape that is in the next ticker tapes AND has an ID that is less than or equal to the other next ticker tapes. So it is the closest one.

I’m reminded of this excellent conversation from Monty Python since it can get a bit confusing at first:

video

The final rule concerns whichever ticker tape has the longest string. And that string is what you are about to create, for each and every instance of your entity.

We’re coming with you!

You will generate a string of text for each of the entity instances (so, for each of the ticker tape instances). And this string will be the driver of a logical loop.

Firstly, let’s set your scene and remind of the context:

  1. “Text 1”
  2. “Text 2”
  3. “Text 3”

Each ticker tape has a text message, for example “Text 1” . This message should be concatenated with the other text messages to form a long “final” string. Each should have a comma inserted between them, into the final string, and of course a “.” at the end. Just to make a nice tidy “final” string. It might look like “Text 1, Text 2, Text 3.”.

Aliases and Strings #2

So each instance has a text string, and a “final text”. The “final text” will be the ticker tape text string concatenated with the closest ticker tape’s text string, plus a comma if required – for example if there are no “next ticker tapes” for a given tape, it’s because we have reached the end of the instances (number 4 , if there is no number 5).

The following attributes give us the numbers used in the table above:

Aliases and Strings #2

And the final (final) global attribute:

Final String Result

Aliases and Strings #2

In the next part of this series, there will be a chance to look back on the techniques, observe the warning message and generally investigate your logical loop.

Aliases and Strings part three will be with you in a few days, In the meantime of course you can read the online help here.

Stunning Infographics with Oracle Policy Automation and Easelly #1

Hi There!


This content is accessible only to logged in users of the OPA Hub Website.

To Register takes only 10 seconds and uses LinkedIn for authentication.

Once registered you can change your OPA Hub password and manage it independently of LinkedIn.

We recommend you keep different passwords for all your sites.

To register, click the Log in link in the menu at the top of your page.

Thanks, the OPA Hub Website.

Back to OPA Basics : Oracle Policy Modeling Features

Back to OPA Basics : Oracle Policy Modeling Features

Welcome to another in our periodic back to OPA basics series. At the moment I am watching a lot of new starters join a set of experienced developers. And funnily enough, both groups sometimes are stuck in their routine. For the new people, they fall back on what they know from other rules engines. For the more experienced people, that are familiar with Oracle Policy Modeling, they repeat what they learned long ago and do not necessarily see anything that has been added to the application in the intervening time since they first started using it.

So here are my top five cool time savers and useful things you can find in Oracle Policy Modeling today.

  • The Rule Assistant

I still find it strange that many people don’t use the Assistant in Word. If there was ever a tool to avoid having to remember the arcane spelling and phraseology of an Oracle Policy Automation attribute, this is it!

Back to OPA Basics - Rule Assistant

  • The Convert to Test Case Export

Watching people filling in every cell in their Test Case spreadsheet, when they probably have already saved many of the initial scenarios as debug sessions, I think they should remember the fact that they can move a unit test into a Test Case, and vice-versa.

Back to OPA Basics - Export as Test Case

  • The Find Unused Attribute Filter

I tend to use this one when the Rule Assistant has not been used very much, so we are looking for duplicate / mispelled attributes in our Project (see Rule Assistant, above).

Back to OPA Basics - Unused Attributes

  • The Inclusion Report

OK, so I’m probably cheating as far as this one is concerned, but it is a real time saver. In 19A, the introduction of the Inclusion Report has saved me time already. Great for beginning an impact assessment when some sort of surgery is required on Project structure. Find out more here.

Back to OPA Basics - Inclusion Report

  • The Export Entity Data Model Option

This is a tiny little option hidden away in the toolbar but I’m often asked by non-OPA people for the data model and I find this export really simple and quick to use.

Tiny Button - Export Data Model

Well, that’s our top five for now. What other tricks do you use to get the most out of Oracle Policy Modeling?

Let us know in the comments!

 

Calendar Black Out Dates with Control Extensions

Calendar Black Out Dates with Control Extensions

The OPA Hub Website is always happy to hear from readers and learn about the things they are doing and trying to do. In this case, this article was inspired by our reader AF, from Adelaide. The question was; how can we implement a calendar control, to allow the users to select a date – but the calendar control must be able to black-out certain dates (public holidays, non-work days). It’s the sort of thing we probably can all relate to.

The Calendar control that Oracle Policy Automation uses is a very standard JavaScript dropdown, but there is little in the way of configuration in respect of the dates shown. We can style the calendar and we can offer two different ways to enter dates (either as the traditional calendar or the three-fields-in-a-row style that some applications use).

So it comes down to what can be done with an Extension. Regular reader will remember that we have spoken about calendar controls before, on the subject of Year-Only Selection. So that Extension will be the basis of this article.

Firstly, what are the tools we might need?

  • jQuery
  • JQuery UI, especially datepicker

The datepicker widget from jQuery supports a variety of user-related events, including one called BeforeShowDay, which is where we can come in a specify which days should not be clickable. They remain in the calendar display of course.

The basic concept therefore, for this demonstration is:

  1. The user can select a date from the control. Certain days are not available.
  2. The control must handle both adding a date when the date is not currently entered, as well as when the date is already entered and the user wants to correct it (for example, going back to a previous screen in the interview.
  3. The date must of course be saved to our chosen attribute.

As always this is without any warranty or guarantee of fitness for purpose. It’s a quick demonstration that you can then add to and correct yourselves.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
 * Richard Napier The OPA Hub Website March 2019
 * Educational Example of Custom Date Control Extension
 * I will remember this is for demonstration purposes only
 */
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xDate") {
			return {
				mount: function (el) {
 
					var myDatePicker = document.createElement('input');
					myDatePicker.setAttribute("id", "dateselect");
					var mySessionDate = interview.getValue("dt_session");
 
 
					el.appendChild(myDatePicker);
 
 
					$('#dateselect').datepicker({
						dateFormat: "yy-mm-dd",
						onSelect: function (dateText) {
							var RecoveredDate = dateText;
 
							interview.setInputValue("dt_circ", RecoveredDate);
 
						},
						beforeShowDay: function (date) {
							var array = ["2019-03-14", "2019-03-15", "2019-03-16"]
							var string = jQuery.datepicker.formatDate('yy-mm-dd', date);
 
							return [array.indexOf(string) == -1]
						}
					});
 
					var mySelectedDate = "";
 
					if (interview.getValue("dt_circ") == null) {
 
						$('#dateselect').datepicker("setDate", mySessionDate);
						var RecoveredDate = mySessionDate;
 
						interview.setInputValue("dt_circ", RecoveredDate);
 
 
					} else {
 
						var myPreviouslySelectedDate = new
							Date(interview.getValue("dt_circ"));
 
 
						var myPreviouslySelectedDateAsDate = new
							Date(myPreviouslySelectedDate);
 
						var myDayPrefix = "";
						var myMonthPrefix = "";
						if (myPreviouslySelectedDateAsDate.getDate() < 10) {
							myDayPrefix = "0"
						}
						if (myPreviouslySelectedDateAsDate.getMonth() < 10) {
							myMonthPrefix = "0"
						}
						var myConvertedYear = myPreviouslySelectedDateAsDate.getFullYear();
						var myConvertedMonth = myPreviouslySelectedDateAsDate.getMonth() + 1;
						var myConvertedDay = myPreviouslySelectedDateAsDate.getDate();
						var myPreviouslySelectedDateOnly =
							myConvertedYear + "-" + myMonthPrefix + (myConvertedMonth) + "-" + myDayPrefix + myConvertedDay;
 
 
						mySelectedDate = myPreviouslySelectedDateOnly;
 
 
						$('#dateselect').datepicker("setDate", mySelectedDate);
 
 
						var RecoveredDate = $('#dateselect').datepicker("getDate");
 
						interview.setInputValue("dt_circ", new Date(RecoveredDate));
					}
				},
				update: function (el) {},
				unmount: function (el) {
					var RecoveredDate = $('#dateselect').datepicker("getDate");
 
					interview.setInputValue("dt_circ", new Date(RecoveredDate));
 
					var myPicker = $('#dateselect');
					myPicker.remove();
 
 
				}
			}
		}
	}
});

Calendar Black Out Dates with Control Extensions – About the Code

The first part of the Mount is basically setting up the jQuery datepicker to be able to hide some days. We also set the date format to the international YYYY-MM-DD that we all know. Of course a more sophisticated approach would check the region and apply the correct format.

Line 22 Sets up the Select Event and Line 29 the BeforeShowDay  Event.

We attempt to grab the value of our user-entered date (dt_circ) and place it in the date control. If that is unknown or null, then we will default to the current date.

When the user selects a valid date, we will of course copy it into the attribute again.
Finally, when the Unmount fires, we will clean up.

The End Result

 

In a later post we will look at using an entity to store the blackout dates. Stay tuned! For the time being the Project is in the OPA Hub Shop.

Excel as an OPA Data Connection #2

Excel as an OPA Data Connection #2

So, following on from the previous post in this ” Excel as an OPA Data Connection” series, we have been investigating using Excel as both the Metadata and Data storage for a prototype Connection. The goal being that if I want to quickly model something and show it to a prospect I can do everything in Excel, and do not need any other software.

The previous post laid out the architecture, and highlighted that we would be putting the Excel on a Web Server and using a Web Service to open and manipulate the Excel file. Once again, this is just a bit of an interesting concept and is not at all for real-life use, especially as Microsoft has explicitly stated that remote automation with Microsoft Office is not a good idea (nor is it supported).

Excel as an OPA Data Connection : Common Points

In our Web Service code, the three main endpoints (GetMetadata, Load and Save) have a great deal in common. They all manipulate either DataTables (Load and Save) or MetaTables (GetMetadata) and in the case of DataTables they have Row(s) and DataField(s) whilst the MetaTables have MetaFields.  Essentially your job is to build these into a hierarchy, and they form the response that is sent back to Oracle Policy Automation.

In the screenshot below, the Excel data range is being parsed into a series of Metafields for the GetMetadata response, and we are setting the different tags of our SOAP response. I took a shortcut in the prototype and no matter which metadata you ask for you get all the fields back in the response.

 Excel as an OPA Data Connection GetMetadata

Excel as an OPA Data Connection : Context

In the case of the Load and Save, they receive either loadrequest.context or saverequest.context which will contain any URL argument items you want to pass into the Service (for example, in a Load, you will pass an ID which will correspond to the row of data you want). You can pass in as many as you want.

In the screenshot below, you can see that both the Load and Save have the context object available. In the code, since it is a prototype, we assume the only context element is the one we are looking for.

 Excel as an OPA Data Connection Context

Excel as an OPA Data Connection : Load and Save

In the case of a Load request, you will send back the Tables and Row(s) and Fields for the Interview. In the case of a Save request, since we are only handling updates in our prototype,  we send back the Row and Fields as the response, marking them as “input” fields. We are not using Load after Submit in our case, so there are no “output” fields to send back. If we were to handle inserts, we would have to send back the Row and Fields in that case as well, plus the ID of the new record for example in a Load after Submit.

In the screenshot below I am testing the Load Response, hard coding some values into the fields. Note the “TEST” value at the top. In the finished version of course, these are replaced with Excel Cell contents.

 Excel as an OPA Data Connection Load Example

Since the entire Web Service is written in Visual Basic, it is a great learning opportunity to be able to dump the XML requests and responses to files, in order to better understand what Oracle Policy Automation is sending or receiving. In the screenshot below, a Save Request being sent to the Web Service.

 Excel as an OPA Data Connection XML Example

Excel as an OPA Data Connection : Attribute Types

One area where I got quite confused is the different ways to indicate what kind of attribute you are working with. In the request for a save, for example, there are field types for each attribute which are actually constants (0,1,2,3,4 and so on, one for each type). When building the save response I needed to then map that number to an AttributeTypeEnum (another constant value) and set the ItemElementName to get the “<date-val>” or “<text-val>” tags that you need. It took a while to work out the logic. Between MetaFields that say they are “STRING” and DataFields that say they are “text-val” it can get a bit boring!

Here’s the sort of thing I mean, checking the fieldtype and mapping to the AttributeEnumType:

Excel as an OPA Data Connection : Video

Rather than keep on writing, let’s have a video to put it all together and see the adventure in the flesh, doing what it is supposed to do!  This was great fun, and is definitely a cool way to learn more about the Connector API and what would be needed when building an integration. Of course, these days we have Integration Cloud and so many more managed tools and services but I am of the opinion that it is better to be over-informed than under-informed. Speaking of which, if you need to read the official Connector API Overview, you will find it here.

Of course there is more that could be done. As described above, the first thing will be to implement record creation. Then, perhaps, a child table or two using the same basic principle. Who knows, one day when I have more time I might come back to it.

If anyone wants the Visual Studio Project and code, then just leave a Comment. Have fun!

 

 

 

Excel as an OPA Data Connection

Excel as an OPA data Connection

In the English-speaking world there is an expression about the month of March that I like very much : “Mad march hares” (referring to those big goofy rabbits-on-steroids that start running about and looking for a partner right about now).

Well, we have been engaged in some madness here at the OPA Hub Website this week too.

It starts with a simple statement. We like to do demonstrations, and we often need a Data Connection to be able to do a proper demonstration “end to end” so to speak. And the scenario of the demonstration can change every day as we do things for different customers. So we are always looking to find ways to make it as easy as possible to do that. Let’s look at some of the options:

This feature allows us to create “fake” Connections simply by copying and pasting a template GetMetadata Response into the dialog. Nice, but this only handles the basic modelling and mapping experience. There is no data.

Readers will know that we are great fans of this product, and Mantis are also sponsoring our Website this half year (full disclosure). It should be evident from the videos we’ve done that we love it. But it requires a database, and that takes a little time to set up.

  • Excel as an OPA Data Connection

Yes, well, I will admit I was sceptical when I thought about it. But why not? The big advantages are obvious : if we have the metadata in the Excel, we can change field names and table names in 2 seconds. And creating test data is as easy as copy and paste. And you already have Excel on your machine!

Let’s think about the basic mechanics of how this works. I am afraid that this solution is easiest  to implement if you are in Private Cloud. Public Cloud is possible but it takes a bit more work. A local installation (where you have a local Virtual Machine for example) is also possible. We decided to go for the Private Cloud solution for our proof of concept. What do we need?

  • A Web Server – in our case Internet Information Server.
  • A Web Service – in our case written in Visual Basic as an old-fashioned ASMX file.
  • Microsoft Excel – accessible to the Web Server.
  • Oracle Policy Automation Hub – that can access the Web Service URL mentioned above.
  • Oracle Policy Modeling – that can access the Oracle Policy Automation Hub mentioned above.

Great Learning Opportunity

The great thing about doing something like this, however crazy, is the learning experience it gives us. If you want to get down and dirty to understand the nuances of DataTables, UpdateTables and MetaTables and all the other myriad structures in the Connection API, this is the way to get to grips with it – line by line and XML dump by XML dump.

Before going any further, yes, we know it is definitely not supported to do remote automation with Microsoft Office but this is a proof of concept! There will inevitably be some setup challenges to ensure that the Identity used by your IIS Application has also access to Excel, and you probably will spend a fair amount of time staring at DCOM error messages. We used this article as our debugging tool.

Starting Out – Getting the Stub Code

In Visual Studio, the best way to leverage the standard Connection API WSDL is to download it from your OPA Hub Connections Detail Page. Drill down on an existing Connection and find the download in the Actions menu.

Excel as an OPA Data Connection 1

Then you can use the Microsoft SD tool wsdl.exe to import a WSDL (like the one you have just downloaded) and turn it into a bit of stub code. You can generate it in Visual C# or Visual Basic, using a command line like this one:

WSDL.exe [/language:] [/protocol:] [/namespace:] [/username] [/password] [/domain] [/out:] <url or path>

Language can be VB, VC or even JS. Once you have your file generated, then you can create a new Web Service Project in Visual Studio (Community Edition or a more professional one if you have it). At this point you should have all of the standard service endpoints (CheckAlive, GetMetadata and so on) all in the code marked up as not being implemented. If you deploy your Web Service, sure you can call it with Soap UI but nothing will happen.

As you probably know, the basic set of endpoints for a useful Connection are

  • CheckAlive
  • GetMetadata
  • Load
  • Save

CheckAlive

These will be our target for the prototype. CheckAlive is super simple since it returns an empty CheckAlive response. This is the trigger for the lovely green tick mark you see in the Connections list. If the web service responds with a CheckAlive response, you get a green tick:

Excel as an OPA Data Connection 3

The code is two lines long, thanks to the stub we imported earlier.

GetMetadata

Obviously to be able to use the Connection, we need to be able to Model our data source. So the Excel spreadsheet is going to contain two tables. One for data, one for metadata. To keep things simple, the Excel spreadsheet just has two named ranges, and a place to name our object:

Excel as an OPA Data Connection

For our proof of concept, we are going to assume that the user of the Excel sheet remembers to keep the metadata and data synched (if the name of a field changes in the metadata, then the headings need to change in the data table). Not very hard to remember! The data table can contain as many rows as you want since it is just a named range.

Now that we have this structure built into the Excel, we need to implement the GetMetadata endpoint, so we can use these fields in our Modeling.

The obvious thing is to read the metadata from Excel, and then format it into a GetMetadata Response. And it works. The IIS Web Service opens Excel (!) and reads the information before formatting it and sending it back.

Excel as an OPA Data Connection 6

Since this is running from the Web Server, we can access this Connection Web Service from anywhere, and nobody would know there is an Excel spreadsheet behind it. Edit the Excel, change the field names and data, refresh the Connection and ready to go!

We’ll look at the Load and Save endpoints, as well as discussing more about the actual mechanics in the next post.

What is Happening Here – Date Function with Wrong Date

What is Happening Here – Date Function with Wrong Date

See if you can guess : What is Happening Here?

Below is a project written in Oracle Policy Automation 12 (this was actually in 12.18B but it has no bearing on the example). It has only one attribute : the date of the next visit. This is written as follows:

The date of the next visit= YearEnd (AddYears(the current date;1))

The date you are running the Debugger, the current date is November 19, 2018. The rule should perform a simple assignment, taking the current date, adding a year and then using that as the input for the YearEnd function. So :

YearEnd(November 19, 2019)

This should give the value of December 31 2019. Also, there are no other attributes in this project. There are no JavaScript extensions, no custom controls, no CSS or other additions. The project is being built using English language. The project does not have any translations, forms, or anything else inside it. But the Debugger  session of the Oracle Policy Automation Interview displays the following:

OPA 12 - What is Happening Here

The date is incorrectly showing 12/31/20. So what is happening here? Even more fun, the Data tab of the Debugger shows the following:

OPA 12 - What is Happening Here

The value is correct on the right, wrong on the left. So what has happened to the Oracle Policy Automation project in this example?

You are free to give the answer, if you know it, in the comments. I will come back in a couple of days and explain. And before you ask, yes, I can across this in the real world yesterday and it is not a bug, it did not require a Service Request, and somebody had done something. The behavior is entirely reproducible I would imagine in any language.

Sometimes you want to write about something (in my case, I wanted to look at Silent and Hidden settings) but life gets in the way. This was such an amusing thing (with hindsight) that I decided to write about it instead.

Enjoy this and hopefully you will immediately have spotted the possible culprit. You can peruse the documentation online here.

List of Values, Display Values and Translations in Oracle Policy Automation

List of Values, Display Values and Translations  in Oracle Policy Automation

A common List of Values question that comes up is the following:

“How are list of values handled in Oracle Policy Automation, when I have more than one language? What gets put into the database?”

Of course, by “database” I mean whatever platform you are using to save the response from Oracle Policy Automation  : Oracle Sales Cloud, Oracle Service Cloud, Oracle Siebel CRM, Salesforce or any other.  For the record, the exact behaviour of your Connector will depend on how it has been programmed,but if it is doing what it should be doing, then the following information will apply.

The question that comes up is actually, to be fair, usually more detailed : people want to know the behaviour of the list of values both when it is created as a Screen element (single-use) or as a Value List (multi-use) and when there is more than one language involved. Well, fear not because the video below will answer all of those questions I hope, in a friendly and easy to follow way.

Imagine you have a Project in Oracle Policy Automation that includes an attribute of type Text, with a drop-down list to display values for the user.

  • What if there are multiple languages?
  • What if you use Screen-based Values?
  • What if you add Display Values as well as Values?
  • What if you migrate to Project Value Lists?
  • What editing might you have to do in your Translation file(s)?
  • What gets into the database?

List of ValuesAll these points will be covered in the video. Hopefully there will be no surprises in the video itself,  but it will be useful to see it in action and get confirmation of what you think might happen. And as mentioned previously, a big thanks to our OPA Hub Website Sponsors Mantis Solutions, makers of the OPA DB Connector, whose assistance made this video way easier to create and much faster to implement. If you are interested in Mantis OPA DB Connector, please reach out here.

 

Until the next post, I hope you are (at least those of you in the Northern Hemisphere) all having a pleasant Summer.

Temporal Reasoning in Oracle Policy Automation #3 : Time Travel

Hi There!


This content is accessible only to logged in users of the OPA Hub Website.

To Register takes only 10 seconds and uses LinkedIn for authentication.

Once registered you can change your OPA Hub password and manage it independently of LinkedIn.

We recommend you keep different passwords for all your sites.

To register, click the Log in link in the menu at the top of your page.

Thanks, the OPA Hub Website.

What’s New in Oracle Policy Automation 18B #2 Relationship Control Extensions

What’s New in Oracle Policy Automation 18B #2

The main thrust of this post first came into my head when I was writing one of the recent Back to Basics posts about Relationships. And as if by magic, Oracle Policy Automation went ahead and improved the product with something I felt was lacking. I should ruminate more often, perhaps they have telepathic powers over there. So in this post, What’s New in Oracle Policy Automation 18B #2, we are going to look at the new feature of the Control Extensions : the ability to customise the Relationship experience.

What’s New in Oracle Policy Automation 18B #2

The relationship above is a good example. In the course of a prototype, I designed the car and the passenger entities for a car-sharing enterprise. A car can have many potential passengers. For each journey, however, your passenger can only be in one car at a time. And yes, I understand that I could build a many-to-many and intersection the car and passengers or infer the current passengers or what have you, but this is just an example.

What’s New in Oracle Policy Automation 18B #2

So in the above example, you can see that I am in the process of selecting the passengers for each car. Putting aside the discussion about how best to model the data, there is a challenge here. The checkbox (which is the only display offered) is fine, but due to the lack of dynamism (?) in the display, the choices remain static. I mean by that you are able to choose an incoherent selection, with the same passenger being in multiple cars.

Of course, when you do so, the engine (correctly) gives you an error and you must correct your data entry. But what if we did it another way?

The core of this is the fact that now, in Oracle Policy Automation 18B, you can use the following in your Extensions:

control.getControlType() – which now will return “OneToMany” or “ManyToMany” and so forth for relationship controls. So your code could adapt the User Experience based on the cardinality.

control.getOptions() – returns an array of the different choices for the user ( the passengers in my case above). So you can retrieve the list of choices.

To help manage this kind of extension, control.getValue() returns an array of the selected values for your relationship (the instances that have been selected). So you can examine the selected values.

Let’s look at this code. It is, as always provided for educational and entertainment purposes (indeed, many will find my stream of consciousness code amusing). It is also available on the OPA Hub Website Shop page as a free PDF download. So let’s see What’s New in Oracle Policy Automation 18B #2 : Relationship Controls with an example.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
(c) 2018 Richard Napier The OPA Hub Website May 2018
Educational Example of Relationship Input Controls
I will remember this is for demonstration and educational purposes only
 */
 
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xPassengerSelect") {
			return {
				mount: function (el) {
					//console.log("Control " + control.getProperty("name") + " is a " + control.getDataType() + ", originally a " + control.getControlType());
					var myValues = [];
					//Previous values
					myValues = control.getValue();
					var myOptions = control.getOptions();
					//console.log("Obtained list of instances for control " + control.id);
					var myDropDown = document.createElement('select');
					myDropDown.setAttribute('id', control.instance.toString());
					myDropDown.setAttribute('data-instance', control.instance.toString());
					myDropDown.setAttribute('data-entity', control.entity.toString());
					myDropDown.setAttribute('multiple', 'true');
					for (j = 0; j &lt; myOptions.length; j++) {
						var myoption = new Option(myOptions[j].text, myOptions[j].value)
							myoption.setAttribute("data-instance", control.instance.toString());
						myoption.setAttribute("data-entity", control.entity.toString());
						myDropDown.options.add(myoption)
						//console.log("Added list option " + myOptions[j].text);
					}
					for (i = 0; i &lt; myDropDown.length; i++) {
						currentOption = myDropDown[i];
 
						if (myValues.indexOf(currentOption.value) != -1) {
							$("select [data-instance='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("selected", "selected");
						}
 
					}
					$(myDropDown).change(function () {
 
						//New Values Selected
 
						for (i = 0; i &lt; myDropDown.length; i++) {
							currentOption = myDropDown[i];
 
							if (currentOption.selected == true) {
								myValues.push(currentOption.value);
 
								//Disable All Values Matching Selected in other instances
								$("select [data-instance!='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("disabled", "true")
 
							} 
 
						}
					});
					var deselectbutton = document.createElement("button");
					deselectbutton.setAttribute("type", "button");
					deselectbutton.setAttribute('data-instance', control.instance.toString());
					var deselectbuttontext = document.createTextNode("Deselect All");
					deselectbutton.appendChild(deselectbuttontext);
 
					el.appendChild(myDropDown);
					$(myDropDown).after(deselectbutton);
 
					$(deselectbutton).click(
 
						function () {
						$("select [data-instance='" + this.getAttribute('data-instance') + "']").filter(":selected").prop("selected", false);
						control.setValue("");
							$("select [data-instance!='" + this.getAttribute('data-instance') + "']").attr("disabled", false);
					});
 
					for (i = 0; i &lt; myDropDown.length; i++) {
						currentOption = myDropDown[i];
 
						if (myValues.indexOf(currentOption.value) != -1) {
							$("select [data-instance='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("selected", "selected")
 
						}
 
					}
				},
				update: function (el) {},
				unmount: function (el) {}
			}
		}
	}
});

So what are we looking at. There are probably four key areas in this rough prototype.

Lines 18 to 27 build a multiple-select drop-down instead of the check-boxes. Using HTML 5 data attributes, each option and each drop-down (there will be  drop-downs, one for each of the car ) is tagged with the instance name and the entity name. This is useful if you intend to have a page with lots of entity-related things on it , and it was useful in the Entity Collect example from a few weeks ago as well.

Lines  29 to 33 look through the existing values of the Control (maybe the user has already been working on this page, and has now come back to it for further editing) and selects programatically all those values that were chosen previously. Otherwise when you click the Next button and then the Previous button, you will no longer “see” your selections even though they actually have been selected.

Lines 38 to 58 handle the Change event if the user selects other items in the multi-select, and ensures that the corresponding items are deactivated in the other drop-downs.

Lines 58 to 78 create the Deselect All button for each drop-down, which removes all the selected items both from the drop-down and from the underlying control values, and re-enables the values in the other drop-downs.

Once again, I state for the record that this was just a “stream of consciousness” which became a bare-bones prototype. There are lots of holes in the code, and lots of repetition because I just wrote it in a single shot. So you have been warned.

It does, however, demonstrate the new functionality, so our post title What’s New in Oracle Policy Automation 18B #2 is fulfilled. This is something you could not really do in previous versions.


Have fun!