When investigating a goal, calling Attribute.getNextQuestion() returns a single attribute whose value is required next. However, when screens are defined in the rulebase, it is usually preferable to find a screen that collects the particular attribute and display that screen instead of the single attribute. This allows related questions to be grouped together on the same screen, and allows the appearance of the query to be specified from within Oracle Policy Modeling. For example, an attribute's value might represent a user's country of birth, and should be restricted to a specific set of values. The information about which values are acceptable is defined on a control inside a screen.
This example is an extension of the example of investigating a goal. Instead of directly asking the next question to the user, it retrieves a screen for the next question, and asks for an answer for each of the attributes that appears on the screen. In a real application the screen would probably be displayed as a window, or as a form on an HTML page, but for simplicity, this example just displays the text of each control on the screen and asks for answers if the control collects data.
Click on the appropriate link to view either the Java or the C# example:
This code is assumed to exist at the top of the Java source file:
import java.io.*;
import java.util.*;
import com.oracle.determinations.engine.*;
import com.oracle.determinations.engine.web-determinations.*;
The following shows the question search loop, modified to use screens instead of asking each question individually:
// This is where the user's input will come from:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
Engine eng = EngineFactory.localEngine();
Rulebase rb = eng.getRulebase(...);
Session sess = eng.createSession(rb, ...);
sess.setThinkMode( ThinkMode.IMMEDIATE );
EntityInstance globalEI = sess.getGlobalEntityInstance();
Entity globalEnt = globalEI.getEntity();
Attribute attr = globalEnt.getAttribute("a5");
// Repeatedly try to find an answer for the attribute
// until we run out of questions to ask the user.
Question question = attr.getNextQuestion(globalEI);
while(attr.isUnknown(globalEI))
{
// The entity instance of the question will, for all practical purposes,
// be the entity instance of the screen.
EntityInstance screenEntityInstance = question.getEntityInstance();
// Retrieve a screen that collects this particular attribute:
Screen screen = question.getScreen();
System.out.println();
System.out.println("Screen: " + screen.getTitle(screenEntityInstance));
System.out.println();
// Process every control on the screen:
List controls = screen.getControls();
Iterator iControl = controls.iterator();
while(iControl.hasNext()) {
Control currentControl = (Control)iControl.next();
displayControl(screenEntityInstance, currentControl, in); }
// Continue the question search for the required attribute: }
// Question search is over.
// See whether it was successful or not:
if(attr.isUncertain(globalEI)) {
System.out.println("Unable to find a value!"); }
else
{
String goalValue = (String) attr.getValue(globalEI);
System.out.println("The value of attribute a5 is " + goalValue); }
// The session was created as an unmanaged session, so the garbage
// collector will free the session object and related objects.
This is the implementation of the displayControl() function used in the above code.
private static void displayControl(EntityInstance controlEntityInstance,
Control currentControl,
BufferedReader inputReader)
throws java.io.IOException
{
// Controls can be hidden:
if (!currentControl.isVisible(controlEntityInstance))
{
// Control is hidden, so get out now while you can!
return;
}
// Not all controls will have a caption:
String caption = currentControl.getSubstitutedCaption(controlEntityInstance);
if (caption.length() > 0)
{
System.out.println(caption);
}
// A fixed-value control has a specific value that must always be set:
if (currentControl.getControlType() == ControlType.FIXED_VALUE)
{
FixedValueControl fixedValControl = (FixedValueControl)currentControl;
fixedValControl.getAttribute().setValue(controlEntityInstance, fixedValControl.getValueToSet());
}
// An attribute control is handled by just asking the user the answer to the question:
if (currentControl.getControlType().isAttributeControl())
{
AttributeControl attrControl = (AttributeControl)currentControl;
Attribute attr = attrControl.getAttribute();
// There are a number of sub-types of attribute control - but in this example
// we just ask for a textual response:
// If there was no caption, we still want to prompt the user for something.
// So use the question text of the attribute:
if (caption.length() == 0)
{
String questionText = attr.getSubstitutedText(controlEntityInstance, SentenceForm.QUESTION);
System.out.println(questionText);
String answer = inputReader.readLine();
// Set the answer - a blank string is considered uncertain:
if (answer.length() == 0)
{
attr.setValue(controlEntityInstance, HaleyUncertain.INSTANCE);
}
else
{
attr.setValue(controlEntityInstance, answer);
}
}
}
// Entity controls require asking the user for instances of each entity:
if (currentControl.getControlType() == ControlType.ENTITY)
{
EntityControl entityControl = (EntityControl)currentControl;
Entity collectedEntity = entityControl.getEntity();
Relationship collectedRel = entityControl.getRelationship();
// New instances need to be created on the Session object:
Session sess = controlEntityInstance.getSession();
List childTargets = new ArrayList();
// Keep prompting the user for instances of this entity until they give up:
while(true)
{
System.out.println("Enter the value for a new instance of " +
collectedRel.getName());
System.out.println("(or just press enter to finish creating instances)");
System.out.print("Value for " + collectedRel.getName() + "? ");
String definingAttrValue = inputReader.readLine();
// Set the answer - a blank string breaks the loop
if (definingAttrValue.length() == 0)
{
break;
}
// Create a new instance of the entity as requested:
EntityInstance newEntityInstance = sess.createEntityInstance(collectedEntity);
childTargets.add(newEntityInstance);
// Display each of the child controls, which will collect specific
//data about the new entity instance:
List childControls = entityControl.getControls();
Iterator iChildControl = childControls.iterator();
while(iChildControl.hasNext())
{
Control currentChildControl = (Control) iChildControl.next();
displayControl(newEntityInstance, currentChildControl, inputReader);
}
}
collectedRel.setInstance(controlEntityInstance, childTargets);
}
}
This code is assumed to exist at the top of the C# source file:
using System;
using System.IO;
using Oracle.Determinations.Engine;
using Oracle.Determinations.Engine.web-determinations;
using Oracle.Determinations.Masquerade.Util;
The following shows the question search loop, modified to use screens instead of asking each question individually:
// This is where the user's input will come from:
TextReader In = Console.In;
Engine eng = EngineFactory.LocalEngine();
Rulebase rb = eng.GetRulebase(...);
Session sess = eng.CreateSession(rb, ...);
sess.SetThinkMode(ThinkMode.IMMEDIATE);
EntityInstance globalEI = sess.GetGlobalEntityInstance();
Entity globalEnt = globalEI.GetEntity();
RBAttr attr = globalEnt.GetAttribute("a5");
// Repeatedly try to find an answer for the attribute
// until we run out of questions to ask the user.
Question question = attr.GetNextQuestion(globalEI);
while (attr.IsUnknown(globalEI))
(
// The entity instance of the question will, for all practical purposes,
// be the entity instance of the screen.
EntityInstance screenEntityInstance = question.GetEntityInstance();
// Retrieve a screen that collects this particular attribute:
Screen screen = question.GetScreen();
Console.Out.WriteLine();
Console.Out.WriteLine("Screen: " + screen.GetTitle(screenEntityInstance));
Console.Out.WriteLine();
// Process every control on the screen:
List controls = screen.GetControls();
foreach(Control currentControl in controls)
(
DisplayControl(screenEntityInstance, currentControl, In);
)
// Continue the question search for the required attribute:
)
// Question search is over.
// See whether it was successful or not:
if (attr.IsUncertain(globalEI))
(
Console.Out.WriteLine("Unable to find a value!");
)
else
(
string goalValue = (string) attr.GetValue(globalEI);
Console.Out.WriteLine("The value of attribute a5 is " + goalValue);
)
// The session was created as an unmanaged session, so the garbage
// collector will free the session object and related objects.
This is the implementation of the DisplayControl() function used in the above code:
private static void DisplayControl(EntityInstance controlEntityInstance,
Control currentControl, TextReader inputReader)
(
// Controls can be hidden:
if (!currentControl.IsVisible(controlEntityInstance))
(
// Control is hidden, so get out now while you can!
return;
)
// Not all controls will have a caption:
string caption = currentControl.GetSubstitutedCaption(controlEntityInstance);
if (caption.Length > 0)
(
Console.Out.WriteLine(caption);
)
// A fixed-value control has a specific value that must always be set:
if (currentControl.GetControlType() == ControlType.FIXED_VALUE)
(
FixedValueControl fixedValControl = currentControl as FixedValueControl;
fixedValControl.GetAttribute().SetValue(controlEntityInstance, fixedValControl.GetValueToSet());
)
// An attribute control is handled by just asking the user the answer to the question:
if (currentControl.GetControlType().IsAttributeControl())
(
AttributeControl attrControl = currentControl as AttributeControl;
RBAttr attr = attrControl.GetAttribute();
// There are a number of sub-types of attribute control - but in this example
// we just ask for a textual response:
// If there was no caption, we still want to prompt the user for something.
// So use the question text of the attribute:
if (caption.Length == 0)
(
string questionText = attr.GetSubstitutedText(controlEntityInstance, SentenceForm.QUESTION);
Console.Out.WriteLine(questionText);
string answer = inputReader.ReadLine();
// Set the answer - a blank string is considered uncertain:
if (answer.Length == 0)
(
attr.SetValue(controlEntityInstance, HaleyUncertain.INSTANCE);
)
else
(
attr.SetValue(controlEntityInstance, answer);
)
)
)
// Entity controls require asking the user for instances of each entity:
if (currentControl.GetControlType() == ControlType.ENTITY)
(
EntityControl entityControl = currentControl as EntityControl;
Entity collectedEntity = entityControl.GetEntity();
Relationship collectedRel = entityControl.GetRelationship();
// New instances need to be created on the Session object:
Session sess = controlEntityInstance.GetSession();
List childTargets = new ArrayList();
// Keep prompting the user for instances of this entity until they give up:
while (true)
(
Console.Out.WriteLine("Enter the value for a new instance of " +
collectedRel.GetName());
Console.Out.WriteLine("(or just press enter to finish creating instances)");
Console.Out.Write("Value for " + collectedRel.GetName() + "? ");
string name = inputReader.ReadLine();
// Set the answer - a blank string breaks the loop
if (name.Length == 0)
(
break;
)
// Create a new instance of the entity as requested:
EntityInstance newEntityInstance = sess.CreateEntityInstance(collectedEntity);
newEntityInstance.SetName(name);
childTargets.Add(newEntityInstance);
// Display each of the child controls, which will collect specific
//data about the new entity instance:
List childControls = entityControl.GetControls();
foreach(Control currentChildControl in childControls)
(
DisplayControl(newEntityInstance, currentChildControl, inputReader);
)
)
collectedRel.SetInstance(controlEntityInstance, childTargets);
)
)
See also: