ofbiz 之minilang解析

编写一个simple method 首先我们需要对输入参数进行验证 ,判断参数是否完整。 
1. 验证 
1.1. Login-required 
:这是一个simple-method的属性,对是否需要登陆进行设置,默认值为true ,即默认需要先登陆。(加上service 定义中的auth 定义,所以如果你不希望一个simple service 必须登陆才能调用的话,那么首先得将service 定义中的auth设为false ,再将此处的login-required 设为false),后续会陆续多种子权限判断的用法,关于权限判断都是首先需要登陆的。 
1.2. use-transaction 
:设置此simple method 是否使用事务。根据业务需求来判断具体设置。 
1.3. check-permission 
:判断权限是否具有某一权限,一般用法为: 
<check-permission permission="person" action="_update"> 
<alt-permission permission="person" action="_view"/> 
<fail-property resource="WebtoolsUiLabels" property="doNotHavePermission"></fail-property> 
</check-permission> 
<check-errors></check-errors> 
使用check-permission前提条件是当前service 环境中必须存在用户的登陆信息,即能获取到userLogin . service 的调用场景有很多,controller.xml中,screen中,simple method 中,bsh文件中,ftl 文件中,java 文件中,groovy文件中等,其中前三项系统会自动将userLogin,locale 等信息自动封装到service context 中去,所以不需要我们手段传值,所以我们在其他环境中调用service的时候就需要对需要的隐性参数进行传值,比如fail-property中会用到locale, check-permission会用到userLogin 等,调用举例如下: 

dispatcher.runSync("TestServiceOnSimple",UtilMisc.toMap("param3","TestServiceOnJava","userLogin",userLogin,"locale",locale)); //java文件中 

check-permission中有个属性error-list-name="error_list" ,这条属性的意思是意义是将错误信息放到error_list这个list 中。配合check-errors的共同使用。 


其中check-permission判断是否具有”${permission的值}_ADMIN” 权限,如果action的值不为null,则会首先判断当前用户是否具有”${permission的值}_ADMIN”权限,如果有则权限判定符合要求,否则判断是否具有”${permission的值}_${action的值}”,如果check-permission判断权限要求都不满足的话,会进行alt-permission 权限判断,判断规则和check-permission一样, check-permission 和 alt-permission 两者的关系是or的关系,即只要两者有一个满足权限要求即可。如果两者条件都不满足的话那么将会把fail-property 写进错误信息中,fail-property错误信息来源于”${ resource的值}.xml”中key值为”${property的值}”所对应的value 值。系统会自动根据客户端浏览器的locale从文件中获取对象的提示信息。 
当然你也可以直接将来报错提示信息写在当前simple methord 中,使用 
<check-permission permission="person" action="_update"> 
<alt-permission permission="person" action="_view"/> 
<fail-message message="you do not have XXX permission !!"/> 
</check-permission> 
fail-message 与 fail-property 是不能共存的,二者只能存其一。 
所有上面的内容只会对权限进行判断,权限不满足的话收集提示信息,<check-errors></check-errors>则是返回错误信息。如果没有check-errors那么service method 将会继续往下执行。有check-errors的话则会中断simple method 的执行。 

如果非要用java 语言进行翻译的话,我觉得应该是这样的。 

<check-permission permission="person" action="_update"> 
<alt-permission permission="party" action="_view"/> 
<fail-property resource="WebtoolsUiLabels" property="doNotHavePermission"></fail-property> 
</check-permission> 
<check-errors></check-errors> 

翻译成java service 应该是这样的. 

Security security = dctx.getSecurity(); 
if (!(security.hasPermission ("person_ADMIN", userLogin) 
||  security.hasPermission ("person_update", userLogin) 
||  security.hasPermission ("party_ADMIN", userLogin) 
||  security.hasPermission ("party_view ", userLogin)) 
) {Return ServiceUtil.returnError( 
UtilProperties.getMessage("WebtoolsUiLabels","doNotHavePermission",locale)); 
} 

另:check-permission 中还有个子节点accept-userlogin-party ,似乎不很常用,后待研究 
1.4. if-has-permission 
<if-has-permission permission="person_view" > 
<set field="hasPermission" type="Boolean" value="true"/> 
<field-to-result field="hasPermission"/> 
<log level="info" message="you have ACCTG_FX_ENTRY!"/> 
<else> 
<set field="hasPermission" type="Boolean" value="false"/> 
<property-to-field 
resource="CommonUiLabels" property="CommonGenericPermissionError" field="failMessage"/> 
<field-to-result field="hasPermission"/> 
<field-to-result field="failMessage"/> 
</else> 
</if-has-permission> 

if-has-permission判断权限的规则和check-permission的规则是一样的。不重复了,if-has-permission和check-permission最大的不同在于if-has-permission可以进行if-else 的逻辑判断.当然如果不需要else判断的话可以把else节点整个去掉,即: 
<if-has-permission permission="person_view" > 
<set field="hasPermission" type="Boolean" value="true"/> 
<field-to-result field="hasPermission"/> 
<log level="info" message="you have ACCTG_FX_ENTRY!"/> 
</if-has-permission> 


翻译一下前边的if-has-permission的例子. 
首先判断当前用户是否具有person_view的权限,如果有这个权限那么执行: 
<set field="hasPermission" type="Boolean" value="true"/> 
创建Boolean 变量 hasPermission 值为true 
<field-to-result field="hasPermission"/> 
将hasPermission这个变量赋值到result结果集中 
<log level=" info" message="you have ACCTG_FX_ENTRY!"/> 
输出info级别日志,” you have ACCTG_FX_ENTRY!”. 

判断权限如果没有这个权限则执行: 

<set field="hasPermission" type="Boolean" value="false"/> 
创建Boolean 变量 hasPermission 值为false 
<property-to-field 
resource="CommonUiLabels" property="CommonGenericPermissionError" field="failMessage"/> 

从CommonUiLabels.xml文件中获取key为CommonGenericPermissionError的国际化内容并赋值到变量failMessage中 
<field-to-result field="hasPermission"/> 
将hasPermission这个变量赋值到result结果集中 
<field-to-result field="failMessage"/> 
将failMessage这个变量赋值到result结果集中 

1.5. if-compare 
<if-compare field="statusId" 
operator="equals" value="INVOICE_PAID"> 
         <log level="info" 
message="The compare conditions are met"></log> 
         <else> 
         <log level="info" 
message="The compare conditions are not met"></log> 
         </else> 
         </if-compare> 
