The following guide is intended for programmers tasked with extending the rules catalog for Composable Architecture Platform.
The Composable Architecture Platform is specifically designed to be extended with relative ease and even includes the ability to seamlessly adapt the documentation to match the installed extensions. New rules added via extensions are automatically available in the rules editor and are automatically deployed to the target X Engine alongside any dependent artifacts (such as their own additional libraries). Rules can leverage the Composable Architecture Platform framework for database access, file management, credentials, logging and much more.
Over the years, Composable Architecture Platform users have built custom extension for everything from manipulating data to accessing complex data services. Many of those extensions have been donated back to the community and are now fully supported by TomorrowX. If you write an extension that you believe other users may benefit from, then we encourage you to contact us with a request to include it in the base product. The benefit to you is that TomorrowX will ensure future support of the extension throughout new releases.
Coding for the Composable Architecture Platform X Engine requires the understanding of a number of concepts exposed by the framework. We will cover the key concepts in this section.
Within each new extension you can have one or more rules. Rules are the building blocks of any Composable Architecture Platform configuration.
Every rule within Composable Architecture Platform has a lifecycle. The lifecycle consists of an initialization phase, an execution phase and a clean-up phase. It is important that new resources used by each rule are properly allocated and subsequently cleaned up to avoid memory and resource leaks.
As part of understanding the rule lifecycle, it is important to know that only one instance of any given rule is created at any one time. This means that class variables are shared across threads and static class variables are shared across all instances of the same rule. For this reason, care must be taken to ensure the thread safety of each rule.
Whilst each rule has a single-entry point, you can have multiple exit points. These are known as chain points. Some rules allow for additional chain points to be added by the user as well. It is the responsibility of the rule programmer to determine which chain points the rule enters.
Note that there is a lot of framework logic around each chain event. It is possible for a rule further down the chain to terminate any further chain point processing (Set Completed). Chain points are also set to automatically collect performance statistics.
Some rules rely on external resources (such as data files). Rules that are able to dynamically load these resources should be "change aware". The rules framework provides a notification method to alert rules that a file has changed and should be reloaded.
Data moves through the X Engine on the back of a Variable Attribute Object (VAO). For each request to the X Engine, a VAO is created and handed to the first rule in the rule set. Each rule can add, alter and remove variables and objects to/from the VAO. The VAO also, in some instances, can contain an alternative data wrapper that provides a binding to the original request object. For example, for HTTP based rules, the data wrapper will contain an object with the application server's request and response objects as well as the filter chain.
At the X Engine level, the framework maintains variables that are shared between all threads and rule set instances. These are referred to as Global variables and can be obtained through the X Engine interface.
Input adaptors are the glue between the data being intercepted by the X Engine and the rules themselves. It is the job of the input adaptor to break the data into VAOs and hand them to the X Engine as such. This normally means converting any part of the data into Strings that are useful for the rule writer. New Input adaptors can be installed via extensions the same way as rules.
Each extension has the ability to incorporate JAR files and other specific classes that may be required to run a particular rule. It is important to understand that the X Engine is loading classes outside the scope of any application or process that it is protecting. Hence you cannot load classes from the application, and the application cannot load classes from the X Engine. This approach was implemented to protect the application from accidental conflicts with different versions of JAR files that may be used by either the X Engine or the application.
Composable Architecture Platform is designed to be backwards compatible with JDK 6.0 or later. For that reason, we recommend that you attempt to follow the same approach. This will ensure that your rule will be able to be redistributed to other Composable Architecture Platform users. If, however you are building a rule for internal use only, and you know for sure which JDK version you will be using, you can make your own compatibility choices.
We will now proceed to create a basic new rule using the development environment that we set up in the precious section.
Right click your package and select New->Class..:
Complete the entries as shown and click Finish. You now have a new class that looks as follows:
We are going to use this skeleton to create our new rule. The rule we are going to create will determine if the value of a given variable is above or below a certain threshold.
We are going to need two input fields: the variable, and the threshold; and three chain points: Above, Equal and Below.
The first thing we need is a placeholder for our input fields:
We will store the initialization parameters in these variables. Please note that you should refrain from using static variables within the rules. Static variables will be shared across ALL instances of the rule within the running rule sets. Class variables, on the other hand, remain linked to every single instance and stay valid for the duration of the running of the rules. This means that items such as counters can be created as instance variables (provided access to the variable is properly synchronized).
Next we quickly remove the TODO tag from the cleanup() method. Our cleanup method in this instance does nothing:
If, however, we had allocated resources (for example a TCP/IP socket, a Thread or some other resource that isn't subject to garbage collection), then this is the place to clean it up. It is important to notice that the cleanup() method should never throw an exception. All possible exceptions should be caught and handled with the cleanup method itself.
The initialize method is called when the rule is loaded from within a rule set. It is also called when a rule set is validated.
The primary goal of the initialize method is to read and validate rule parameters. Here is the simplest form of reading a variable name:
In the above code, we read the variable name set in the rule set. We then make sure it isn't null (rule definition incorrectly configured), and that it isn't blank (we always need a variable to test for this rule to make sense). If either of error occurs, we send an error back to the X Engine with the setError method. The setError method takes two parameters: an error code identifier, and an array of strings to insert into the error message to help with diagnostics. The "BASE003" error code identifier is defined in the Base Rules errors.properties
file. It is defined as follows:
The &1 and &2 replacement variables are predefined as the rule's label and the rule set's file name respectively. All other &x instances are replaced with the Strings from the errorInfo array passed to the setError method in the order they appear. So &3 will be errorInfo[0], &4 will be errorInfo[1] and so forth.
You can create your own error code identifiers and include them in your extension. We will do this next for the threshold value.
The threshold value is different to the variable name in that it can take a number of different forms. It can be a variable (from which we must read the content at run time) or it can be a constant. What we do know for sure, is that it can't be blank, null or a String. So, we will test accordingly:
The getValueType() method used here will tell you if any given parameter passed to a rule is either a variable (VAR_VARIABLE), number (VAR_NUMBER) or a quoted string (VAR_STRING). The resulting error message will be defined later as follows:
ABRL001=The threshold &3 set on rule &1 in rule set &2 is invalid. It must be a number or a variable
For our quick sample this is all that is required, but we will quickly cover a few other examples.
If you are planning on allocating resources in this method, then it is important to only do so in a live setting. You can determine if the call is a live setting by using the following code snippet (taken for a rule that accesses a database table):
If your rule were attempting to access a database table, part of the validation before the rule is allowed to run would be to check if that table exists. The following example shows the code required to perform this task using the X Engine database connectivity framework:
The above example shows the basic concept of obtaining a database connection based on a database name, checking the existence of a table in that database, and acting upon the returned information.
Notice that from within the rules you do not need to worry about schemas or database definitions, you are only dealing with databases and tables.
Of vital importance is how exceptions are handled and the integrity of the connection pool.
The example illustrates how an exception is caught and not only sent to the user via the console (setError), but also logged into the logging system of the user's choice (log). Significant exceptions should always be logged this way, whereas user resolvable problems shouldn't be logged.
You should also notice the return of the obtained connection to the connection pool. This step should never be missed.
We will now take the example one step further and include the creation of a table. The following example is from the History Recorder rule:
The important lessons from the above code are the mapping of BIGINT and LONGVARCHAR, as well as the handling of the statements used.
BIGINT is intended as a mapping for the Java "long" integer type. Many databases will handle long as a BIGINT, but some databases (for example Oracle) require it to be called NUMBER. So, to make the rule code as portable as possible between databases, the console allows you to configure the preferred data type for each database driver.
LONGVARCHAR is similar in that not all databases support the LONGVARCHAR data type. So once again, it can be replaced with the largest string possible (for example VARCHAR(32767) or some other maximum value for the database in use).
Finally, we need to point out that ad-hoc statements such as executeUpdate only have a place in the initialize method where the re-use factor is almost non-existent. For all runtime use, prepared statements should be used. We will cover this in the next section.
The processRule method is where all of the action happens. Reverting to our basic sample, what we need to do is obtain the value of the variable and the value of the threshold, and then compare them. We subsequently take a chain point action depending on the result.
The first step is to make the skeleton code a little more meaningful by naming the inherited arguments a little better:
The next step is to obtain the values. We will limit the rules to integers only, so we can use the following code for the variable value:
Notice the use of setWarning on the exception. In this case the message in errors.properties is defined as:
ABRL002=WARNING: The value "&4" contained in the variable &3 on rule &1 in rule set &2 is invalid. It must be a valid integer.
The difference between setError and setWarning in the processRule method is that setError results in the termination of the rule set flow, whereas setWarning allows the rules to continue running.
We will now obtain the threshold to compare against. The following code is used:
It is fundamentally the same as the variable value, except that we are not told whether the threshold parameter contains a variable or a constant. The getRuntimeValue method solves this problem for us by detecting the correct data type and returning the appropriate value for us as a simple String.
Now that we have all the relevant data, we can proceed to the logic of our rule. It looks as follows:
We essentially establish which chain point to follow and then return the value of the call to that chain point, to the calling rule. If you choose not to chain anywhere, you can simply return the vao variable instead. Alternatively, you can chain down all chain points of a rule using the chainAll method:
Our rule now compiles and is ready to be included in an extension.
Each extension contains not just the rule code, but also a manifest defining the rule parameters, a list of error messages, icon images and documentation. In this section we cover how to properly package a rule into an extension.
Note that each extension can contain more than one rule and, in most circumstances, do.
The basic file structure of an extension looks as follows:
Start by creating an empty folder called "My Rules" with the classes, doc, images and lib folders inside it.
The doc folder is used for rules documentation and the images folder is used for icons for the rules editor.
The classes and lib folder respectively are no different to the corresponding web app folders and probably need little explanation. We will now package up our sample rule into a jar file and place it in the lib folder.
In Eclipse, right click the package rule.sample.tomorrow.com and select Export. You will be presented with the Export wizard. Select Java->JAR file as shown:
Click on Next >
Check that the export contains the package (and the package only), then key in your export destination and click on Finish.
You will get an export confirmation and you are done. We can now move on to defining the rules manifest.
Note: When selecting a name for your JAR file, take care to ensure that it is unlikely to already exist in another extension. We suggest using your company name (or some other unique identifier) in the name itself.
The manifest is designed as a piece of XML. It describes each rule, it's properties and its chain points.
We will now create the rules manifest from within Eclipse. Right click the "src" folder and select New->Other and then expand the XML folder:
Select XML and click Next >
Name the XML file rules.xml and click Finish:
You will now have a basic XML file:
To create the root element for the rules catalogue, right click the ?=? xml element and select Add After->New Element:
Name the new element "rulesCatalogue" and click OK. Your document now looks like this:
We now need to add a child element for the rule. Right click the rulesCatalogue and select Add Child->New Element:
The element name must be "rule". Enter that and click on OK.
Each rule has a number of attributes that must be defined at the element level. You will need to enter them one by one, by selecting the "rule" element and then Add Attribute->New Attribute. The following shows the first attribute to add:
Proceed to add all of the following attributes:
These attributes provide a name that will be used for the rule in the rules editor (Threshold comparer), the class that contains the rule, an image to use for the rule in the editor (in this case we are re-using the "?" image used for the conditions rule), instructions for the rules editor about whether or not new chain points can be added to the rule by the user, a short note that explains the purpose of the rule (this note shows up in the rules editor and is also the default help instruction for a rule where no documentation has been created) and finally it defines the group where the rule can be found in the rules editor (this group name can be anything, but using an existing meaningful group is recommended).
Rule attributes in this context refer to child elements named "attribute". These elements are in fact the individual parameters being passed to each rule on initialization. We are going to start by adding our variable name:
Right click the rule element and select Add Child->New Element..:
Name the new element "attribute" and click on OK.
Proceed to add new attributes to the attribute element. You are going to need to add the following:
Then add another child to the rule and complete it as follows:
This provides all of the input parameters we need.
Note: You may find it quicker to edit the XML directly. We are providing the IDE method here for clarity.
Chain points must be defined as rule child elements as well. The following shows the required chain points:
The complete XML looks like this:
Save the rules.xml file, right click it and select Export.. Select the File System as the destination:
Save it to the My Rules folder:
Our rules manifest is now complete.
The next step is to create the file that contains our custom error messages. This file must be named "errors.properties". From within Eclipse, select the src folder, right click and select New..->Other..:
Select "Untitled Text File" and click on Finish:
You will have a new untitled text file. Simply key in the following:
Then click Ctrl+S. You will be asked for a location and a name. Select the src folder and the name "errors.properties":
Once again, export the file to the "My Rules" folder (like we did with the "rules.xml" file).
We have now done enough work to actually test the extension. The first step is to zip it up so that it can be installed in the console. The way this is done is very important. If you include the wrong path in the zip structure, then the extension will fail to work. Generally, in most zip programs (WinZip, 7Zip) you simply right click the extension folder and click "Add to xxx.zip":
You should now return to the Composable Architecture Platform console and log in with administrative credentials. Then select Extensions in the Administration section:
You can now upload your new extension:
You will see your extension in the list, and you can select it to see the included rules:
You should now open the rules editor. You can either create a new rule set or simply edit an existing one. When you do, the new rules show up in the Conditions folder:
You can now drag it onto the canvas to see the properties:
From here you can proceed to create a basic example, deploy it and test that the rule works as intended. We will not cover that portion here as it is adequately covered in the main manual.
The images folder is used for icons that appear in the rules editor, in the rules tree, and in the top left corner of each rule. These icons must be 16x16 pixel transparent GIF images, and for each icon there needs to be a corresponding highlight icon. The highlight icon is the icon that appears when the user hovers their mouse over the icon. The base icon can have whatever name is suitable and likely to be unused. The highlight icon must be named the same as the icon but preceded by the text "hi_". For example, if there is an icon named "database.gif" then there must also be an icon named "hi_database.gif".
Every new rule should have proper documentation. Although not a requirement to make a rule work, it will greatly help future users of the rule, and also completes the integration with the rules editor and the rules reference.
The documentation system relies on a template Microsoft Word document, saved as a "Filtered Web Page". The easiest way to get started is to copy an existing example document from the Base Rules extension. The included example is the Alias rule. The Alias source document can be found in the Base Rules doc folder with the name "software.tomorrow.rules.rules.Alias.docx". Copy the file into your own doc folder and rename it so that it matches your package and rule name. For our example, it means renaming it to "software.tomorrow.rules.sample.AboveBelowRule.docx".
Open the document in Microsoft Word:
You are seeing the basic structure of a Rules Reference help item. All rules should have the heading, Group, Extension and Since version completed.
They should also contain a basic snapshot of the rule, a short description, a snapshot of the properties, and then some more extensive help information.
So, our resulting document looks something like this:
Make sure you save the document in its ordinary format (Ctrl-S).
It is now time to save the documented rule as HTML so that it can be used by both the rules editor, and the rules reference builder. The outcome of this step is critical, so make sure you pay attention to every detail.
The first step is to select "Save As..":
You will see the save dialog. Select "Web Page, Filtered" as the target:
Click on Save. You now have properly formatted documentation. You will need to repackage your extension ZIP file and re-install it to have the rule included in the rules reference.
If your rule requires data files (for example a CSV file or an HTML page), it must notify the X Engine about files it requires and also implement the FileMonitorCallback interface. The first notification should happen during the initialization phase of the rule using the following method call:
You must provide a full path to the file. Subsequently, whenever the file is modified, the rule will receive a callback to allow it to update any internally cached information based on that file. The callback is performed by the following method:
In addition, the rule must implement a method for deployment verification. This method is:
It must return a list of the file names the rule depends on, to allow the deployment engine to determine which rules to deploy.
The following code snippet shows how this method can be implemented:
As a large number of extensions deal with the need for accessing HTTP sites and services, the X Engine runtime (from version 8 and up) includes a helper class that greatly simplifies the task of dealing with that protocol.
The helper class automatically deals with self-signed certificates, proxy configuration and authentication schemes.
The helper class acts like a full featured browser, carrying forward elements such as cookies and providing simple interfaces for using the default HTTP protocol methods (GET, PUT, POST, PATCH and DELETE).
The following code snippet provides a simple sample on how to use this class:
The following shows the key methods available for the HttpBrowser class:
At times there may be tasks that you wish to perform when a certain extension is installed. For example, you may wish to add new credentials to the credential vault. To do this, you need to create a class within your extension named "RulesInstaller". Which package name you use is not important as long as the name is correct. You can then proceed to access console objects as part of the extension installation and un-install. A typical RulesInstaller class looks as follows:
In this example, we will provide a new extension that allows the sending of an SMS text message using the Web-based gateway from Kapow.
The full source is provided later in this manual. In the following example we only list the parts that are relevant to this discussion as we go through what is happening in the code.
As the Kapow SMS service requires a user ID and password, we are going to obtain those from the credential vault. So, we need placeholders for them:
The next step is to declare variables to match the input properties supplied to the rule at initialization time. In this case, the input properties are as follows:
So, we declare:
Note the additional integer with the suffix “Type” declared for each property. We need this type, as an input property can either be a fixed string in quotes, or a variable name. If it is a fixed string, it can be resolved at initialization. If it is a variable, it can only be resolved at execution time.
The Kapow SMS service is accessed over HTTP using a simple GET method. The easiest way to do that is to use the HttpBrowser class as previously discussed.
If however you need to use your own HTTP client, you may need to traverse a corporate proxy server to get to the internet. To obtain the proxy information:
All of the private variables will be set up in the initialize method. This method is called whenever the rule set is first loaded. At this point we have access to all of the properties set in the rules editor, credentials, and configuration items. We must store and validate them. The following code snippet shows this process for the Kapow user ID:
This is a very simple way of obtaining the values provided via the configuration. Next, we are going to read the input properties. We only show the message property here:
There are a number of elements to highlight. The error checking simply ensures that whatever is provided is not a blank value. If it is, however, a call to the setError() method follows, providing a message ID to display to the user. Error messages are read from a properties file that must be packaged up with our extension code. In this case, the file contains the following values:
Notice the replacement text &1 and &2 in the error messages. These are automatically replaced with the rule name and rule set name when the error is displayed. Any following replacement text (&3, &4 and so on) will be replaced with elements from the errorInfo array passed to the method.
Next we use the getValueType()method to determine the type of property passed to us. The possibilities are VAR_NUMBER, VAR_STRING or VAR_VARIABLE. In this case, if we are dealing with a fixed string, we set the contents of the user variable to that string (without any surrounding quotes) using the getValueString()method. If it is not a string (a variable), then we need to determine the value at execution time.
The code basically repeats for each property until all input is validated and set into the rule.
Next the code obtains and validates the proxy configuration from the configuration. This proxy configuration will only be used to connect to Kapow via a proxy if required.
We now have all of the information we need.
The next step is to provide any code required to clean up once the rule is unloaded from the X Engine. This could involve terminating an open connection, closing a file, etc. In this case there is nothing to do, so the code looks like this:
The rule is now prepared for execution time and this method takes care of that. The most relevant parts are in the first section of the method:
Notice the method parameters. The first VariableAttributeObject contains the current data being passed to the rule. The second is the originating chain point. The most important of those is the data object named “vao”.
In the next line, we load the default chain point from the rules configuration. This rule has two chain points as shown here (OK and Failed).
In this code example we default to failed and only override it if we have a successful message transmission.
The next step is to make sure the message we are going to send to Kapow is in fact the right one. If the message was provided as a constant, we simply load it from the internal variable created during initialization. If it is a variable, we load it now.
We proceed to do this for all properties.
An alternative way to do the same thing is to use the getRuntimeValue() method as shown in the previous example. This requires less work but is also slightly slower at execution time.
Before sending anything, we check the run type of the current execution. As the code can be either run in production, or on a test server, it is important that any rule that can make updates, or send real alerts, has the ability to disable the actual sending. The flags in the rule configuration determine if the alert should be sent, so we must honor this behavior in the rule:
The flags are bit maps, hence the check in the above for the RUNTYPE_SEND_ALERTS flag (see the JavaDoc for the full list of flags). If it is determined that we should not send the alert, we output a message to the Composable Architecture Platform console instead and override the chain point to “OK”.
The code now goes ahead and uses the HttpBrowser object to send the message to Kapow.
Notice the blanket catch of exceptions and the setting of an error attribute if something unusual occurs. It is paramount the X Engine is resilient to exception and internal failures. The use of the Composable Architecture Platform logging framework is also visible from this code.
Finally, chain out to the chosen chain point and return the result of that chain to the parent rule.
Once we have completed our extension, we must define a manifest to go with it, so that the rules editor can visualize it and package it up, so the X Engine can load the code.
The manifest is designed as a piece of XML. It describes the rule, its properties, and its chain points. The following is the sample XML used for the Kapow SMS rule:
It starts by defining the rule name (as it shows up in the rules editor), the class, and whether chain points can be dynamically added (this property must match the code and should always be false for custom rules).
A note is added to describe the behavior of the rule. This note shows up in the Extension details in the rules console and also in the documentation pane in the rules editor itself.
A group is also set. This is the group where the rule can be found in the rules list tree in the rules editor.
Next, the various properties that are being set on the rule are defined (the “attribute” tags). Each defines a name (how the rule knows it), a label (how the user sees it) and a data type that can be “text” or “list”. An example of a list definition is shown below:
Note that if you need to have your rules editor in multiple languages, you must supply a manifest for each language required.
Finally, the chain points are defined. Once again it contains an internal value (name) and a label (what the user sees).
You are now ready to package up your new extension.
Create a file structure that looks as follows:
Place your manifest in the “rules.xml” file, your error message in the “error.properties” file, and your new class file in the “classes” folder. If your class needs to use any JAR files not already in other extensions, add them to the lib folder. Then zip the entire structure into a single zip file.
This new zip file is now ready to be loaded into the rules editor using the Composable Architecture Platform console. Please refer to the “Extensions” chapter in the product reference for instructions on how to accomplish this.
Before you can start creating a new rule for Composable Architecture Platform, you need a suitable development environment. The following example illustrates how to set up a rule writing environment using Eclipse. We are making the assumption that you are familiar with Eclipse. If you are using an alternative development environment, then the instructions should still be useful for setting up your own particular project.
Within Eclipse, select File->New->Project..
Select the Java Project as shown:
Click on Next >.
Name your project. For this example, we have used MyTomorrowRule:
Click on Finish. If you are not already in the Java Perspective, you will be asked if you wish to switch to it:
Click on Yes.
Your project is now visible and ready to configure:
We are now going to locate and copy the files we need for rules writing into a folder under the project. Start by signing in to the Composable Architecture Platform console as either a super user or an administrator, then click on the Base Rules extension.
You will have the option to download the extension:
Save the downloaded extension to a convenient folder and unzip it. You will see the following file structure:
Right click the lib folder and select Copy.
Return to the Eclipse project, right click it and select Paste:
All of the libraries required for basic rule writing are now within the project:
Select the entire list of libraries, then right click and select Add to Build Path:
Next, create an appropriate package for your rule:
Name the package something that is unique, and preferably matches your organization’s naming conventions. In this case we have used software.tomorrow.rules.sample:
Your project is now ready for you to begin coding.
public abstract class Rule
extends java.lang.Object
public static final int RUNTYPE_NORMAL
Bit mask for running in normal mode
See Also:
Constant Field Values
public static final int RUNTYPE_WRITE_DATA
Bit mask for allowing write of data
See Also:
Constant Field Values
public static final int RUNTYPE_SEND_ALERTS
Bit mask for allowing sending of alerts
See Also:
Constant Field Values
public static final int RUNTYPE_WRITE_CASES
Bit mask for writing cases into case managers
See Also:
Constant Field Values
public static final int RUNTYPE_DEBUG_OFF
Bit mask to disable debug messages (console alerts)
See Also:
Constant Field Values
public static final int PERFLEVEL_UNKNOWN
Performance monitoring is not set
See Also:
Constant Field Values
public static final int PERFLEVEL_TRANSACTIONS
Performance monitoring for transactions only
See Also:
Constant Field Values
public static final int PERFLEVEL_TIMING
Performance monitoring for both transactions and timing
See Also:
Constant Field Values
public static final int PERFLEVEL_URI
Performance monitoring for transactions and timing and individual URI performance
See Also:
Constant Field Values
public static final int PERFLEVEL_ALL
Performance monitoring for transactions and timing, individual URI performance and connection pools
See Also:
Constant Field Values
public static final int VAR_NUMBER
The data provided is a number
See Also:
Constant Field Values
public static final int VAR_STRING
The data provided is a string
See Also:
Constant Field Values
public static final int VAR_VARIABLE
The data provided is a variable
See Also:
Constant Field Values
public Rule()
public void setError(java.lang.String errorCode,
java.lang.String[] parms)
Record the fact that an error has occured. Setting an error causes the X Engine to abort with a runtime exception.
Parameters:
errorCode - The error code to report
parms - The parameters to inject into the error text
public java.lang.String getConfigurationSetting(java.lang.String key)
Return a configuration setting for the X Engine. This method searches the configuration setting in the order of the configuration itself, followed by the X Engine configuration file
Parameters:
key -
Returns:
The value of the configuration setting
public java.lang.String getCredentialsValue(java.lang.String key,
java.lang.String field)
Obtain the value for a given credential key and field
Parameters:
key -
field -
Returns:
Valid credential value or null if not found
public java.lang.String renderMessage(java.lang.String errorCode,
java.lang.String[] parms)
Record the fact on the console that a warning was detected. The X Engine will continue
Parameters:
errorCode - The error code to report
parms - The parameters to inject into the error text
Returns:
The rendered message
public void setWarning(java.lang.String errorCode,
java.lang.String[] parms)
Record the fact on the console that a warning was detected. The X Engine will continue
Parameters:
errorCode - The error code to report
parms - The parameters to inject into the error text
public void addMonitoredFile(java.io.File file)
Add a file to be monitored by the rule. If the file changes during the life of the rule, a notification will be sent to the rules "updateFile" method.
Parameters:
file - the file to monitor
public void removeFileMonitor()
Removes all file monitors for this rule
public int getValueType(java.lang.String value)
Detect what kind of value has been passed as a parameter. Return type are: VAR_NUMBER: The parameter is a number VAR_STRING: The parameter is a string VAR_VARIABLE: The parameter is a variable
Parameters:
value - The value to test
Returns:
The value type of a provided value parameter
public java.lang.String getValueString(java.lang.String value)
Resolve the string value type of a provided value parameter, removing any quote characters
Parameters:
value - The value to resolve
Returns:
The resolved (clean) value
public java.lang.String getRuntimeValue(software.tomorrow.rules.base.VariableAttributeObject vao,
java.lang.String value)
Resolve the runtime value of a given parameter, based on the string supplied to it
Parameters:
vao - The variable attribute object to use
value - The value to resolve
Returns:
The resolved (runtime) value
public java.lang.String getRuntimeValue(software.tomorrow.rules.base.VariableAttributeObject vao,
java.lang.String value,
int maxLength)
Resolve the runtime value of a given parameter, based on the string supplied to it
Parameters:
vao - The variable attribute object to use
value - The value to resolve
maxLength - The maximum length of the returned value
Returns:
The resolved (runtime) value
public abstract void initialize()
Initialize the internal state of the rule, based on the set properties
public abstract void cleanup()
Clean up any allocated resources before shutting down
public abstract software.tomorrow.rules.base.VariableAttributeObject processRule(software.tomorrow.rules.base.VariableAttributeObject vao,
software.tomorrow.rules.base.ChainPoint source)
throws java.lang.Throwable
Process the rule to the depth of all connected subrules. The outcome is the processed object with any new attributes and changes.
Parameters:
vao - The variable attribute object with current data
source - The originating chain point
Returns:
the processed object
Throws:
java.lang.Throwable
public software.tomorrow.rules.base.VariableAttributeObject execute(software.tomorrow.rules.base.VariableAttributeObject vao,
software.tomorrow.rules.base.ChainPoint source)
throws java.lang.Throwable
Wrap the processing of the rule and its performance testing, exception handling This method is for the X Engine only and should not be called directly
Parameters:
vao - The variable attribute object with current data
source - The originating chain point
Returns:
the processed object
Throws:
java.lang.Throwable
public void addPerformanceData(java.lang.StringBuffer data,
java.lang.String ruleSet)
Get the performance data for the currently running X Engine and add it to the provided StringBuffer as well-formed XML Note: This approach is not synchronized and can suffer from inaccuracies on a busy system
Parameters:
data - The performance data to add
ruleSet - The ID of the rule set
public java.util.Hashtable getProperties()
Get the specific properties of this rule to show for maintenance
Returns:
Hashtable with property/value value pairs as Strings
public java.util.Hashtable getRuleChainPoints()
Get a list of points into which this rule can chain
Returns:
Hashtable with point name/chain point value pair
public void setRuleChainPoint(java.lang.String chainPointId,
software.tomorrow.rules.base.ChainPoint chainPoint)
Attach a rule to a chain point
Parameters:
chainPointId - The Id of the rule to chain into
chainPoint - The name of the point to connect to
public boolean isChainPointAddAllowed()
Are new (custom) chain points allowed
Returns:
True if yes, false if no
public void materializeRule(software.tomorrow.rules.base.RuleSet ruleSet)
Prepare this rule to be executable (connect all chain points to their rules)
Parameters:
ruleSet - The originating rule set
public java.lang.String getId()
Get the ID of this rule
Returns:
Returns the id.
public void setId(java.lang.String id)
Set the ID of this rule
Parameters:
id - The id to set.
public void setProperties(java.util.Hashtable properties)
Set rule specific properties
Parameters:
properties - The properties to set.
public long getTransactions()
Get the transaction count for this rule
Returns:
Returns the transactions.
public void setTransactions(long transactions)
Set the transaction count for this rule
Parameters:
transactions - The transactions to set.
public void addTransaction()
Increment transaction count
public void addTransactionTime(long time)
Increment inline timings
public software.tomorrow.rules.base.VariableAttributeObject chainTo(java.lang.String name,
software.tomorrow.rules.base.VariableAttributeObject vao,
Rule source)
throws java.lang.Throwable
Chain through to a chain point
Parameters:
name - The name of the chain point
vao - The data packet to supply
source - The originating rule
Returns:
the data packet processed by rules further down the chain
Throws:
java.lang.Throwable
public software.tomorrow.rules.base.VariableAttributeObject chainAll(software.tomorrow.rules.base.VariableAttributeObject vao,
Rule source)
throws java.lang.Throwable
Chain through to all the chain points in sequence
Parameters:
vao - The data packet to supply
source - The originating rule
Returns:
the data packet processed by rules further down the chain
Throws:
java.lang.Throwable
public software.tomorrow.rules.base.RuleSet getRuleSet()
Get the parent rule set for this rule
Returns:
Returns the ruleSet.
public void setRuleSet(software.tomorrow.rules.base.RuleSet ruleSet)
Set the parent rule set for this rule
Parameters:
ruleSet - The ruleSet to set.
public int getRunType()
Obtain the run-type for this rule as defined by the RUNTYPE constants
Returns:
Returns the runType.
public void setRunType(int runType)
Set the run-type for this rule
Parameters:
runType - The runType to set.
public java.lang.String getLabel()
Get the text label for this rule
Returns:
Returns the label.
public void setLabel(java.lang.String label)
Set the text label for this rule
Parameters:
label - The label to set.
public void writeConsole(java.lang.String message)
Send a message to the console
Parameters:
message - Message to send
public void log(int level,
java.lang.String message,
java.lang.Throwable exception,
Rule rule,
software.tomorrow.rules.base.VariableAttributeObject vao)
Use this method to log rule exceptions to any installed LogAdapter.
Parameters:
level - The log level of the log entry as per the constants defined on this adapter
message - The message logged.
exception - Any exception caught. Can be null.
rule - Any rule that triggered the log entry. Can be null.
vao - Any data packet that caused the failure. Can be null.
public class VariableAttributeObject
extends java.lang.Object
public static final int PROCESS
The completion is for the entire process
See Also:
Constant Field Values
public static final int RULESET
The completion is for the current rule set only
See Also:
Constant Field Values
public static final int LOOP
The completion is for the current loop only
See Also:
Constant Field Values
public VariableAttributeObject()
public java.lang.String getAttribute(java.lang.String id)
Retrieve an attribute value by name. If not found, blank will be returned
Parameters:
id - The name of the attribute
Returns:
The attribute value
public java.lang.StringBuffer getLargeAttribute(java.lang.String id)
Retrieve a large attribute value by name. If not found, blank will be returned
Parameters:
id - The name of the attribute
Returns:
The attribute value
public java.lang.Object getObjectAttribute(java.lang.String id)
Retrieve an object attribute value by name. If not found, a blank string object will be returned
Parameters:
id - The name of the attribute
Returns:
The attribute value
public boolean isLargeAttribute(java.lang.String id)
Check if an attribute is large
Parameters:
id -
Returns:
true if large and stored as StringBuffer, false otherwise
public boolean isObjectAttribute(java.lang.String id)
Check if a variable is an object (not String or String Buffer)
Parameters:
id -
Returns:
true if large and stored as StringBuffer, false otherwise
public boolean hasAttribute(java.lang.String id)
Determine if a given attribute exists
Parameters:
id - The name of the attribute
Returns:
true if the attribute exists
public void setAttribute(java.lang.String id,
java.lang.String value)
Set the value of an attribute. If a banned attribute name is provided it will be ignored
Parameters:
id - The name of the attribute to set
value - The value to set
public void setLargeAttribute(java.lang.String id,
java.lang.StringBuffer value)
Set the value of an attribute. If a banned attribute name is provided it will be ignored
Parameters:
id - The name of the attribute to set
value - The value to set as a StringBuffer
public void setObjectAttribute(java.lang.String id,
java.lang.Object value)
Set the value of an attribute. If a banned attribute name is provided it will be ignored if null is provided, the attribute will be deleted
Parameters:
id - The name of the attribute to set
value - The value to set as an Object
public java.util.Enumeration getAttributeNames()
Obtain all the current attribute names
Returns:
Enumeration of attribute names
public int getAttributeCount()
Obtain a count of current attributes
Returns:
the count of attributes
public boolean isCompleted()
Returns:
Returns the completion status of the rule set.
public void setCompleted(boolean completed)
Parameters:
completed - The new completion status.
public software.tomorrow.rules.base.DataWrapper getDataWrapper()
Returns the raw data that was used as the basis for the initial variable setting
Returns:
Returns the dataWrapper.
public void setDataWrapper(software.tomorrow.rules.base.DataWrapper dataWrapper)
Set the raw data that was used as the basis for the initial variable setting
Parameters:
dataWrapper - The dataWrapper to set.
public java.lang.Throwable getException()
Get the stored exception
Returns:
Returns the exception.
public void setException(java.lang.Throwable exception)
Store an exception for later analysis
Parameters:
exception - The exception to set.
public int getCompletionScope()
Get the scope of the completion. This can either resolve to: LOOP, PROCESS or RULESET
Returns:
Returns the completionScope.
public void setCompletionScope(int completionScope)
Set the current completion scope. This can either be LOOP, PROCESS or RULESET
Parameters:
completionScope - The completionScope to set.
public boolean isRedirected()
Determine if the response from the X Engine has resulted in a redirection (for example a HTTP redirect)
Returns:
Returns the redirected.
public void setRedirected(boolean redirected)
Advise that the response from the engine is performing a redirect
Parameters:
redirected - The redirected to set.
public boolean isTrace()
Returns:
Returns the trace.
public void setTrace(boolean trace)
Parameters:
trace - The trace to set.
public java.util.Vector getTraceData()
get the full trace data vector
Returns:
The trace as a vector of Strings
public void addTraceData(java.lang.String traceData)
Add a new trace data line
Parameters:
traceData -
public boolean hasContent()
Returns:
Returns the hasContent.
public void setHasContent(boolean hasContent)
Parameters:
hasContent - The hasContent to set.
Constructor Summary |
Rule() |
Method Summary |
void | addMonitoredFile(java.io.File file) Add a file to be monitored by the rule. |
void | addPerformanceData(java.lang.StringBuffer data, java.lang.String ruleSet) Get the performance data for the currently running X Engine and add it to the provided StringBuffer as well-formed XML Note: This approach is not synchronized and can suffer from inaccuracies on a busy system |
void | addTransaction() Increment transaction count |
void | addTransactionTime(long time) Increment inline timings |
software.tomorrow.rules.base.VariableAttributeObject | chainAll(software.tomorrow.rules.base.VariableAttributeObject vao, Rule source) Chain through to all the chain points in sequence |
software.tomorrow.rules.base.VariableAttributeObject | chainTo(java.lang.String name, software.tomorrow.rules.base.VariableAttributeObject vao, Rule source) Chain through to a chain point |
abstract void | cleanup() Clean up any allocated resources before shutting down |
software.tomorrow.rules.base.VariableAttributeObject | execute(software.tomorrow.rules.base.VariableAttributeObject vao, software.tomorrow.rules.base.ChainPoint source) Wrap the processing of the rule and its performance testing, exception handling This method is for the X Engine only and should not be called directly |
java.lang.String | getConfigurationSetting(java.lang.String key) Return a configuration setting for the X Engine. |
java.lang.String | getCredentialsValue(java.lang.String key, java.lang.String field) Obtain the value for a given credential key and field |
java.lang.String | getId() Get the ID of this rule |
java.lang.String | getLabel() Get the text label for this rule |
java.util.Hashtable | getProperties() Get the specific properties of this rule to show for maintenance |
java.util.Hashtable | getRuleChainPoints() Get a list of points into which this rule can chain |
software.tomorrow.rules.base.RuleSet | getRuleSet() Get the parent rule set for this rule |
java.lang.String | getRuntimeValue(software.tomorrow.rules.base.VariableAttributeObject vao, java.lang.String value) Resolve the runtime value of a given parameter, based on the string supplied to it |
java.lang.String | getRuntimeValue(software.tomorrow.rules.base.VariableAttributeObject vao, java.lang.String value, int maxLength) Resolve the runtime value of a given parameter, based on the string supplied to it |
int | getRunType() Obtain the run-type for this rule as defined by the RUNTYPE constants |
long | getTransactions() Get the transaction count for this rule |
java.lang.String | getValueString(java.lang.String value) Resolve the string value type of a provided value parameter, removing any quote characters |
int | getValueType(java.lang.String value) Detect what kind of value has been passed as a parameter. |
abstract void | initialize() Initialize the internal state of the rule, based on the set properties |
boolean | isChainPointAddAllowed() Are new (custom) chain points allowed |
void | log(int level, java.lang.String message, java.lang.Throwable exception) Use this method to log rule exceptions to any installed LogAdapter. |
void | log(int level, java.lang.String message, java.lang.Throwable exception, Rule rule, software.tomorrow.rules.base.VariableAttributeObject vao) Use this method to log rule exceptions to any installed LogAdapter. |
void | materializeRule(software.tomorrow.rules.base.RuleSet ruleSet) Prepare this rule to be executable (connect all chain points to their rules) |
abstract software.tomorrow.rules.base.VariableAttributeObject | processRule(software.tomorrow.rules.base.VariableAttributeObject vao, software.tomorrow.rules.base.ChainPoint source) Process the rule to the depth of all connected subrules. |
void | removeFileMonitor() Removes all file monitors for this rule |
java.lang.String | renderMessage(java.lang.String errorCode, java.lang.String[] parms) Record the fact on the console that a warning was detected. |
void | setError(java.lang.String errorCode, java.lang.String[] parms) Record the fact that an error has occured. |
void | setId(java.lang.String id) Set the ID of this rule |
void | setLabel(java.lang.String label) Set the text label for this rule |
void | setProperties(java.util.Hashtable properties) Set rule specific properties |
void | setRuleChainPoint(java.lang.String chainPointId, software.tomorrow.rules.base.ChainPoint chainPoint) Attach a rule to a chain point |
void | setRuleSet(software.tomorrow.rules.base.RuleSet ruleSet) Set the parent rule set for this rule |
void | setRunType(int runType) Set the run-type for this rule |
void | setTransactions(long transactions) Set the transaction count for this rule |
void | setWarning(java.lang.String errorCode, java.lang.String[] parms) Record the fact on the console that a warning was detected. |
void | writeConsole(java.lang.String message) Send a message to the console |
Methods inherited from class java.lang.Object |
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Summary |
static int | LOOP The completion is for the current loop only |
static int | PROCESS The completion is for the entire process |
static int | RULESET The completion is for the current rule set only |
Method Summary |
void | addTraceData(java.lang.String traceData) Add a new trace data line |
java.lang.String | getAttribute(java.lang.String id) Retrieve an attribute value by name. |
int | getAttributeCount() Obtain a count of current attributes |
java.util.Enumeration | getAttributeNames() Obtain all the current attribute names |
int | getCompletionScope() Get the scope of the completion. |
software.tomorrow.rules.base.DataWrapper | getDataWrapper() Returns the raw data that was used as the basis for the initial variable setting |
java.lang.Throwable | getException() Get the stored exception |
java.lang.StringBuffer | getLargeAttribute(java.lang.String id) Retrieve a large attribute value by name. |
java.lang.Object | getObjectAttribute(java.lang.String id) Retrieve an object attribute value by name. |
java.util.Vector | getTraceData() get the full trace data vector |
boolean | hasAttribute(java.lang.String id) Determine if a given attribute exists |
boolean | hasContent() |
boolean | isCompleted() |
boolean | isLargeAttribute(java.lang.String id) Check if an attribute is large |
boolean | isObjectAttribute(java.lang.String id) Check if a variable is an object (not String or String Buffer) |
boolean | isRedirected() Determine if the response from the X Engine has resulted in a redirection (for example a HTTP redirect) |
boolean | isTrace() |
void | setAttribute(java.lang.String id, java.lang.String value) Set the value of an attribute. |
void | setCompleted(boolean completed) |
void | setCompletionScope(int completionScope) Set the current completion scope. |
void | setDataWrapper(software.tomorrow.rules.base.DataWrapper dataWrapper) Set the raw data that was used as the basis for the initial variable setting |
void | setException(java.lang.Throwable exception) Store an exception for later analysis |
void | setHasContent(boolean hasContent) |
void | setLargeAttribute(java.lang.String id, java.lang.StringBuffer value) Set the value of an attribute. |
void | setObjectAttribute(java.lang.String id, java.lang.Object value) Set the value of an attribute. |
void | setRedirected(boolean redirected) Advise that the response from the engine is performing a redirect |
void | setTrace(boolean trace) |
Methods inherited from class java.lang.Object |
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Summary |
static int | PERFLEVEL_ALL Performance monitoring for transactions and timing, individual URI performance and connection pools |
static int | PERFLEVEL_TIMING Performance monitoring for both transactions and timing |
static int | PERFLEVEL_TRANSACTIONS Performance monitoring for transactions only |
static int | PERFLEVEL_UNKNOWN Performance monitoring is not set |
static int | PERFLEVEL_URI Performance monitoring for transactions and timing and individual URI performance |
static int | RUNTYPE_DEBUG_OFF Bit mask to disable debug messages (console alerts) |
static int | RUNTYPE_NORMAL Bit mask for running in normal mode |
static int | RUNTYPE_SEND_ALERTS Bit mask for allowing sending of alerts |
static int | RUNTYPE_WRITE_CASES Bit mask for writing cases into case managers |
static int | RUNTYPE_WRITE_DATA Bit mask for allowing write of data |
static int | VAR_NUMBER The data provided is a number |
static int | VAR_STRING The data provided is a string |
static int | VAR_VARIABLE The data provided is a variable |