...
Note that the simple-method.xsd file is also available at http://ofbiz.apache.org/dtds/simple-methods.xsd .
To specify the XMLschema XML schema for a simple-methods or simple-map-processors XML file use the following:
...
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> <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."/> <!-- 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="Status is missing."/> but in general it's better to use fail-property because<!-- Note that fail-message is not localisable --> </not-empty> </ used here for the purpose of demonstration; but in general it's better to use fail-property because fail-message is not localisable --> </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"> <fail-message message="Estimated Start 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."/> </convert> </process> <process field="estimatedCompletionDate"> <convert type="Timestamp"> <fail-message message="Estimated Completion Date is not a valid Date-Time."/> </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-map-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 ${} (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 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.
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". |
...
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". |
...
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
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 ana Product"> <check-permission permission="CATALOG" action="_CREATE"> <fail<alt-messagepermission messagepermission="CATALOG_ROLE"Security Error: to run createProduct you must have the CATALOG_CREATE or CATALOG_ADMIN permission 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 --> </check-permission> <check-id field-name="productId" map-name="parameters"/> <check-errors/> <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-namefield="newEntity" entity-name="Product"/> <set-nonpk-fields map-name="parameters" value-namefield="newEntity"/> <set-pk-fields mapfrom-namefield="parameters.productId" value-namefield="newEntity.productId"/> <now-timestamp-to-env env-name<if-empty field="newEntity.lastModifiedDateproductId"/> <now-timestamp-to-env env <sequenced-id sequence-name="Product" field="newEntity.createdDateproductId"/> <else> <set from-field="userLogin.userLoginId" field="newEntity.lastModifiedByUserLogin"/> <set from-field="userLogin.userLoginId"<check-id field="newEntity.createdByUserLoginproductId"/> <create-value value-name="newEntity"<check-errors/> <!-- induce keywords if autoCreateKeywords is emtpy or Y-->/else> </if-empty> <if<field-to-emptyresult field-name="autoCreateKeywordsnewEntity.productId" mapresult-name="newEntityproductId"/> <call-bsh><![CDATA[org.ofbiz.commonapp.product.product.KeywordSearch.induceKeywords(newEntity);]]></call-bsh><now-timestamp field="nowTimestamp"/> <else> <if-compare field-name="autoCreateKeywords" map-name<set from-field="nowTimestamp" field="newEntity.createdDate" operator/> <set from-field="equalsnowTimestamp" valuefield="YnewEntity.lastModifiedDate"/> <set from-field="userLogin.userLoginId" field="newEntity.lastModifiedByUserLogin"/> <call-bsh><![CDATA[org.ofbiz.commonapp.product.product.KeywordSearch.induceKeywords(newEntity);]]></call-bsh> <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"/> </if-compare>then> </else>if> </if!--empty> after checking status change, set all parameters </simple-method>--> <simple-method event-name="create" short-description="Create Work Effort"<set-nonpk-fields map="parameters" value-field="lookedUpValue"/> <!-- only save if something has changed --> <call-map-processor xml-resource="org/ofbiz/commonapp/workeffort/workeffort/WorkEffortMapProcessors.xml"<if-compare-field field="lookedUpValue" to-field="savedValue" operator="not-equals" type="Object"> processor-name="update" in-map-name="parameters" out-map-name="context"/> <check-errors/> <!-- only set lastModifiedDate after comparing new & old to see if anything has changed --> <call-service<set servicefrom-namefield="createWorkEffortnowTimestamp" in-map-namefield="contextlookedUpValue.lastModifiedDate"/> <set <default-message>Work Effort successfully created.</default-message>from-field="userLogin.userLoginId" field="lookedUpValue.lastModifiedByUserLogin"/> <result<if-tonot-requestempty result-name="workEffortId"/field="lookedUpValue.revisionNumber"> </service> </simple-method> <simple-method event-name="update" short-description="Update Work Effort"> <set field="lookedUpValue.revisionNumber" value="${lookedUpValue.revisionNumber + 1}" type="Long"/> <call-map-processor xml-resource="org/ofbiz/commonapp/workeffort/workeffort/WorkEffortMapProcessors.xml" <else> <set processor-namefield="updatelookedUpValue.revisionNumber" in-map-namevalue="parameters1" out-map-nametype="contextLong"/> <check-errors/> </else> <call-service service-name="updateWorkEffort" in-map-name="context"> </if-not-empty> <default<store-message>Work Effort successfully updated.</default-message>value value-field="lookedUpValue"/> </service>if-compare-field> </simple-method> </simple-methods> |