if-compare,把某一参数的值与一特定的值进行比较。比较的逻辑类型通过operator进行设置,种类主要有less,greater,less-equals,greater-equals,equals,not-equals,contains等,不挨个解释了无非是大于,等于,大(小)于等于,包含等。 
if-compare中另外还有两个参数format、type . type指比较参数双方的数据类型,比较之前系统会将比较双方的参数转化成你指定的type类型。 
format指比较参数双方的格式,一般用在日期格式中,和日期有关的type类型主要有Time,Date,Timestamp三种,针对这三种子日期类型format类型有三个默认值 
分别是"HH:mm:ss","yyyy-MM-dd","yyyy-MM-dd HH:mm:ss.SSS" 。使用时间进行比较的时候参数的格式最好和默认的format相同,否则容易出现不可预料的问题。 

与if-has-permission类似,当满足if条件的情况下执行<if-compare 与 <else>中间的内容,否则则执行<else>与</else>中间的内容,当然和if-has-permission一样,也可以不使用<else></else>(以后类似情况不再提了,自己类推吧。).即 
<if-compare field="statusId" 
operator="equals" value="INVOICE_PAID"> 
         <log level="info" 
message="The compare conditions are met"></log> 
         </if-compare> 





1.6. if-compare-field 
if-compare-field与if-compare用法规则相同,唯一的不同在于if-compare是一个参数与固定值之间的比较,而if-compare-field是两个参数之间的比较。 
1.7. if-empty 
<if-empty field="param5"> 
    <log level="info" message="the parameter param5 is empty"></log> 
    <else> 
    <log level="info" message="the parameter is not empty "></log> 
    </else> 
</if-empty> 

判断一个参数是否为null,如上判断参数param5是否为null. 
1.8. if-not-empty 
<if-not-empty field="param5"> 
<log level="info" message="the parameter is not empty "></log> 
<else> 
    <log level="info" message="the parameter is empty "></log> 
</else> 
</if-not-empty> 
顾名思义这个是和if-empty反着用的。 
   
1.9. if-instance-of 
<if-instance-of field="param5" class="String"> 
<log level="info" message="the parameter is a String"></log> 
<else> 
    <log level="info" message="the parameter is not a String"></log> 
</else> 
</ if-instance-of> 
OR 
<if-instance-of field="param5" class="java.util.List"> 
<log level="info" message="the parameter is a List"></log> 
<else> 
   <log level="info" message="the parameter is not a List"></log> 
</else> 
</if-instance-of> 
if-instance-of判断某一参数是否属于指定的参数类型。类似于java 中的instanceof  。 

1.10. if-regexp 
<if-regexp field="param5" expr="^[a-zA-Z_0-9]+$"> 
<log level="info" message="expr validate success"></log> 
<else> 
<log level="info" message="expr validate Fail"></log> 
</else> 
</if-regexp> 
使用正则表达式对参数进行验证。 

1.11. if-validate-method 
<if-validate-method field="param5" method="isEmail"> 
<log level="info" message="param5 is a Email"></log> 
<else> 
<log level="info" message=" param5 is not a Email"></log> 
</else> 
</if-validate-method> 

使用验证方法对参数进行验证,if-validate-method有个class属性,其默认值为 
"org.ofbiz.base.util.UtilValidate",使用${class}类中的${method}方法对参数param5进行验证。 
1.12. if 
<if> 
<condition> 
<and> 
<if-compare field="param1" operator="equals" value="value1"/> 
<if-compare field="param2" operator="equals" value="value2"/> 
</and> 
</condition> 
    <then> 
<log level="info" message="condition1 validate success"></log> 
    </then> 
    <else-if> 
    <condition> 
<if-compare field="param3" operator="equals" value="value3"/> 
</condition> 
   <then> 
<log level="info" message="condition2 validate success"></log> 
    </then> 
    </else-if> 
    <else> 
<log level="info" message="condition1 and condition2 validate Fail"></log> 
    </else>
</if>
If 一般情况下配合condition 使用,进行多条件的组合判断,使用<and></and> 或者<or></or>组织多个条件的逻辑关系,如果condition 条件满足,那么执行then ,否则执行 else-if 或者 else . 此用法是minilang 中唯一可以使用else if 逻辑判断的地方。 
1.13. check-id 
<check-id field="parameters.orderId" error-list-name="error_list"> 
</check-id> 
对参数进行特殊字符验证,判断orderId 中是否含有空格、“、‘、&、?、<、>、、/等。针对每种不同的特殊字符,check-id 提供了一种默认错误提示信息与之对应,所以错误信息可以不用设置,当然也可以使用fail-message 和 fail-property提供错误信息(用法同check-permission ,后续用到将不再重复),将错误信息放到${error-list-name}中,供check-errors使用。 

    

1.14. add-error 
<add-error error-list-name="error_list"> 
    <fail-message message="error Need a reason?"/> 
</add-error> 
OR 
<add-error error-list-name="error_list"> 
<fail-property resource="WebtoolsUiLabels" property="errorKey"> 
</fail-property>
</add-error> 

向一个错误结果list中添加错误信息,错误结果list的name 可以指定,错误信息的来源可以来自来源于国家化xml文件.而可以是直接写死的message。一般用在之前介绍的那么多if-XXXX判断中,如果条件不满足(<else></else>中间)那么将错误信息写入错误信息结果list中,再通过check-errors 将错误信息返回。 



1.15. check-errors 
<check-errors error-code="resultPage" error-list-name="error_list"> 
    </check-errors> 
前边已经讲到很多,是将错误信息进行返回,如果错误信息结果${error-list-name}中存在错误那么将返回错误信息并终止当前simple method 的运行。 
error-list-name指定要返回的错误信息结果list名称,MethodContext中可能会包含多个错误结果信息list,根据业务需要而定,  error-code 返回错误状态码,一般用在controller.xml 中, 
   <request-map uri="testServiceTest"> 
    <security https="false" auth="false"/> 
        <event type="service" invoke="TestServiceOnJava"/> 
<response name="success" type="view" value="toSuccess"/> 
        <response name="error"   type="view" value="toError"/> 
<response name="resultPage"   type="view" value="toResult"/> 
   </request-map> 
系统会根据其返回的code 而指向不同的request 或者 view 。 

check-errors 另有4个节点,(已过期,源码已经被注释) 
<message-suffix resource="WebtoolsUiLabels" property="doNotHavePermission2"></message-suffix> 
<message-prefix resource="WebtoolsUiLabels" property="doNotHavePermission2"></message-prefix> 
<error-prefix   resource="WebtoolsUiLabels" property="doNotHavePermission2"></error-prefix> 
<error-suffix   resource="WebtoolsUiLabels" property="doNotHavePermission2"></error-suffix> 
1.16. assert 
assert:断言待确定。 

