aconfgen: поддержка Alfresco 4.0
Немного обновил aconfgen: теперь он должен корректно работать с Alfresco 4.0.
В новой версии изменения следующие:
- добавлена возможность работы с процессами, написанными для Activiti
- добавлена возможность генерировать локализацию модели
Итак, по порядку о нововведениях. Пусть у нас есть вот такое описание процесса:
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://activiti.org/bpmn20"> <process id="example" name="Parallel Review And Approve Activiti Process"> <extensionElements> <activiti:executionListener event="start" class="org.alfresco.repo.workflow.activiti.listener.ScriptExecutionListener"> <activiti:field name="script"> <activiti:string>execution.setVariable('wf_approveCount', 0); execution.setVariable('wf_actualPercent', 0); execution.setVariable('wf_reviewerCount', bpm_assignees.size()); execution.setVariable('wf_requiredPercent', wf_requiredApprovePercent);</activiti:string> </activiti:field> </activiti:executionListener> </extensionElements> <startEvent id="start" name="Start" activiti:formKey="wf:submitParallelReviewTask"></startEvent> <userTask id="reviewTask" name="Review Task" activiti:assignee="${reviewAssignee.properties.userName}" activiti:formKey="wf:activitiReviewTask"> <extensionElements> <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener"> <activiti:field name="script"> <activiti:string>if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate); if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;</activiti:string> </activiti:field> </activiti:taskListener> <activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener"> <activiti:field name="script"> <activiti:string>if(task.getVariableLocal('wf_reviewOutcome') == 'Approve') { var newApprovedCount = wf_approveCount + 1; var newApprovedPercentage = (newApprovedCount / wf_reviewerCount) * 100; execution.setVariable('wf_approveCount', newApprovedCount); execution.setVariable('wf_actualPercent', newApprovedPercentage); }</activiti:string> </activiti:field> </activiti:taskListener> </extensionElements> <multiInstanceLoopCharacteristics isSequential="false"> <loopDataInputRef>bpm_assignees</loopDataInputRef> <inputDataItem name="reviewAssignee"></inputDataItem> <completionCondition>${wf_actualPercent >= wf_requiredApprovePercent}</completionCondition> </multiInstanceLoopCharacteristics> </userTask> <exclusiveGateway id="reviewDecision" name="Review Decision"></exclusiveGateway> <userTask id="approved" name="Document Approved" activiti:assignee="${initiator.properties.userName}" activiti:formKey="wf:approvedParallelTask"> <documentation> The document was reviewed and approved. </documentation> <extensionElements> <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener"> <activiti:field name="script"> <activiti:string>if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate); if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority; // Set parallel review params on task, to be kept in history task.setVariableLocal('wf_reviewerCount', wf_reviewerCount); task.setVariableLocal('wf_requiredPercent', wf_requiredPercent); task.setVariableLocal('wf_actualPercent', wf_actualPercent); task.setVariableLocal('wf_approveCount', wf_approveCount);</activiti:string> </activiti:field> </activiti:taskListener> </extensionElements> </userTask> <userTask id="rejected" name="Document Rejected" activiti:assignee="${initiator.properties.userName}" activiti:formKey="wf:rejectedParallelTask"> <documentation> The document was reviewed and rejected. </documentation> <extensionElements> <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener"> <activiti:field name="script"> <activiti:string>if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate); if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority; // Set parallel review params on task, to be kept in history task.setVariableLocal('wf_reviewerCount', wf_reviewerCount); task.setVariableLocal('wf_requiredPercent', wf_requiredPercent); task.setVariableLocal('wf_actualPercent', wf_actualPercent); task.setVariableLocal('wf_approveCount', wf_approveCount);</activiti:string> </activiti:field> </activiti:taskListener> </extensionElements> </userTask> <endEvent id="end" name="End"></endEvent> <sequenceFlow id="flow1" name="" sourceRef="start" targetRef="reviewTask"></sequenceFlow> <sequenceFlow id="flow2" name="" sourceRef="reviewTask" targetRef="reviewDecision"></sequenceFlow> <sequenceFlow id="flow3" name="" sourceRef="reviewDecision" targetRef="approved"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_actualPercent >= wf_requiredApprovePercent}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flow4" name="" sourceRef="reviewDecision" targetRef="rejected"></sequenceFlow> <sequenceFlow id="flow5" name="" sourceRef="approved" targetRef="end"></sequenceFlow> <sequenceFlow id="flow6" name="" sourceRef="rejected" targetRef="end"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_example"><!-- Диаграмма вырезана за ненадобностью --></bpmndi:BPMNDiagram> </definitions>
По-моему, писать такие процессы «руками» теперь просто нереально. Ну да ладно. При помощи команды
./aconfgen.py -mMdiafcr ~/example.bpmn20.xml
получаем вот такую модель:
<?xml version="1.0" encoding="utf-8"?> <model xmlns="http://www.alfresco.org/model/dictionary/1.0" name="wf:samplemodel"> <!--Model metadata--> <description>Task model for example.bpmn20.xml</description> <author>lx</author> <version>1.0</version> <!--Import necessary namespaces--> <imports> <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/> <import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/> </imports> <!--List of found namespaces in process definition--> <namespaces> <namespace prefix="wf" uri="https://github.com/fufler/aconfgen/prefix/wf"/> </namespaces> <!--List of types--> <types> <!--Type for wf:submitParallelReviewTask task--> <type name="wf:submitParallelReviewTask"> <parent>bpm:startTask</parent> <!--overrides default properties values--> <overrides> <property name="bpm:packageItemActionGroup"> <default>edit_package_item_actions</default> </property> </overrides> <!--Task mandatory aspects--> <mandatory-aspects> <aspect>wf:customAspect</aspect> </mandatory-aspects> </type> <!--Type for wf:rejectedParallelTask task--> <type name="wf:rejectedParallelTask"> <parent>bpm:activitiOutcomeTask</parent> <!--Add outcome property for activiti tasks--> <properties> <property name="wf:rejectedParallelTaskOutcome"> <type>d:text</type> <default>done</default> <constraints> <constraint type="LIST" name="wf:rejectedParallelTaskOutcomeConstraint"> <parameter name="allowedValues"> <list> <value>done</value> </list> </parameter> </constraint> </constraints> </property> </properties> <!--overrides default properties values--> <overrides> <property name="bpm:packageItemActionGroup"> <default>edit_package_item_actions</default> </property> <property name="bpm:outcomePropertyName"> <default>{https://github.com/fufler/aconfgen/prefix/wf}rejectedParallelTask</default> </property> </overrides> <!--Task mandatory aspects--> <mandatory-aspects> <aspect>wf:customAspect</aspect> </mandatory-aspects> </type> <!--Type for wf:activitiReviewTask task--> <type name="wf:activitiReviewTask"> <parent>bpm:activitiOutcomeTask</parent> <!--Add outcome property for activiti tasks--> <properties> <property name="wf:activitiReviewTaskOutcome"> <type>d:text</type> <default>approved</default> <constraints> <constraint type="LIST" name="wf:activitiReviewTaskOutcomeConstraint"> <parameter name="allowedValues"> <list> <value>approved</value> <value>rejected</value> </list> </parameter> </constraint> </constraints> </property> </properties> <!--overrides default properties values--> <overrides> <property name="bpm:packageItemActionGroup"> <default>edit_package_item_actions</default> </property> <property name="bpm:outcomePropertyName"> <default>{https://github.com/fufler/aconfgen/prefix/wf}activitiReviewTask</default> </property> </overrides> <!--Task mandatory aspects--> <mandatory-aspects> <aspect>wf:customAspect</aspect> </mandatory-aspects> </type> <!--Type for wf:approvedParallelTask task--> <type name="wf:approvedParallelTask"> <parent>bpm:activitiOutcomeTask</parent> <!--Add outcome property for activiti tasks--> <properties> <property name="wf:approvedParallelTaskOutcome"> <type>d:text</type> <default>done</default> <constraints> <constraint type="LIST" name="wf:approvedParallelTaskOutcomeConstraint"> <parameter name="allowedValues"> <list> <value>done</value> </list> </parameter> </constraint> </constraints> </property> </properties> <!--overrides default properties values--> <overrides> <property name="bpm:packageItemActionGroup"> <default>edit_package_item_actions</default> </property> <property name="bpm:outcomePropertyName"> <default>{https://github.com/fufler/aconfgen/prefix/wf}approvedParallelTask</default> </property> </overrides> <!--Task mandatory aspects--> <mandatory-aspects> <aspect>wf:customAspect</aspect> </mandatory-aspects> </type> </types> <!--Custom aspect definition sample--> <aspects> <aspect name="wf:customAspect"> <title>Custom aspect sample</title> <properties> <property name="wf:customProperty"> <type>d:string</type> <mandatory>false</mandatory> <multiple>false</multiple> </property> </properties> </aspect> </aspects> </model>
Как видно из примера, для Activiti-процессов в модели автоматические генерируются bpm:outcomePropertyName и соответствующий constraint, для JPDL-процессов всё осталось попрежнему. Constraint генерируется следующим образом: если после таска в описании есть Exclusive Gateway, то значениями constraint становятся названия всех тасков, непосредственно следующих за ним; если следующий элемент не Exclusive Gateway, но в constraint попадает только одно значение — «done».
В версии 4.0 немного изменилась схема локализации: теперь большая часть локализации генерируется по модели, а не по описанию процесса. По описанию Activiti-процесса генерируются всего две строки:
./aconfgen.py -W ~/example.bpmn20.xml
example.workflow.title= example.workflow.description=
Зато достаточно много строк можно нагенерировать по модели:
./aconfgen.py -mMdia ~/example.bpmn20.xml | ./aconfgen.py -Z -
wf_samplemodel.title= wf_samplemodel.description= wf_samplemodel.type.wf_submitParallelReviewTask.title= wf_samplemodel.type.wf_submitParallelReviewTask.description= wf_samplemodel.type.wf_rejectedParallelTask.title= wf_samplemodel.type.wf_rejectedParallelTask.description= wf_samplemodel.type.wf_activitiReviewTask.title= wf_samplemodel.type.wf_activitiReviewTask.description= wf_samplemodel.type.wf_approvedParallelTask.title= wf_samplemodel.type.wf_approvedParallelTask.description= wf_samplemodel.aspect.wf_customAspect.title= wf_samplemodel.aspect.wf_customAspect.description= wf_samplemodel.property.wf_rejectedParallelTaskOutcome.title= wf_samplemodel.property.wf_rejectedParallelTaskOutcome.description= wf_samplemodel.property.wf_activitiReviewTaskOutcome.title= wf_samplemodel.property.wf_activitiReviewTaskOutcome.description= wf_samplemodel.property.wf_approvedParallelTaskOutcome.title= wf_samplemodel.property.wf_approvedParallelTaskOutcome.description= wf_samplemodel.property.wf_customProperty.title= wf_samplemodel.property.wf_customProperty.description= listconstraint.wf_rejectedParallelTaskOutcomeConstraint.done= listconstraint.wf_activitiReviewTaskOutcomeConstraint.approved= listconstraint.wf_activitiReviewTaskOutcomeConstraint.rejected= listconstraint.wf_approvedParallelTaskOutcomeConstraint.done=
Новая версия скрипта пока что находится в состоянии альфа-версии, так не было возможности потестировать в «боевых» условиях. Вроде вывод скрипта сходится с примерами от Jeff Potts и тем, что написано на вики. Об ошибках пишите в комменты — исправлю.
Адрес проживания скрипта остался прежним. Новую версию смотрите в бранче 4.0.
Комментарии
30/08/2013 - 09:44
08/09/2013 - 07:40
Какая версия python?
Какая версия aconfgen?