Originally written Written By: David E. Jones, jonesde@ofbiz.org
Warning |
---|
This is deprecated since revisions 1360689 and 1361073 in trunk and r1361651 in R12.04. Older releases continue to use the previous version here documented. |
Info |
---|
The new documentation is at Mini Language - minilang - simple-method - Reference. There is still no documentation for Map processor though, the one below can be used |
...
Table of Contents
- Introduction
- The Simple Map Processor Mini-Language
- Simple Map Processor Overview
- Make In String Operations
- Process Field Operations
- Simple Map Processors Example
- The Simple Method Mini-Language
- Simple Method Overview
- Special Context Access Syntax
- Call Operations
- Java Call Operations
- Control and Error Handling Operations
- Event Specific Operations
- Service Specific Operations
- Method Environment Operations
- Entity Engine Misc. Operations
- Entity Engine Find Operations
- Entity Engine Value Operations
- Entity Engine List Operations
- Entity Engine Transaction Operations
- Conditional (If) Operations
- Other Operations
- Simple Methods Example
...
Anchor | ||||
---|---|---|---|---|
|
...
The Mini-Language concept in Open For Business is similar to the Gang of Four Interpreter pattern, or the Mark Grand Little Language pattern. This is also the central theme of the Building Parsers with Java book by Steven John Metsker which the OFBiz Rule Engine is based on. The idea is to create simple languages that simplify complex or frequently performed tasks.
...
Often this idea is implemented using a free form (BNF) or english-like syntax. In Open For Business the Mini-Languages are expressed as XML files to simplify the learning and manipulation of the syntax, in addition to making the Mini-Languages easier to write and extend.unmigrated-wiki-markup
The XML schema (XSD) for the simple-map-processor and simple-method XML files is in the distribution in *framework/minilang/dtd/simple-methods.xsd* or on the website at \[<span style="color: #ff0000"><strong>to be modified</strong></span> [http://docs.ofbiz.org/pages/]\]. These are combined into a single file to make it easy to use inlined . These are combined into a single file to make it easy to use inlined simple-map-processors inside a simple-method.
To specify the XMLschema for a simple-methods or simple-map-processors XML file use the following:
Note that the simple-method.xsd file is also available at http://ofbiz.apache.org/dtds/simple-methods.xsd .
To specify the XML schema for a simple-methods or simple-map-processors XML file use the following:
Code Block |
---|
Code Block |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="[to be modified www.ofbizhttp://ofbiz.apache.org/dtds/simple-methods.xsd]"> |
Anchor | ||||
---|---|---|---|---|
|
- Simple Map Processor Overview
- Make In String Operations
- Process Field Operations
- Simple Map Processors Example
...
Anchor | ||||
---|---|---|---|---|
|
The Simple Map Processor Mini-Language performes performs two primary tasks: validation and conversion. It does this in a context of moving values from one Map to another. The input map will commonly contain Strings, but can contain other object types like Integer, Long, Float, Double, java.sql.Date, Time, and Timestamp.
Panel | ||
---|---|---|
NOTE: The reference information for the simple-map-processor has been moved to annotations in |
We hope to recommended soon a tool that will use XSL/Transform to render the documentation directly from the XSD file in Browsers
...
file. The idea is to now to use an XML completion tool in development. If you are interested by this issue take a look at https://issues.apache.org/jira/browse/OFBIZ-571 As static documentation you may find a simple-methods.html generated file in attachments. This file may be out of date but with the attached simple-methods.xsl file you are able to generate an updated file. In such case please feel free to put a comment below in order to let us know, thanks. |
Anchor | ||||
---|---|---|---|---|
|
Note that fail-message is used here for the purpose of demonstration but in general it's better to use fail-property because fail-message is not localisable
Code Block |
---|
<simple-map-processors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/simple-methods.xsd">
<simple-map-processor name="update">
<make-in-string field="estimatedStartDate">
<in-field field="estimatedStartYear"><constant>-</constant>
<in-field field="estimatedStartMonth"><constant>-</constant>
|
...
Code Block |
---|
<simple-map-processors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="[to be modified www.ofbiz.org/dtds/simple-methods.xsd]"> <simple-map-processor name="update"> <make-in-string field="estimatedStartDate"> <in-field field="estimatedStartYear"><constant>-</constant> <in-field field="estimatedStartMonth"><constant>-</constant> <in-field field="estimatedStartDay"><constant>T</constant> <in-field field="estimatedStartHour"><constant>:</constant> <in-field field="estimatedStartMinute"><constant>:</constant> <in-field field="estimatedStartSecond"> </make-in-string> <process field="workEffortId"><copy replace="false"/></process> <process field="scopeEnumId"><copy/></process> <process field="currentStatusId"> <copy/> <not-empty> <fail-message message="Status is missing."/> </not-empty> </process> <process field="priority"> <convert type="Long"> <fail-message message="Priority is not a valid whole number."/> </convert> </process> <process field="estimatedStartDate"> <compare-field operator="less" field="estimatedCompletionDate" type="Timestamp" format="yyyy-MM-dd'T'HH:mm:ss" <!-- Note that fail-message is used here for the purpose of demonstration but in general it's better to use fail-property because fail-message is not localisable --> <fail-message message="EstimatedStatus Startis date/time must be BEFORE End date/time."/> </compare-field> <convert type="Timestamp" format="yyyy-MM-dd'T'HH:mm:ss"> <fail-message message="Estimated Start Date is not a valid Date-Time."/missing."/> <!-- Note that fail-message is used here for the purpose of demonstration; but in general it's better to use fail-property because fail-message is not localisable --> </convert>not-empty> </process> <process field="estimatedCompletionDatepriority"> <convert type="TimestampLong"> <fail-message message="Estimated Completion DatePriority is not a valid whole Date-Timenumber."/> </convert> </process> <process field="estimatedMilliSecondsestimatedStartDate"> <convert type="Double<compare-field operator="less" field="estimatedCompletionDate" type="Timestamp" format="yyyy-MM-dd'T'HH:mm:ss"> <fail-message message="Estimated Milli-seconds is not a valid number Start date/time must be BEFORE End date/time."/> </convert>compare-field> </process> </simple-map-processor> <simple-map-processor name="delete"> <process field="workEffortId"> <copy/> <not-empty> <convert type="Timestamp" format="yyyy-MM-dd'T'HH:mm:ss"> <fail-message message="Estimated Start Date is not a valid Date-Time."/> </convert> </process> <process field="estimatedCompletionDate"> <convert type="Timestamp"> <fail-message message="WorkEstimated EffortCompletion IDDate is missing not a valid Date-Time."/> </not-empty>convert> </process> </ <process field="estimatedMilliSeconds"> <convert type="Double"> <fail-message message="Estimated Milli-seconds is not a valid number."/> </convert> </process> </simple-map-processor> </simple <simple-map-processors> |
The Simple Method Mini-Language
processor name="delete">
<process field="workEffortId">
<copy/>
<not-empty>
<fail-message message="Work Effort ID is missing."/>
</not-empty>
</process>
</simple-map-processor>
</simple-map-processors>
|
The Simple Method Mini-Language
- Simple Method Overview
- Special Context
- Simple Method Overview
- Special Context Access Syntax
- Call Operations
- Java Call Operations
- Control and Error Handling Operations
- Event Specific Operations
- Service Specific Operations
- Method Environment Operations
- Entity Engine Misc. Operations
- Entity Engine Find Operations
- Entity Engine Value Operations
- Entity Engine List Operations
- Entity Engine Transaction Operations
- Conditional (If) Operations
- Other Operations
- Simple Methods Example
...
Simple Method Overview
Anchor | ||||
---|---|---|---|---|
|
The Simple Method Mini-Language is a simple way to implement an event that is invoked by the Control Servlet or a service that is invoked by the Service Engine. A Simple Method can be invoked through the static methods on the SimpleMethod class, or as an event through an entry in the controller configuration XML file like the following:
Code Block |
---|
<event type="simple" path="org/ofbiz/commonapp/workeffort/workeffort/WorkEffortSimpleEvents.xml" invoke="update"/>
|
or as a service through an entry in a services.xml file like the following:
Code Block |
---|
<service name="createPartyRole" engine="simple" location="org/ofbiz/commonapp/party/party/PartyRoleServices.xml" invoke="createPartyRole" auth="true">
<description>Create a Party Role (add a Role to a Party)</description>
<attribute name="partyId" type="String" mode="IN" optional="true"/>
<attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
</service>
|
The path or location for a Simple Method is the classpath and filename of the XML file.
In this Mini-Language you can invoke Simple Map Processors, Services and bsh scripts, perform entity related operations, and create messages to return to the caller. Specific operations can be enclosed in if blocks to execute conditionally and values or fields can be copied around in the maps, lists and method environment.
There are a number of tags which can be used to get and set attributes to/from a request or session object when called as an event or to set attributes in the result when called as a service. These operations are only applied when applicable. In other words if you include an env-to-request operation it will only be invoked when the simple-method is called as an event and an env-to-result operation will only be invoked when the simple-method is called as a service. Everything else is the same when called as an event or a service which makes it easy to write flexible logic that can be mounted/applied in various ways.
There are a number of objects that exist in the method environment when a simple-method starts or that are used as it executes to keep track of certain information. Some will exist when called as an event or a service, these are marked in the XSD. Each name can be overridden using an attribute on the simple-method tag. The defaults are listed below in the XSD.
Panel | ||
---|---|---|
NOTE: The reference information for simple-method has been moved to annotations in |
...
file. The idea is to now to use an XML completion tool in development. If you are interested by this issue take a look at https://issues.apache.org/jira/browse/OFBIZ-571 As static documentation you may find a simple-methods.html generated file in attachments with reference information. This file may be out of date but with the also attached simple-methods.xsl file you are able to generate an updated file. In such case please feel free to put a comment below in order to let us know about that, thanks. |
Special Context Access Syntax
In strings and field names a special syntax is supported to flexibly access Map member, List elements and to insert environment values into string constants.
The ${} (dollar-sign-curly-brace) syntax can be used to insert an environment variable value in pretty much any string constant in a simple-method file. Not only can it be used to reference top-level envrionment environment variables, the syntax elements described below can be used to access values in sub-structures.
You can should use the "." (dot) syntax to access Map members (the old map/field syntax is deprecated since 2009). For example if you specify the attribute field-name="product.productName" it will reference the productName member of the productMap. This would be the same as specifying map-name="product" field-name="productName". Note that this is, of course, more flexible than a field-name/map -name combination because the Map structure can be multiple levels deep. For example if you have use the attributefield-nameused the attribute field="products.widget.productName" it will reference the productName in the widget Map which is in the products Map.unmigrated-wiki-markup
The "\[\]" (square-brace) syntax can be used to access list elements. For example you can specify the attribute field-name="products\[0\].productName"and it will reference the productName of the first (position zero) element in the products List. To make this more useful you can pull a list index from the environment using something like field-name="products\[$\{currentIndex\}\].productName".unmigrated-wiki-markup
There are two extensions to the \ [\] syntax that can be used when refering referring to an environment location that is the target of an operation. If you do not include a number between the square braces the value will be put at the end of the list. If you put a "+" (plus sign) in front of the number between the square braces (ie: \ [+2\]) it will insert the value before that position in the list instead of replacing the value at that location. For example, specifying \ [+0\] would insert the value at the beginning of the list.unmigrated-wiki-markup
In fact, you can use the $\{\} syntax to substitute any string or other value at any location in a field -name or other string constant. So, you could even reference a Map member named in some other environment variable. For example you could use field-name="products\[$\{currentIndex\}\].productName".
Okay, enough of the general stuff, you may find in the XSD file descriptions of the available operations. Here is simply a categorized list of them.
...
Call Operations
call-map-processor
set-service-fields
call-service
call-service-asynch
script
call-bsh
call-simple-method
...
Java Call Operations
create-object
call-object-method
call-class-method
...
Control and Error Handling Operations
check-errors
add-error
return
...
Event Specific Operations
field-to-request
field-to-session
request-to-field
request-parameters-to-list
session-to-field
webapp-property-to-field
Service Specific Operations
field-to-result
...
Method Environment Operations
map-to-map
field-to-list
list-to-list
order-map-list (not documented in XSD yet)
set (not documented in XSD yet)
string-append (not documented in XSD yet)
string-to-list (not documented in XSD yet)
to-string
clear-field
unmigratedfirst-wikifrom-markuplist
*\[All operations in red below have been be replaced by the set operation\] *
field-to-field (deprecated, do not use anymore)
env-to-env (deprecated, do not use anymore)
env-to-field (deprecated, do not use anymore)
field-to-env (deprecated, do not use anymore)
string-to-field (deprecated, do not use anymore)
...
Control Operations
iterate
iterate-map
loop
first-from-list
...
Entity Engine Misc. Operations
now-timestamp-to-env
now-date-to-env
sequenced-id
make-tonext-seq-envid
set-current-user-login entity-data
Entity Engine Find Operations
find-by-primary-key
find-by-and
entity-one
entity-and
entity-condition
entity-count
get-related-one
get-related
order-value-list
filter-list-by-and
filter-list-by-date
Entity Engine Value Operations
make-value
clone-value
create-value
store-value
refresh-value
remove-value
remove-related
remove-by-and
The remove-by-and tag uses the delegator to remove entity values from the datasource and is constrained by anding the fields passed in the map. Make sure the map contains something, or all values will be removed.
Attribute Name | Required? | Description |
---|---|---|
entity-name | Y | The name of the entity to remove instances of. |
map-name | Y | The name of a map in the method environment that will be used for the entity fields. |
clear-cache-line
Uses the delegator to clear elements from the cache; intelligently looks at the map passed to see if it is a byPrimaryKey, and byAnd, or an all.
Attribute Name | Required? | Description |
---|---|---|
entity-name | Y | The name of the entity to clear cache lines of. |
map-name | Y | The name of a map in the method environment that will be used for the entity fields. If the fields in the map form the full primary key the entry will be removed from the byPrimaryKey cache. If the map exists but the fields do not include a full primary key the entry will be removed from the byAnd cache. If no map-name is specified the entry will be removed from the all cache. |
clear-entity-caches
This is a very simple tag that should be used sparingly because of the performance impact. It clears all lines from all Entity Engine caches. It has no attributes or sub-elements.
set-pk-fields
Looks for each PK field in the named map and if it exists there it will copy it into the named value object.
Attribute Name | Required? | Description |
---|---|---|
value-name | Y | The name of the method environment field that contains the GenericValue object. |
map-name | Y | The name of a map in the method environment that will be used for the entity fields. |
set-if-null | N | Specifies whether or not to set fields that are null or empty. Defaults to true. |
set-nonpk-fields
Looks for each non-PK field in the named map and if it exists there it will copy it into the named value object.
Attribute Name | Required? | Description |
---|---|---|
value-name | Y | The name of the method environment field that contains the GenericValue object. |
map-name | Y | The name of a map in the method environment that will be used for the entity fields. |
set-if-null | N | Specifies whether or not to set fields that are null or empty. Defaults to true. |
Entity Engine List Operations
store-list
The store-list tag uses the delegator to store all entity values in the list. This is different than storing a single value in that values in the list will be inserted if it does not exist or updated if it does exist.
Attribute Name | Required? | Description |
---|---|---|
list-name | Y | The name of the method environment field that contains the list of GenericValue objects. |
remove-list
The remove-list tag uses the delegator to remove all entity values in the list. For each value in the list if it is a primary key just that entity instance will be removed, but if it is not a full primary key all entity instances will be removed from the datasource that match the constraint of the field map.
Attribute Name | Required? | Description |
---|---|---|
list-name | Y | The name of the method environment field that contains the list of GenericValue objects. |
Entity Engine Transaction Operations
transaction-begin
The transaction-begin tag will begin a transaction if one is not already in place. If a transaction is begun the environment field named as the began-transaction-name will be set to true, otherwise it will be set to false.
Note that unless the simple-method is flagged to not use a transaction all simple-methods will be inside a transaction. The same is true for service calls through the Service Engine.
Attribute Name | Required? | Description |
---|---|---|
began-transaction-name | N | The name of the method environment field that contains a Boolean specifying whether or not a transaction was begun in the current transaction demarcation. Defaults to "beganTransaction". |
transaction-commit
The transaction-commit tag will commit a transaction if a transaction was begun in the current demarcation context as represented by the environment field named as the began-transaction-name. If the Boolean in that field is false no commit will be done.
Attribute Name | Required? | Description |
---|---|---|
began-transaction-name | N | The name of the method environment field that contains a Boolean specifying whether or not a transaction was begun in the current transaction demarcation. Defaults to "beganTransaction". |
transaction-rollback
The transaction-rollback tag will rollback a transaction if a transaction was begun in the current demarcation context as represented by the environment field named as the began-transaction-name. If the Boolean in that field is false a set rollback only will operation will be done instead of rollback which will force the transaction to rollback regardless of which method or object is responsible for beginning and ending the transaction.
Attribute Name | Required? | Description |
---|---|---|
began-transaction-name | N | The name of the method environment field that contains a Boolean specifying whether or not a transaction was begun in the current transaction demarcation. Defaults to "beganTransaction". |
Conditional (If) Operations
if
The if operation offers a flexible way of specifying combinations of conditions, alternate conditions, and operations to run on true evaluation of the conditions or to run otherwise.
The other if operations are meant for a specific, simple condition when used outside of the condition sub-element of this operation. The attributes of the other if operations are the same when used inside this operation. In this case they are empty tags and do not have any sub-elements because the operations to run are under the then or else tags.
Sub-Element Name | How Many | Description |
condition | 1 | A simple element with no attributes that contains the condition that will be evaluated to determine which sub-operations to execute. To combine the other if operations documented below the and, or, xor, and notelements can be used. The and, or, and xor elements can contain as many general if operations and modifier/combination elements (ie and, or, xor, and not). |
then | 1 | The then element is used to contain operations that will run if the condition evaluate to true. A then tag must be included, but can be empty. |
else-if | 0 to many | The else-if element can be used to specify alternate conditional execution blocks. Each else-if element must contain two sub-elements: condition and then. These operations are used the same as the condition and then elements describes above. If the condition of the parent if element is evaluated to false, each condition of the else-if sub-elements will be evaluated, and the operations under the then element corresponding first condition that evaluates to true will be run. |
else | 0 or 1 | The else element can be used to contain operations that will run if the condition evaluates to false, and if no else-ifsub-conditions evaluate to true. It can contain any simple-method operation. The else tag must be placed as the last tag under the if tag. |
if-validate-method
The operations contained by the if-validate-method tag will only be executed if the validate method returns true. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
map-name | N | The name of the method environment field that contains the map that the field to be validated will come from. If not specified the field-name will be treated as a method environment field name (an env-name). |
field-name | Y | The name of the map field that will be validated. |
method | Y | The name of the method that will be called to validate the field. It must be a static method that takes a single String parameter and return a boolean. |
class | N | The name of the class that contains the validation method. If not specified defaults to "org.ofbiz.base.util.UtilValidate". |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
if-compare
The operations contained by the if-compare tag will only be executed if the comparison returns true. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
map-name | N | The name of the method environment field that contains the map that the field to be validated will come from. If not specified the field-name will be treated as a method environment field name (an env-name). |
field-name | Y | The name of the map field that will be compared. |
operator | Y | Specified the comparison operator must be one of the following: less, greater, less-equals, greater-equals, equals, not-equals, or contains. |
value | Y | The value that the field will compared to. Must be a String, but can be converted to other types. |
type | N | The data type to use for the comparison. Must be one of the following: String, Double, Float, Long, Integer, Date, Time, or Timestamp. If no type is specified the default will be String. |
format | N | A format specifier to use when converting String objects to other data types, mainly Date, Time and Timestamp. |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
if-compare-field
The operations contained by the if-compare-field tag will only be executed if the comparison returns true. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
map-name | N | The name of the method environment field that contains the map that the field to be validated will come from. If not specified the field-name will be treated as a method environment field name (an env-name). |
field-name | Y | The name of the map field that will be compared. |
operator | Y | Specified the comparison operator must be one of the following: less, greater, less-equals, greater-equals, equals, not-equals, or contains. |
to-map-name | N | The name of the method environment field that contains the map that the field to be compared will come from. If left empty will default to the method environment. It does not default to the map-name because that would make it impossible to compare a map field to an environment field. |
to-field-name | N | The name of the to-map field that the main field will be compared to. If left empty will default to the field-name. |
type | N | The data type to use for the comparison. Must be one of the following: String, Double, Float, Long, Integer, Date, Time, or Timestamp. If no type is specified the default will be String. |
format | N | A format specifier to use when converting String objects to other data types, mainly Date, Time and Timestamp. |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
if-regexp
The operations contained by the if-regexp tag will only be executed if the value complies with the regular expression. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
map-name | N | The name of the method environment field that contains the map that the field to be validated will come from. If not specified the field-name will be treated as a method environment field name (an env-name). |
field-name | Y | The name of the map field that will be compared. |
expr | Y | A regular expression that the map value must comply with. |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
if-empty
The operations contained by the if-empty tag will only be executed if the map field is empty. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
map-name | N | The name of the method environment field that contains the map that the field to be validated will come from. If not specified the field-name will be treated as a method environment field name (an env-name). |
field-name | Y | The name of the map field that will be compared. |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
if-not-empty
The operations contained by the if-not-empty tag will only be executed if the map field is not empty. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
map-name | N | The name of the method environment field that contains the map that the field to be validated will come from. If not specified the field-name will be treated as a method environment field name (an env-name). |
field-name | Y | The name of the map field that will be compared. |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
if-has-permission
The operations contained by the if-has-permission tag will only be executed if the user has the specified permission, and optionally the action. This tag can contain any of the simple-method operations, including the conditional/if operations.
Attribute Name | Required? | Description |
permission | Y | The name of the permission in the database. The user must belong to a security group that has this permission. |
action | N | If an action is specified the user can have one of two permissions: the permission + "_ADMIN" or permission + action. Examples of actions include "_CREATE", "_VIEW", etc. |
Sub-Element Name | How Many | Description |
Any Operation | 0 to many | Any simple-method operation can be nested under an if-* tag. |
else | 0 or 1 | The else tag can be used to contain operations that will run if the condition fails, or in other words if the operations under the if tag do not run. It can contain any simple-method operation. The else tag must be placed as the last tag under the if-* tag. |
check-permission
The check-permission tag checks to see if the current user has the specified permission. The the user does not have the specified permission or there is no user associated with the context then the failure message from fail-message or file-property will be added to the specified error list.
Attribute Name | Required? | Description |
permission | Y | The name of the permission in the database. The user must belong to a security group that has this permission. |
action | N | If an action is specified the user can have one of two permissions: the permission + "_ADMIN" or permission + action. Examples of actions include "_CREATE", "_VIEW", etc. |
error-list-name | N | The name of a list in the method environment that the error messages will be added to. Will be created if does not exist. Defaults to "error_list". |
Sub-Element Name | How Many | Description |
alt-permission | 0 to many | Allows you to specify alternate permissions, any of which will satisfy this check permission. If the current userLogin does not have any of these permissions the error will be added to the list. Has two attributes: permission and action that behave just as the corresponding attributes described above for the check-permission element. |
fail-message | one | An inline failure message. |
fail-property | one | A failure message from a properties file. |
check-id
Wiki Markup |
---|
The check-id tag checks to see if the ID value in the given field is a valid ID string. Valid IDs can be any sequence of characters or digits but must not containt the following characters: space \[ \], doublequote \["\], single quote \['\], ampersand \[&\], question mark \[?\], less-than sign \[<\], greater-than sign \[>\]. |
Attribute Name | Required? | Description |
field-name | Y | The name of the field that contains the ID value to check. |
map-name | N | The name of the Map that contains the field. If not specified the environment will be used to find the field. |
error-list-name | N | The name of a list in the method environment that the error messages will be added to. Will be created if does not exist. Defaults to "error_list". |
Sub-Element Name | How Many | Description |
fail-message | one | An inline failure message. |
fail-property | one | A failure message from a properties file. |
Other Operations
property-to-field
The property-to-field tag puts the inlined string value in the specified field.
Attribute Name | Required? | Description |
resource | Y | The resource location of the properties file. |
property | Y | The property whose value will be put in the field. |
default | N | The default value to use if the specified property is empty. |
map-name | N | The name of the map in the method environment. If not specified the field-name will be used to get the field from the method environment. |
field-name | Y | The name (key) of the map field to use. |
log
The log tag logs a message used the OFBiz Debug class, which uses Log4J to log to the console, a file, or some other location. The message is a concatenation of the message attribute and then all of the field and string sub-element values in the order they are specified.
Attribute Name | Required? | Description |
level | Y | The logging/debug level to use. Must be one of the following: verbose | timing | info | important | warning | error | fatal | always. These are the standard OFBiz logging levels. |
message | N | A shortcut for simple messages. If used along with field and/or string sub-elements the inline string in the message will come first. |
Sub-Element Name | How Many | Description |
field | 0 to many | Inserts the value of the field into the message where specified. |
string | 0 to many | Inserts the value of the inline string into the message where specified. |
calculate
The calculate tag performs the specified calculation and puts the result in an object in the field of the specified map (see the calculate element attribute descriptions above). The type of the object can be specified with thetype attribute, but defaults to Double.
The calculate tag can contain calcop andnumber tags, and thecalcop tag can also contain these two tags to enable nested calculations.
Each calcop tag has three attributes: operator, map-name and field-name. Only the operator is required. The operator specifies the operation to perform on the given field and nested calcops and numbers. It must be one of the following: get | add | subtract | multiply | divide | negative.
Regardless of the operator the action is very similar. It translates to a formula like the following: (V1 operator V2 operator V3). In other words a final result is calculated by applying the operator to the values in the order they are specified. If a field-name (and optionally map-name) is specifies on the calcop tag that field will be used as the first value, otherwise the first nested calcop or number will be the first value.
The get operator is just an alias for add. It adds all of the values under it. Likewise the negative operator is almost an alias for subtract, with the exception that the first value is negated instead of left positive. For convenience the calculate tag itself acts like an add, in other words the calcops and numbers under it are all added together.
Attribute Name | Required? | Description |
map-name | N | The name of the map in the method environment. If not specified the field-name will be used to get the field from the method environment. |
field-name | Y | The name (key) of the map field to use. |
type | N | The object type to put into this field. Can be: Double | Float | Long | Integer. The default is Double. |
Sub-Element Name | How Many | Description |
calcop | 0 to many | This tag is used to apply an operator in the calculation. It can have calcop and number tags nested under it, making it also act like a parenthesis. It has three attributes: operator, map-name, and field-name. These are described below. |
number | 0 to many | This is used to put a numeric constant (a number) into the calculation. It has one attribute: value. This must be a properly formatted number or an error will result. |
Here is an example of an XML snippet that performs the calculation a=b+(((c+x+2)-d)/e), or in Reverse Polish Notation (a little bit closer to the resulting XML, and the notation used in the Rule Engine) a=(b,/(((c,x,2),-d),e)).
Here is the XML:
Code Block |
---|
<calculate field-name="a">
<calcop operator="get" field-name="b"/>
<calcop operator="divide">
<calcop operator="multiply">
<calcop operator="add" field-name="c">
<calcop operator="get" field-name="x"/>
<number value="2"/>
</calcop>
<calcop operator="negative" field-name="d"/>
</calcop>
<calcop operator="get" field-name="e"/>
</calcop>
</calculate>
|
Simple Methods Example
Wiki Markup |
---|
<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="\[<span style="color: #ff0000"><strong>to be modified</strong></span> [http://docs.ofbiz.org/pages/]\]"><simple-method method-name="createProduct" short-description="Create an Product">
<check-permission permission="CATALOG" action="_CREATE"><fail-message message="Security Error: to run createProduct you must have the CATALOG_CREATE or CATALOG_ADMIN permission"/></check-permission>
<check-id field-name="productId" map-name="parameters"/>
<check-errors/> |
<make-value value-name="newEntity" entity-name="Product"/>
<set-nonpk-fields map-name="parameters" value-name="newEntity"/>
<set-pk-fields map-name="parameters" value-name="newEntity"/>
<now-timestamp-to-env env-name="newEntity.lastModifiedDate"/>
<now-timestamp-to-env env-name="newEntity.createdDate"/>
<set from-field="userLogin.userLoginId" field="newEntity.lastModifiedByUserLogin"/>
<set from-field="userLogin.userLoginId" field="newEntity.createdByUserLogin"/>
<create-value value-name="newEntity"/>
Wiki Markup |
---|
<\!-\- induce keywords if autoCreateKeywords is emtpy or Y-\->
<if-empty field-name="autoCreateKeywords" map-name="newEntity">
<call-bsh><\!\[CDATA[org.ofbiz.commonapp.product.product.KeywordSearch.induceKeywords(newEntity);]\]></call-bsh>
<else>
<if-compare field-name="autoCreateKeywords" map-name="newEntity" operator="equals" value="Y">
<call-bsh><\!\[CDATA[org.ofbiz.commonapp.product.product.KeywordSearch.induceKeywords(newEntity);]\]></call-bsh>
</if-compare>
</else>
</if-empty>
</simple-method>
<simple-method event-name="create" short-description="Create Work Effort">
<call-map-processor xml-resource="org/ofbiz/commonapp/workeffort/workeffort/WorkEffortMapProcessors.xml"
processor-name="update" in-map-name="parameters" out-map-name="context"/>
<check-errors/>
<call-service service-name="createWorkEffort" in-map-name="context">
<default-message>Work Effort successfully created.</default-message>
<result-to-request result-name="workEffortId"/></service>
</simple-method>
<simple-method event-name="update" short-description="Update Work Effort">
<call-map-processor xml-resource="org/ofbiz/commonapp/workeffort/workeffort/WorkEffortMapProcessors.xml"
processor-name="update" in-map-name="parameters" out-map-name="context"/>
<check-errors/>
<call-service service-name="updateWorkEffort" in-map-name="context">
<default-message>Work Effort successfully updated.</default-message></service>
</simple-method> |
clear-cache-line
clear-entity-caches
set-pk-fields
set-nonpk-fields
Entity Engine List Operations
store-list
remove-list
Entity Engine Transaction Operations
transaction-begin
transaction-commit
transaction-rollback
Conditional (If) Operations
if
if-validate-method
if-instance-of
if-compare
if-compare-field
if-regexp
if-empty
if-not-empty
if-has-permission
check-permission
check-id
assert
while
Other Operations
property-to-field
log
calculate
set-current-user-login
set-calendar
Here is an example of an XML snippet that performs the calculation a=b+(((c+x+2)-d)/e), or in Reverse Polish Notation (a little bit closer to the resulting XML, and the notation used in the Rule Engine) a=(b,/(((c,x,2),-d),e)).
Here is the XML:
Code Block |
---|
<calculate field="a">
<calcop operator="get" field="b"/>
<calcop operator="divide">
<calcop operator="multiply">
<calcop operator="add" field="c">
<calcop operator="get" field="x"/>
<number value="2"/>
</calcop>
<calcop operator="negative" field="d"/>
</calcop>
<calcop operator="get" field="e"/>
</calcop>
</calculate>
|
...
Simple Methods Example
Note that fail-message is used here for the purpose of demonstration but in general it's better to use fail-property because fail-message is not localisable
Code Block |
---|
<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="[http://ofbiz.apache.org/dtds/simple-methods.xsd]\]">
<simple-method method-name="createProduct" short-description="Create a Product">
<check-permission permission="CATALOG" action="_CREATE">
<alt-permission permission="CATALOG_ROLE" action="_CREATE"/>
<!-- Note that fail-message is used here for the purpose of demonstration but in general it's better to use fail-property because fail-message is not localisable -->
<fail-message message="Security Error: to run createProduct you must have the CATALOG_CREATE or CATALOG_ADMIN permission, or the limited CATALOG_ROLE_CREATE permission"/>
</check-permission>
<check-errors/>
<make-value value-field="newEntity" entity-name="Product"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<set from-field="parameters.productId" field="newEntity.productId"/>
<if-empty field="newEntity.productId">
<sequenced-id sequence-name="Product" field="newEntity.productId"/>
<else>
<check-id field="newEntity.productId"/>
<check-errors/>
</else>
</if-empty>
<field-to-result field="newEntity.productId" result-name="productId"/>
<now-timestamp field="nowTimestamp"/>
<set from-field="nowTimestamp" field="newEntity.createdDate"/>
<set from-field="nowTimestamp" field="newEntity.lastModifiedDate"/>
<set from-field="userLogin.userLoginId" field="newEntity.lastModifiedByUserLogin"/>
<set from-field="userLogin.userLoginId" field="newEntity.createdByUserLogin"/>
<if-empty field="newEntity.isVariant">
<set field="newEntity.isVariant" value="N"/>
</if-empty>
<if-empty field="newEntity.isVirtual">
<set field="newEntity.isVirtual" value="N"/>
</if-empty>
<if-empty field="newEntity.billOfMaterialLevel">
<set field="newEntity.billOfMaterialLevel" value="0" type="Integer"/>
</if-empty>
<create-value value-field="newEntity"/>
<!-- if setting the primaryProductCategoryId create a member entity too -->
<!-- THIS IS REMOVED BECAUSE IT CAUSES PROBLEMS FOR WORKING ON PRODUCTION SITES
<if-not-empty field="newEntity.primaryProductCategoryId">
<make-value entity-name="ProductCategoryMember" value-field="newMember"/>
<set from-field="productId" map-name="newEntity" to-field-name="productId" to-map-name="newMember"/>
<set from-field="primaryProductCategoryId" map-name="newEntity" to-field-name="productCategoryId" to-map-name="newMember"/>
<now-timestamp field="nowStamp"/>
<set from-field="nowStamp" field="newMember.fromDate"/>
<create-value value-field="newMember"/>
</if-not-empty>
-->
<!-- if the user has the role limited position, add this product to the limit category/ies -->
<if-has-permission permission="CATALOG_ROLE" action="_CREATE">
<entity-and entity-name="ProductCategoryRole" list="productCategoryRoles" filter-by-date="true">
<field-map field-name="partyId" from-field="userLogin.partyId"/>
<field-map field-name="roleTypeId" value="LTD_ADMIN"/>
</entity-and>
<iterate entry="productCategoryRole" list="productCategoryRoles">
<!-- add this new product to the category -->
<make-value value-field="newLimitMember" entity-name="ProductCategoryMember"/>
<set from-field="newEntity.productId" field="newLimitMember.productId"/>
<set from-field="productCategoryRole.productCategoryId" field="newLimitMember.productCategoryId"/>
<set from-field="nowTimestamp" field="newLimitMember.fromDate"/>
<create-value value-field="newLimitMember"/>
</iterate>
</if-has-permission>
</simple-method>
<simple-method method-name="createWorkEffort" short-description="Create Work Effort">
<make-value value-field="newEntity" entity-name="WorkEffort"/>
<if-empty field="parameters.workEffortId">
<sequenced-id sequence-name="WorkEffort" field="newEntity.workEffortId"/>
<else>
<set field="newEntity.workEffortId" from-field="parameters.workEffortId"/>
</else>
</if-empty>
<field-to-result field="newEntity.workEffortId" result-name="workEffortId"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<now-timestamp field="nowTimestamp"/>
<set from-field="nowTimestamp" field="newEntity.lastStatusUpdate"/>
<set from-field="nowTimestamp" field="newEntity.lastModifiedDate"/>
<set from-field="nowTimestamp" field="newEntity.createdDate"/>
<set field="newEntity.revisionNumber" value="1" type="Long"/>
<set from-field="userLogin.userLoginId" field="newEntity.lastModifiedByUserLogin"/>
<set from-field="userLogin.userLoginId" field="newEntity.createdByUserLogin"/>
<create-value value-field="newEntity"/>
<!-- create new status entry, and set lastStatusUpdate date -->
<make-value value-field="newWorkEffortStatus" entity-name="WorkEffortStatus"/>
<set from-field="newEntity.workEffortId" field="newWorkEffortStatus.workEffortId"/>
<set from-field="newEntity.currentStatusId" field="newWorkEffortStatus.statusId"/>
<set from-field="nowTimestamp" field="newWorkEffortStatus.statusDatetime"/>
<set from-field="userLogin.userLoginId" field="newWorkEffortStatus.setByUserLogin"/>
<create-value value-field="newWorkEffortStatus"/>
<!-- Attach the workeffort to a requirement if passed -->
<if-not-empty field="parameters.requirementId">
<make-value value-field="workFullfillment" entity-name="WorkRequirementFulfillment"/>
<set from-field="newEntity.workEffortId" field="workFullfillment.workEffortId"/>
<set from-field="parameters.requirementId" field="workFullfillment.requirementId"/>
<create-value value-field="workFullfillment"/>
</if-not-empty>
<!-- attach to a customer request if passed and copy attached docs -->
<if-not-empty field="parameters.custRequestId">
<!-- check status of customer request if valid -->
<entity-one entity-name="CustRequest" value-field="lookedUpValue"/>
<set field="goodStatusId" value="CRQ_ACCEPTED"/>
<if-compare-field operator="not-equals" field="lookedUpValue.statusId" to-field="goodStatusId" >
<set field="entity" value="Customer request"/>
<add-error><fail-property resource="CommonUiLabels" property="CommonErrorStatusNotValid"/></add-error>
<check-errors/>
</if-compare-field>
<!-- create customer request / work effort relation -->
<make-value value-field="custRequestWorkEffort" entity-name="CustRequestWorkEffort"/>
<set field="custRequestWorkEffort.workEffortId" from-field="newEntity.workEffortId" />
<set field="custRequestWorkEffort.custRequestId" from-field="parameters.custRequestId"/>
<create-value value-field="custRequestWorkEffort"/>
<!-- update status of customer request -->
<set field="updCustReq.custRequestId" from-field="parameters.custRequestId"/>
<set field="updCustReq.statusId" value="CRQ_REVIEWED"/>
<call-service service-name="setCustRequestStatus" in-map-name="updCustReq"/>
<entity-and list="custRequestContents" entity-name="CustRequestContent">
<field-map field-name="custRequestId" from-field="parameters.custRequestId"/>
</entity-and>
<iterate entry="custRequestContent" list="custRequestContents">
<set field="newWorkEffortContent.workEffortId" from-field="newEntity.workEffortId"/>
<set field="newWorkEffortContent.contentId" from-field="custRequestContent.contentId"/>
<set field="newWorkEffortContent.workEffortContentTypeId" value="SUPPORTING_MEDIA"/>
<call-service service-name="createWorkEffortContent" in-map-name="newWorkEffortContent"/>
</iterate>
</if-not-empty>
</simple-method>
<simple-method method-name="updateWorkEffort" short-description="Update Work Effort">
<!-- check permissions before moving on: if update or delete logged in user must be associated OR have the corresponding UPDATE or DELETE permissions -->
<!-- temporarily commented out, because users assigned to a project or phase should
have the capability to modify status on sub-tasks, right? Hmmmm.... -->
<!-- <set from-field="workEffortId" map-name="parameters" to-map-name="findWepaMap"/>
<set from-field="partyId" map-name="userLogin" to-map-name="findWepaMap"/>
<find-by-and entity-name="WorkEffortPartyAssignment" map="findWepaMap" list="wepaList"/>
<if-empty field="wepaList">
<check-permission permission="WORKEFFORTMGR" action="_UPDATE">
<fail-message message="Security Error: to run updateWorkEffort you must have the WORKEFFORTMGR_UPDATE or WORKEFFORTMGR_ADMIN permission"/>
</check-permission>
<check-errors/>
</if-empty>-->
<entity-one entity-name="WorkEffort" value-field="lookedUpValue"/>
<clone-value value-field="lookedUpValue" new-value-field="savedValue"/>
<now-timestamp field="nowTimestamp"/>
<!-- if necessary create new status entry, and set lastStatusUpdate date -->
<if>
<condition>
<and>
<not><if-empty field="parameters.currentStatusId"/></not>
<if-compare-field field="parameters.currentStatusId" to-field="lookedUpValue.currentStatusId" operator="not-equals"/>
</and>
</condition>
<then>
<if-not-empty field="lookedUpValue.currentStatusId">
<!-- check if the status change is a valid change -->
<entity-and entity-name="StatusValidChange" list="validChange">
<field-map field-name="statusId" from-field="lookedUpValue.currentStatusId"/>
<field-map field-name="statusIdTo" from-field="parameters.currentStatusId"/>
</entity-and>
<if-empty field="validChange">
<add-error>
<fail-message message="The status change from ${lookedUpValue.currentStatusId} to ${parameters.currentStatusId} is not a valid change"/>
</add-error>
<log level="error" message="The status change from ${lookedUpValue.currentStatusId} to ${parameters.currentStatusId} is not a valid change"/>
<check-errors/>
</if-empty>
</if-not-empty>
<set from-field="nowTimestamp" field="lookedUpValue.lastStatusUpdate"/>
<make-value value-field="newWorkEffortStatus" entity-name="WorkEffortStatus"/>
<set from-field="lookedUpValue.workEffortId" field="newWorkEffortStatus.workEffortId"/>
<set from-field="parameters.currentStatusId" field="newWorkEffortStatus.statusId"/>
<set from-field="parameters.reason" field="newWorkEffortStatus.reason"/>
<set from-field="nowTimestamp" field="newWorkEffortStatus.statusDatetime"/>
<set from-field="userLogin.userLoginId" field="newWorkEffortStatus.setByUserLogin"/>
<create-value value-field="newWorkEffortStatus"/>
</then>
</if>
<!-- after checking status change, set all parameters -->
<set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
<!-- only save if something has changed -->
<if-compare-field field="lookedUpValue" to-field="savedValue" operator="not-equals" type="Object">
<!-- only set lastModifiedDate after comparing new & old to see if anything has changed -->
<set from-field="nowTimestamp" field="lookedUpValue.lastModifiedDate"/>
<set from-field="userLogin.userLoginId" field="lookedUpValue.lastModifiedByUserLogin"/>
<if-not-empty field="lookedUpValue.revisionNumber">
<set field="lookedUpValue.revisionNumber" value="${lookedUpValue.revisionNumber + 1}" type="Long"/>
<else>
<set field="lookedUpValue.revisionNumber" value="1" type="Long"/>
</else>
</if-not-empty>
<store-value value-field="lookedUpValue"/>
</if-compare-field>
</simple-method>
</simple-methods>
|
...