calculate 
1.17. calculate 
calculate:待确定 


2. 数据操作 
2.1. clone-value 
<clone-value value-field="lookedUpValue" new-value-field="newLookedUpValue"/> 
clone-value克隆参数。以${value-field}参数对象为模板,创建一个新的参数对象。value-field的值必须是一个GenericValue对象或者是能够转化成GenericValue的对象。 
2.2. clear-field 
<if-not-empty field="param6"> 
<log level="info" message="the value of  param6 is not empty"></log> 
   </if-not-empty> 
    <clear-field field="param6"/> 
    <if-empty field="param6"> 
<log level="info" message="the value of  param6 is empty"></log> 
</if-empty> 
运行结果 
[CommonServices.xml#TestServiceOnSimple line 85] the value of  param6 is not empty 
[CommonServices.xml#TestServiceOnSimple line 89] the value of  param6 is empty 
clear-field 将参数${field}从simple method 运行环境中methodContext清除掉。 
2.3. create-object 
待确定 
2.4. clear-cache-line 
待确定 

2.5. clear-entity-caches 
待确定 

2.6. entity-one 
<set field="UserLogin" value="admin"/> 
<entity-one entity-name="UserLogin" value-field="adminUserLogin" 
auto-field-map="true" use-cache="true"> 
</entity-one> 
<log level="info" message="${adminUserLogin}"></log> 
entity-one根据给定主键对某一特定实体进行主键查询。如上例:根据实体UserLogin 主键userLoginId的值进行主键查询,并将查询结果定义为adminUserLogin。 
由于entity-one 的属性auto-field-map的值设置为true,所以系统会从simple method 的运行环境MethodContext中自动寻找实体的主键。use-cache 是关于是否首 先从缓存中获取数据的设置。 

如果auto-field-map的值设置为false,那么系统将不会自动从封装实体主键,那么需要我们手动给参,如下: 
<entity-one entity-name="UserLogin" value-field=" adminUserLogin " auto-field-map="false"> 
<field-map field-name="userLoginId" value="admin"/> 
</entity-one>
<set field="userLoginId" value="admin"/> 即为给主键传参。参数可以为固定的value 值,也可为已经存在与运行环境中的参数值。如下: 
<set field="userLoginId" value="admin"/> 
<entity-one entity-name="UserLogin" value-field=" adminUserLogin " auto-field-map="true"> 
   <field-map field-name="userLoginId" from-field=" userLoginId "/> 
   <select-field field-name="currentPassword"/> 
   <select-field field-name="disabledDateTime"/> 
</entity-one> 
select-field为非主键选择性输出,即将实体字段中用到的字段写入查询结果adminUserLogin中,用不到的则不写入。select-field 不得设置主键,且使用select-field时不能与use-cache="true" 同时使用。 
2.7. entity-and 
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList"> 
        <field-map field-name="partyId" value="admin"/> 
        <select-field field-name="workEffortId"/> 
        <order-by field-name="+workEffortId"/> 
</entity-and> 
<log level="info" message="${wepaList}"></log> 

entity-and 非主键多条件查询。 
use-cache 是关于是否首先从缓存中获取数据的设置。不能和select-field共同使用。 

为了容易查看效果这里使用select-field(用法同entity-one 中select-field)限制查询字段只显示输出了workEffortId
字段。输出结果如下: 
{ 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9000(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9002(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9100(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,OneOffMeeting(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,STAFF_MTG(java.lang.String)] 
} 
entity-and 中属性 limit-range 效果展示 : 
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList"> 
<field-map field-name="partyId" value="admin"/> 
    <select-field field-name="workEffortId"/> 
    <order-by field-name="+workEffortId"/> 
    <limit-range size="3" start="2"/> 
</entity-and> 
<log level="info" message="${wepaList}"></log> 
输出结果: 
{ 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9002(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9100(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)] 
} 
可以发现limit-range的功能为截取查询结果,从第${start}(包括此条)数据起,截取${size}条数据做为最终结果。 

entity-and 中属性 limit-view 效果展示 : 
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList"> 
<field-map field-name="partyId" value="admin"/> 
    <select-field field-name="workEffortId"/> 
    <order-by field-name="+workEffortId"/> 
    <limit-view view-size="2" view-index="2"/> 
</entity-and> 
<log level="info" message="${wepaList}"></log> 
输出结果: 
{ 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9100(java.lang.String)], 
[GenericEntity:WorkEffortPartyAssignment][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)] 
} 
可以发现limit-view 类似于分页,将查询结果划分为每页${view-size}条数据,取第${view-index}页数据,如果用limit-view 来实现相同功能的话,需要设置start="3",size="2" 

entity-and 中属性 use-iterator 效果展示 : 
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList"> 
<field-map field-name="partyId" value="admin"/> 
    <select-field field-name="workEffortId"/> 
    <order-by field-name="+workEffortId"/> 
    <use-iterator/> 
</entity-and> 
<if-instance-of ass="org.ofbiz.entity.util.EntityListIterator" 
ield="wepaList"> 
<log level="info" message="the wepaList is a Iterator"></log> 
</if-instance-of> 
<if-instance-of class="java.util.List" field="wepaList"> 
<log level="info" message="the wepaList is a List object"></log> 
</if-instance-of> 
设置<use-iterator/>时输出结果为: 
the wepaList is a Iterator 
不设置时输出结果为: 
the wepaList is a List object 
可见设置<use-iterator/>使输出参数结果的格式发生了变化。如果设置了use-iterator ,却不使用EntityListIterator结果对象的话,会报错(待查验) 
总结:use-iterator、limit-view、limit-range 三者不能两两共存,且此三者所处位置必须在其他同级节点的后面。 
2.8. entity-condition 
<entity-condition list="partyAssignments" entity-name="WorkEffortPartyAssignment" filter-by-date="true"> 
    <condition-list combine="and"> 
    <condition-expr field-name="workEffortId" from-field="workEffortId"/> 
    <condition-expr field-name="partyId" from-field="userLogin.partyId"/> 
    <condition-expr field-name="statusId" value="PRTYASGN_ASSIGNED"/> 
  <condition-list combine="or"> 
    <condition-expr field-name="roleTypeId" value="CAL_OWNER"/> 
    <condition-expr field-name="roleTypeId" value="CAL_ORGANIZER"/> 
    <condition-expr field-name="roleTypeId" value="CAL_DELEGATE"/> 
    </condition-list> 
    </condition-list> 
</entity-condition> 
entity-condition 对实体${entity-name}进行多条件组合逻辑查询。 
ofbiz 很多实体在创建的时候都会有两个字段,分别为fromDate 和 thruDate. 
这两个字段一般被用来代表当前数据的有效期间,既当前数据的有效期为大于等于fromDate 且  小于 thruDate 。 当fromDate 为null 时 则表示前端无限制, thruDate表示后端无限制。 
属性distinct很好理解,剔除重复数据。需要注意的是如果配合select-field 共同使用的时候,判断重复的条件是判断select-field 需要显示字段是否重复,而不是判断当前实体所有的字段,即SQL 执行顺序是 先select-field 再distinct。 
属性filter-by-date即为对记录表数据时间有效性的过滤,使用前提是当前实体必须有fromDate 和 thruDate这两个字段,且不能使用缓存进行查询 ,即use-cache="false",转化成sql 表示为 
((thruDate IS NULL OR thruDate > '当前时间') AND (fromDate IS NULL OR fromDate <= '当前时间')) 

condition-expr为单个条件的逻辑判断,逻辑判断类型通过operator 进行设置,用法和if-compare类似。ignore-if-empty="true",当前字段为“”时是否忽略, 
意思是如果当前进行判断的字段为””则忽略此判断。同理ignore-if-null="true"意思是如果当前进行判断的字段为null则忽略此判断. 

condition-list为多个条件的逻辑组合,通过combine对condition-list节点中的多个condition-expr 进行逻辑组合,逻辑关系主要有 “and” 和 “or” 两种。 

condition-object为使用当前simple 运行环境中已经存在的org.ofbiz.entity.condition.EntityCondition 类型的对象进行逻辑判断。 

having-condition-list一般用于带有group-by 查询的视图实体查询,首先对根据condition-list查询条件进行查询,然后再根据having-condition-list查询条件进行限制查询。 比如: 
<view-entity entity-name="WorkEffortPartyAssignmentView" package-name="org.ofbiz.workeffort.workeffort"> 
  <member-entity entity-alias="wepa" entity-name="WorkEffortPartyAssignment"></member-entity> 
<alias-all entity-alias="wepa"> 
  <exclude field="partyId"/> 
  </alias-all>
  <alias entity-alias="wepa" name="partyId" group-by="true"> 
  </alias> 
  <alias entity-alias="wepa" name="quantityTotal" field="partyId" function="count"/> 
</view-entity> 
此视图实体全部使用WorkEffortPartyAssignment的参数,根据partyId进行分组,然后获取每组的数量。 
查询使用: 
<entity-condition list="wepaListTwo" entity-name="WorkEffortPartyAssignmentView"> 
<condition-list combine="or"> 
<condition-expr field-name="partyId" operator="equals" value="admin"/> 
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee2"/> 
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee3"/> 
</condition-list> 
<having-condition-list> 
<condition-expr field-name="quantityTotal" operator="equals" value="3"/> 
</having-condition-list> 
<select-field field-name="partyId"/> 
<select-field field-name="quantityTotal"/> 
<use-iterator/> 
</entity-condition> 
首先根据三个partyId条件进行逻辑或进行分组查询,然后再对查询结果进行having-condition-list筛选。Sql 解析结果为: 
SELECT wepa.PARTY_ID, COUNT(wepa.PARTY_ID) FROM OFBIZ.WORK_EFFORT_PARTY_ASSIGNMENT wepa WHERE ((wepa.PARTY_ID = 'admin' OR wepa.PARTY_ID = 'DemoEmployee3' OR wepa.PARTY_ID = 'DemoEmployee2')) GROUP BY wepa.PARTY_ID HAVING (COUNT(wepa.PARTY_ID) = 3) 
having-condition-list 用法同condition-list。 
总结:entity-condition当使用缓存进行查询时,不能使用distinct、having-condition-list、select-field。entity-condition查询限制条件最外层必须为condition-list、condition-expr、condition-object中的一个,三者不能两两并存。entity-condition的几个子节点配置先后顺序分别为:[condition-list、condition-expr、condition-object]三者中的一个、[having-condition-list]、[select-field],[order-by]、[use-iterator、limit-view、limit-range]三者中的一个。


2.9. entity-count 
<entity-count count-field="num" entity-name="WorkEffortPartyAssignment"> 
<condition-list combine="or"> 
<condition-expr field-name="partyId" operator="equals" value="admin"/> 
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee2"/> 
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee3"/> 
</condition-list> 
</entity-count> 
entity-count 查询${entity-name}中符合条件的数据条数并赋值到 ${count-field}参数。条件配置与 entity-condition 一样。不罗嗦。 
2.10. entity-data 
待确定 
2.11. find-by-primary-key 

<set field="fieldsToSelect[]"   value="currentPassword"/> 
<set field="fieldsToSelect[]"   value="partyId"/> 
<set field="inParma.userLoginId" value="admin"/> 
<!—- 此处以上都是参数的处理以及设置 --> 
<find-by-primary-key entity-name="UserLogin" value-field="outResult" map="inParma" fields-to-select-list="fieldsToSelect" /> 
<log level="info" message="---${outResult}---"></log> 
find-by-primary-key功能与entity-one 相同,不同的是find-by-primary-key需要将主键字段封装到一个map中,然后使用,显示字段slelect-field 也是需要先将需要显示的字段封装到一个list 中。 
: entity-name:查询实体名称。 
:value-field:查询结果得到的实体对象名称。 
:map: 一个map ,其中包含了主键字段。作为主要查询的依据。如果主键由多个字段组合而成,那么此map中需要包含所有的主键的字段信息。 
:fields-to-select-list: 一个list,配置查询结果中所包含的非主键字段,主键字段就不要再这里设置了。 
:use-cache:与entity-one 不同,这里的use-cache可以和选择性显示字段fields-to-select-list共同使用 
2.12. find-by-and 
<clear-field field="inParma"/> 

<set field="inParma.partyId" value="admin"/> 
<set field="orderList[]" value="+partyId"/> 
<set field="orderList[]" value="-workEffortId"/> 


<find-by-and list="outResult" map="inParma" entity-name="WorkEffortPartyAssignment" order-by-list="orderList" use-cache="true" use-iterator="true"/> 
<iterate entry="out" list="outResult"> 
<log level="info" message="iterator---${out}---"></log> 
</iterate> 
功能同entity-and,多条件查询。 

:map:map 类型,其中放置了查询条件,map中多条查询条件之间的逻辑关系是and的关系。由于输入参数inParma这个map不能包含所查询实体${entity-name}之外的字段,在之前程序中我们可能已经使用过这个inParma参数,其中可能已经包含一些其他数据,所以我们使用之前最好将inParma参数清除一下。即<clear-field field="inParma"/> 
:order-by-list:list 类型,排序的依据。需要提前封装。 
:use-cache:是否使用缓存查询,与entity-and中use-cache会与其他节点或者属性有冲突不同,这里use-cache与其他节点属性可以共存。 
:use-iterator:是否使用iterator类型返回参数。 
2.13. get-related-one 
<make-value value-field="userNew" entity-name="UserLogin"/> 
<set field="userNew.partyId" value="admin"/> 
<get-related-one relation-name="Party" to-value-field="partyNew" value-field="userNew"/>

get-related-one根据外键实体获取外键所对应主键的实体。 
实体与实体之间存在一中relation关系,如果把relation的方称为 甲实体 ,被relation的实体称为乙实体 。那么这里是根据 甲实体对象对乙方实体对象进行业务操作(查询)。使用get-related-one的前提是 甲实体 对乙方实体 relation 的type类型为one 或者 one-noFK 。 
:value-field:甲方实体对象名称,查询依据。此实体必须包含relation 字段的值, 
即甲方实体对象相对应乙方的外键值必须不能为null值。否则获得结果集为null; 
:relation-name:查询实体名称。 
:to-value-field:查询结果实体对象名称。 


后面将会介绍到remove-related ,这个和 get-related-one 的关系有点相反。 
remove-related 是根据乙方实体对象对甲方实体对象进行业务操作(删除)。 
把这两个结合起来看吧 。(相关relation 的操作建议熟悉实体的relation 再看) 

2.14. get-related 
<clear-field field="partyNew"/> 
<make-value value-field="partyNew" entity-name="Party"/> 
<set field="partyNew.partyId" value="AUTHOR_MADMAX"/> 
<get-related relation-name="UserLogin" list="userLoginList" value-field="partyNew"/> 
待定。。。。。。 


2.15. filter-list-by-and 
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList"> 
<field-map field-name="partyId" value="admin"/> 
<select-field field-name="workEffortId"/> 
<select-field field-name="partyId"/> 
<select-field field-name="roleTypeId"/> 
<order-by field-name="+workEffortId"/> 
</entity-and> 
<iterate entry="wepaL" list="wepaList"> 
<log level="info" message="before filter --- ${wepaL}"></log> 
</iterate> 

<clear-field field="inParma"/> 
<set field="inParma.workEffortId" value="9000"/>
<set field="inParma.roleTypeId" value="PROVIDER_MANAGER"/> 

<filter-list-by-and list="wepaList" map="inParma" to-list="wepaListFilter"/> 
<iterate entry="wepa" list="wepaList"> 
<log level="info" message="after filter wepaList --- ${wepa}"></log> 
</iterate> 
<iterate entry="wepa" list="wepaListFilter"> 
<log level="info" message="after filter wepaListFilter----${wepa}"></log> 
</iterate> 
输出结果如下: 
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9000(java.lang.String)]                 
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9002(java.lang.String)]                 
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9100(java.lang.String)]                 
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_OWNER(java.lang.String)][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)]           
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,OneOffMeeting(java.lang.String)]            
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,STAFF_MTG(java.lang.String)]                
after filter wepaList ---    [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9000(java.lang.String)]      
after filter wepaList ---    [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9002(java.lang.String)]      
after filter wepaList ---    [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9100(java.lang.String)]      
after filter wepaList ---    [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_OWNER(java.lang.String)][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)] 
after filter wepaList ---    [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,OneOffMeeting(java.lang.String)] 
after filter wepaList ---    [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,STAFF_MTG(java.lang.String)]     
after filter    wepaListFilter----[GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9000(java.lang.String)] 

filter-list-by-and 的功能为对存放GenericValue对象的list ,使用一个存放有一个或者多个list 中GenericValue对象的字段的键值对,对list进行筛选。 
如果list中GenericValue对象的字段能够和map中的对象(map中多个对象关系为and,必须全部满足。)对应起来那么则满足条件。 
<filter-list-by-and list="wepaList" map="inParma" to-list="wepaListFilter"/> 
如果 to-list有值,那么则过滤后的结果放到${to-list}中去,否则过滤后结果覆盖${to-list}. 
Map中key 值必须为list 中GenericValue对象中存在的字段,否则过滤后结果为null。 
2.16. filter-list-by-date 
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList"> 
<field-map field-name="partyId" value="admin"/> 
<order-by field-name="+workEffortId"/> 
</entity-and> 
<set field="DateNow" type="Timestamp" value="2009-07-04 10:53:25.546"/> 
<filter-list-by-date list="wepaList" to-list="wepaListFilter" all-same="false" from-field-name="fromDate" thru-field-name="thruDate" valid-date="DateNow"/> 
<iterate entry="wepa" list="wepaList"> 
<log level="info" message="after filter wepaList --- ${wepa}"></log> 
</iterate> 
<iterate entry="wepa" list="wepaListFilter"> 
<log level="info" message="after filter wepaListFilter----${wepa}"></log> 
</iterate> 
filter-list-by-date 对含有GenericValue对象的list 集合中数据进行时间有效性验证。 
:list:要进行过滤验证的list 的名称.其中包含对象必须为GenericValue对象. 
: to-list:过滤后结果输出集合名称,如果不设置此值,结果会覆盖输入集合。 
:from-field-name:时间有效性验证开始时间字段。 
:thru-field-name:时间有效性验证结束时间字段。 
:all-same:无效字段。 
:valid-date:时间有效性验证的标准,此值必须是一个在运行环境中存在的时间类型的参数。如果不设置此值,默认使用当前时间。炎症规则请参考 entity-condition 的filter-by-date。 
2.17. make-value 
<clear-field field="inParma"/> 
<set field="inParma.userLoginId" value="djtao"/> 
<make-value value-field="user" entity-name="UserLogin" map="inParma"/> 
<log level="info" message="make-value----${user}"></log> 
输出结果: make-value----[GenericEntity:UserLogin][userLoginId,djtao(java.la ng.String)] 
Make-value : 创建一个GenericValue对象. entity-name是所要创建对象的实体的名称,value-field是所创建对象的参数名称, map会将其中自动与实体字段相对应的值赋到实体对象中。 
2.18. set-pk-fields 
<clear-field field="inParma"/> 
<set field="inParma.partyId" value="admin"/> 

<set-pk-fields value-field="wepaNew" set-if-null="true" map="inParma"/> 

set-pk-fields 用于给一个GenericValue对象 赋主键值。如果${map}参数中所包含的内容中key有GenericValue对象主键的字段相同的,那么将此key所对象的value赋到GenericValue对象。 
:value-field:GenericValue对象 名称。将要被赋予值的参数名称。 
:map:主键值来源。 
:set-if-null:其目的是想如果map 中某主键对应的值为null的话,是否对此主键进行赋值,如果此设置为“true”的话,主键对应的值为null 或者 “”的话,程序都会给此主键赋值为null 。如果此如果此设置为“false”的话,null值则会忽略,其他原样赋值。 

2.19. set-nonpk-fiels 
<set-nonpk-fields value-field="wepaNew" map="inParma" set-if-null="true"/> 
给非主键赋值,规则和set-pk-fields一样 不重复。 




2.20. create-value 
<create-value value-field="wepaNew" do-cache-clear="true" or-store="false"/> 

在经过make-value、set-pk-fields、set-nonpk-fields之后一个完整的实体对象 就被创建起来了,那么我们将使用create-value将这个实体对象保存到数据库中。 

:value-field:要保存对象的名称。 
:do-cache-clear:清除缓存。 
:or-store:如果数据库中已存在此主键对应数据,是否根据实体对数据进行update更新。 
2.21. store-value 

<set field="user.currentPassword" value="321"/> 

<store-value value-field="user" do-cache-clear="true"/> 

解析后执行SQL 
UPDATE OFBIZ.USER_LOGIN SET CURRENT_PASSWORD=?, LAST_UPDATED_TX_STAMP=?, LAST_UPDATED_STAMP=? WHERE USER_LOGIN_ID=?

minilang 中更新数据和我们用SQL 直接更新不同。首先我们必须获得包含主键信息的实体对象,这个获取实体对象的方式可以是我们用make-value手动生成,也可以根据主键信息查询数据得到的实体对象,然后对实体对象中字段进行set修改。然后使用store-value就可以将改动些到数据库中了。Update 字段只修改实体对象中的非主键字段。 
:do-cache-clear:清除缓存。 

2.22. store-list 
<set field="listUser[]" from-field="user"   /> 
<set field="listUser[]" from-field="user"   /> 
<set field="listUser[]" from-field="user"   /> 
<set field="listUser[]" from-field="user"   /> 
<set field="listUser[]" from-field="user"   /> 

<store-list list="listUser" do-cache-clear="true"/> 

store-list批量修改数据。${list}是一个list 其中放的是要被写入数据库的实体对象。 
store-list 与 store-value 不同的地方在于 , 如果store-list 中的实体对象在数据库中不存在时,他会首先创建一条记录,而store-value 却不会。 

2.23. remove-value 
<remove-value value-field="user" do-cache-clear="true"/> 
根据包含主键字段的实体删除数据。 


2.24. remove-list 
<remove-list list="listUser" do-cache-clear="true"/> 

批量删除。将一个包含多个实体对象的list 中所代表的数据行全部删除。 



2.25. remove-by-and 
<set field="whereMap.partyId" value="djtao"/> 
<set field="whereMap.userLoginId" value="djtao"/> 
<set field="whereMap.currentPassword" value="djtao"/> 
<remove-by-and map="whereMap" entity-name="UserLogin" do-cache-clear="true"/> 
SQL解析后结果为: 
DELETE FROM OFBIZ.USER_LOGIN WHERE (PARTY_ID = 'djtao' AND USER_LOGIN_ID = 'djtao' AND CURRENT_PASSWORD = 'djtao') 
根据多条条件删除实体数据。Map中各个条件之间逻辑关系为and 关系。 

2.26. remove-related 
<make-value value-field="partyObject" entity-name="Party"/> 
<set field="inMap.partyId" value="djtao"/> 
<set-pk-fields value-field="partyObject" map="inMap"/> 

<remove-related relation-name="UserLogin" value-field="partyObject"/> 
SQL解析后结果为: 
DELETE FROM OFBIZ.USER_LOGIN WHERE (PARTY_ID = 'djtao') 

remove-related 根据外键所对应主键的实体的对象删除外键实体记录。如上例:UserLogin 实体中,partyId为外键,根据外键的实体对象进行删除。 



2.27. sequenced-id 
<make-value value-field="newEntity" entity-name="WorkEffort"/> 

    <sequenced-id sequence-name="WorkEffort" field="workEffortId"/> 
<set field="newEntity.workEffortId" from-field="workEffortId"/> 
sequenced-id 一般用于获取实体的自增长字段。 
:sequence-name:实体名称。 
:field:获取到的自增长字段值的名称。 
:get-long-only:待确定。 
:stagger-max:待确定。 
当然也可以这样用,可以节省一行代码,如下: 
<make-value value-field="newEntity" entity-name="WorkEffort"/> 
<sequenced-id sequence-name="WorkEffort" field="newEntity.workEffortId"/> 
2.28. make-next-seq-id(待验证) 
<make-value value-field="newEntity" entity-name="WorkEffort"/> 
   <make-next-seq-id seq-field-name="workEffortId" value-field="newEntity"/> 
功能和sequenced-id 差不多,但由于其自增长字段是通过程序获得并写入数据库的方法获得的,所以在高并发或者一次获取多条自增长的情况下,自增长的值可能会重复。但似乎sequenced-id能避免此问题,待验证。 
:value-field:想要获得自增长字段的实体对象。 
:seq-field-name:实体的自增长字段。 
:increment-by:待确定 
:numeric-padding:待确定
3. 逻辑操作 
3.1. set 
<set field="inMap.num" value="2"/> 
<set field="newValue" default-value="1" from-field="inMap.num" set-if-empty="true" set-if-null="true" type="String"/> 
Set 为变量参数赋值 。 
: field: 变量参数的名称. 
: from-field:变量参数值来源来源于环境中已经存在的变量.当然也可以使用value 
赋固定值。 
:default-value:默认值,当from-field和value都不存在时,使用默认值。 
:set-if-empty:如果变量的值为””是否仍然赋””于变量。 
:set-if-null:如果变量的值为null,是否仍然赋变量null。所以如果此属性配置为false(默认为false) 的话,那么使用set 的话,如果不赋值那么此set 无效。如: 
<set field="inMap.num" />此行代码无任何意义。 

3.2. set-calendar 
创建calendar 日期对象,待确定。 
3.3. set-current-user-login 
<set field="ulLookup.userLoginId" value="system"/> 
  <find-by-primary-key entity-name="UserLogin" map="ulLookup" value-field="newuserLogin"/> 

<set-current-user-login value-field=" newuserLogin"/> 
<log level="info" message="${parameters.userLogin}"></log> 
<log level="info" message="${userLogin}"></log> 

set-current-user-login 改变当前simple context 中的userLogin . 
parameters中的userLogin 不发生改变。 
3.4. string-append 
<string-append string="456" field="newString" arg-list="newList"  prefix="prefix" suffix="suffix"/> 
将String 字符串拼接起来。 
效果类似于 : 
newString = “${newString}”+”${prefix}”+”${string}”+”${suffix}” 
:arg-list:待确定 

3.5. string-to-list 
<set field="newList" type="List"/> 
   <string-to-list string="a" list="newList"/> 
   <string-to-list string="b" list="newList"/> 
   将字符串放到一个list 中。 
3.6. session-to-field 
<session-to-field field="sessionField" session-name="_WEBAPP_NAME_" default="sessionNull"/> 
Session-to-field 将session 中参数取出来赋值到当前环境的某变量中。 
:field:变量名称. 
:session-name:session中变量的名称. 
: default:如果sesssion 中此变量对应的值为null的话,则使用此默认值。 
注:此命令只有在event 调用simple  method 时方有效。即(MethodContext. methodType== MethodContext.EVENT)时方可使用。 
目前所知符合条件的只有一种情况,即在controller.xml中,如下例。 
<request-map uri="testServiceDelegator"> 
   <event type="simple" 
invoke="TestServiceOnSimple" path="component://webtools/script/org/ofbiz/common/CommonServices .xml"/> 
        <response name="success" type="view" value="testServiceTest"/> 
        <response name="error" type="view" value="testServiceTest"/> 
</request-map> 
在event 中调用,且type为simple . 
3.7. field-to-session 
  <field-to-session field="newUserLogin" session-name="userLogin"/> 
Field-to-session 将simple 环境中的参数放入session 中。属性不重复了. 
使用限制和session-to-field一样。 
  
   
3.8. field-to-list 
<clear-field field="newList"/> 
   <field-to-list list="newList" field="newUserLogin"/> 
Field-to-list ,将simple 环境中的一个参数变量放到一个list 类型的参数变量中。 
3.9. field-to-request 
<clear-field field="newList"/> 
   <field-to-list list="newList" field="newUserLogin"/> 
  <field-to-request field="newList" request-name="userLoginList"/> 
field-to-request ,把参数变量放到request 中,使用规则和限制同field-to-session 相同,不重复。 
3.10. request-to-field 
将参数从request 中取出赋职到simple 运行环境中。规则和限制同field-to-request。 
3.11. request-parameters-to-list 
   <request-parameters-to-list request-name="checkBoxName" list-name="parametersList"/> 
request-parameters-to-list 获取request 中的参数数组,并将参数放到simple method 中的list 中。request-parameters参数一般来源于checkBox .使用限制同 Session-to-field。
3.12. list-to-list 
待确定。 
3.13. map-to-map 
待确定。 

3.14. loop 
Loop待确定。 
3.15. first-from-list 
<first-from-list entry="oldExampleStatus" list="oldExampleStatusList"/> 
    <if-not-empty field="oldExampleStatus"> 
    <set field="oldExampleStatus.statusEndDate" from-field="nowTimestamp"/> 
    <store-value value-field="oldExampleStatus"/> 
</if-not-empty> 
first-from-list 从list 参数中得到第一个元素,并赋值到变量参数${entry}中。 
3.16. webapp-property-to-field 
<webapp-property-to-field resource="WebtoolsUiLabels" property="doNotHavePermission" field="fildFromProperties"/> 
Webapp-property-to-field 从国际化资源文件WebtoolsUiLabel.xml中获取property 为” doNotHavePermission” 的字符串并赋值到${field}中。 

3.17. iterate 

   <clear-field field="newParamList"/> 
   <set field="newParamList[]" value="a"/> 
   <set field="newParamList[]" value="b"/> 
   <set field="newParamList[]" value="c"/> 
   
<iterate entry="newParam" list="newParamList" > 
<log level="info" message="${newParam}"></log> 
</iterate> 
Iterate 遍历List参数newParamList。 
3.18. iterate-map 
<clear-field field="newParamMap"/> 
<set field="newParamMap.param1" value="param1"/> 
<set field="newParamMap.param2" value="param2"/> 
<set field="newParamMap.param3" value="param3"/> 
<iterate-map key="newKey" value="newValue" map="newParamMap"> 
<log level="info" message="${newValue}"></log> 
<log level="info" message="${newParamMap.${newKey}}"></log> 
</iterate-map> 
Iterate-map 对map参数进行遍历,这里有两种方法获取map中元素,一: 通过直接读取${value},二:也可以通过${key}读取map . 


3.19. while 
<set field="tmp" value="1"/> 
   <while> 
   <condition> 
   <if-compare operator="equals" value="2" field="tmp"> 
   </if-compare> 
   </condition> 
   <then> 
   <log level="info" message="test"></log> 
   </then> 
</while> 
While 循环,无论condition 条件 是否成立,先执行一次then 中的内容,然后再进行 condition 条件判断,如果不满足,则跳出while 循环。 
3.20. refresh-value 
refresh-value 待确定。 

4. 调用 
4.1. script 
<script location="component://product/webapp/catalog/WEB-INF/actions/imag emanagement/SetDefaultImage.groovy"/> 
Script 调用groovy 脚本 。 
:error-list-name:错误信息存放参数名称 


4.2. call-bsh 
<call-bsh><![CDATA[ 
            taxAuthPartyGeoIds = parameters.get("taxAuthPartyGeoIds"); 
            parameters.put("taxAuthPartyId", taxAuthPartyGeoIds.substring(0, taxAuthPartyGeoIds.indexOf("::"))); 
            parameters.put("taxAuthGeoId", taxAuthPartyGeoIds.substring(taxAuthPartyGeoIds.indexOf("::") + 2)); 
        ]]> 
</call-bsh> 
使用CDATA 部件 直接调用bsh脚本。也可以直接调用bsh 文件。 
<call-bsh error-list-name="error_list" resource="component://webtools/webapp/webtools/WEB-INF/actions/ca che/findUtilCache.bsh"> 
</call-bsh> 


4.3. call-class-method 
  <call-class-method class-name="org.ofbiz.base.util.UtilDateTime" method-name="getInterval" ret-field="originalProductionRunEstimatedTime"> 
<field field="productionRunHeader.estimatedStartDate" type="Timestamp"/> 
    <field field="productionRunHeader.estimatedCompletionDate" type="Timestamp"/> 
</call-class-method> 
<set field="taskTimeDifference" value="${originalProductionRunEstimatedTime - newProductionRunEstimatedTime}" type="Double"/> 

  public static double getInterval(Date from, Date thru) { 
        return thru != null ? thru.getTime() - from.getTime() : 0; 
    } 

call-class-method 调用class类中的方法 . 
: class-name:class类所在路径。 
:method-name:class类中方法名称。 
:ret-field:返回值名称,如果ret-map-name 没有设置的话,直接从当前环境中获取此参数就可以了,如上例。 
: ret-map-name:如果设置此值,那么需要先从simple methodContext中获取此map 对象,然后再从map 中获取ret-field. 
: field:当前调用的方法所需要的参数。 

4.4. call-map-processor 
<call-map-processor xml-resource="component://accounting/script/org/ofbiz/accounting/ payment/PaymentMapProcs.xml" 
processor-name="createCreditCard" in-map-name="parameters" out-map-name="context"/> 
call-map-processor调用map 处理器。 
map-processor 一种对map中元素进行过滤或者转化的处理器,类似于加工车间,入料口投入原料,出料口获得成品。一般多用于service 的参数进行处理,因为一般情况下service 对输入参数有限制,所以有时候需要对输入参数map 进行转化一下以匹配service 参数义。 
:xml-resource:map-processor 路径。 
:processor-name:map-processor名称。 
:in-map-name:输入map名称,相当于入料口原料,可能包含多余的参数。 
:out-map-name:输入map 名称,相当于出料口,获得到的map 可以直接用于service 的输入参数。 



4.5. set-service-fields 
<set-service-fields to-map="categoryFindContext" service-name="getAllCategories" map="parameters"/> 

<call-service service-name="getAllCategories" in-map-name="categoryFindContext"> 
    <result-to-field result-name="categories" field="categories"/> 
</call-service> 

set-service-fields 功能同call-map-processor,都是对map中元素进行过滤处理。不同的是 call-map-processor 的处理规则是我们手动定义的map-processor规则,set-service-fields规则是使用service 定义的输入参数。 
:service-name:service 名称。规定程序按照此service参数定义进行过滤。 
:map:转换器入口,投入map 的名称。 
:to-map:转换器出口,输出map的名称。 

4.6. call-service 
<call-service service-name="getAllCategories" in-map-name="categoryFindContext"> 
            <result-to-field result-name="categories" field="categoriesField"/> 
            <result-to-request result-name="categories" request-name="categoriesField"/> 
            <result-to-session result-name="categories" session-name="categoriesField"/> 
            <result-to-result result-name="categories" service-result-name="categoriesResult"/> 
        </call-service>
call-service 
经过call-map-processor 或 set-service-fields 参数处理之后,处理之后的输出结果, 我们可以直接拿来用做调用service 的输入参数。如上例: 
:service-name:service 名称 
:in-map-name:调用service 时用到的输入参数,map 类型,如果这里调用的是一个simple service的话 这里的in-map-name 就相当于 被调用simple service 中的parameters ,如果这里调用的是一个java service 的话这里的in-map-name 就相当于java service 输入参数中的context ,都是从其中获取参数。 
:result-to-field:假设在service A 中调用 service B ,那么个配置是将B service 中的return 参数 赋值到 service A 的参数。result-name 一定要是service B 中定义过的输出参数。 
:result-to-request:request-to-request  和 request-to-session 分别是将被调用service 的返回参数赋值到request 或者 session 中, 使用此命令有限制,请参考field-to-request。 
:result-to-result: 将service B 的输出参数 赋值到service A 的输出参数中 
result-name 一定要是 service B 中定义过的输出参数, service-result-name一定要是service A中定义过的输出参数。 

4.7. call-service-asynch 
call-service-asynch同call-service 类似,不同的是call-service是能够步调用,call-service-asynch 是异步调用,异步调用使用的ofbiz job 调度实现。 
4.8. call-object-method 
<set field="newString" value="123:456" type="String"/> 

<call-object-method method-name="indexOf" obj-field="newString" ret-field="retObject"> 
<string value=":"></string> 
</call-object-method>    
<log level="info" message="${retObject}"> 
call-object-method 调用参数对象的方法。 
:obj-field:参数对象名称。 
:method-name:参数对象的方法名称。 
:ret-field:返回值。 
:string:输入参数。<string value=":"></string> 。field 同样是做为输入参数。 
4.9. call-simple-method 
  <call-simple-method method-name="getGlArithmeticSettingsInline" xml-resource="component://accounting/script/org/ofbiz/accounting/ ledger/GeneralLedgerServices.xml"/> 

call-simple-method 直接调用simple method ,不是以service 的形式调用。如果被调用simple-method 与当前service 在同一个xml文件中xml-resource 可以不用写。 
5. 其他 
5.1. now-date-to-env 
<now-date-to-env field="nowDate"/> 
将当前日期(不带时间)赋值给变量参数now.格式为yyyy-MM-dd 
   
5.2. now-timestamp 
   <now-timestamp field="nowTime"/> 
将当前日期时间赋值给变量参数nowTime,格式为yyyy-MM-dd HH:mm:ss.sss 
5.3. to-string 
将参数转化成string 格式。待确定。 
5.4. log 
输出日志。前面已经用到很多了 ,不重复了 。 

5.5. Order-map-list 
<clear-field field="newParamMap"/> 
<set field="newParamMap.param1" value="param1"/> 
<set field="newParamMap.param2" value="param2"/> 
<set field="newParamMap.param3" value="param3"/> 

<clear-field field="newParamMap1"/> 
<set field="newParamMap1.param1" value="param4"/> 
<set field="newParamMap1.param2" value="param5"/> 
<set field="newParamMap1.param3" value="param6"/> 

<clear-field field="newParamMap2"/> 
<set field="newParamMap2.param1" value="param7"/> 
<set field="newParamMap2.param2" value="param8"/> 
<set field="newParamMap2.param3" value="param9"/> 


<set field="newList[]" from-field="newParamMap"/> 
<set field="newList[]" from-field="newParamMap1"/> 
<set field="newList[]" from-field="newParamMap2"/> 

<order-map-list list="newList" > 
<order-by field-name="-param1"/> 
</order-map-list> 
<log level="info" message="${newList}"></log> 
order-map-list 以一个list 中map的key为标准对这个list 中各个map 进行排序。 

5.6. order-value-list 
order-value-list 待定。 

5.7. transaction-begin 

开启事务。 
:began-transaction-name:对当前事务取个别名,如果只有一个事务的话,可以使用默认值。 
5.8. transaction-commit 
提交事务,如果有多个事务可以根据began-transaction-name进行选择事务提交。 

5.9. transaction-rollback 
事务回滚。如果有多个事务可以根据began-transaction-name进行选择事务回滚。 

原文地址:https://www.cnblogs.com/lovenan/p/3253067.html