Packages
bpe
4.10.7
13.5.22-aleph
11.4.16
11.4.15
11.4.14
11.4.13
9.9.7
9.9.6
8.12.4
8.12.3
8.12.1
8.12.0
retired
8.2.1
8.2.0
8.1.0
7.11.0
7.10.4
7.10.3
7.10.2
7.10.1
7.9.1
7.9.0
7.8.2
7.8.1
7.8.0
7.6.4
7.6.3
7.6.2
7.6.1
7.6.0
7.5.15
7.5.14
7.5.13
7.5.12
7.5.11
7.5.10
7.5.9
7.5.8
7.5.7
7.5.6
7.5.5
7.5.3
7.5.2
7.5.1
7.5.0
7.4.11
7.4.10
7.4.9
7.4.8
7.4.7
7.4.6
7.4.5
7.4.4
7.4.3
7.4.2
7.4.1
7.4.0
7.3.0
7.2.8
7.2.7
7.2.6
7.1.6
7.1.5
7.1.4
7.1.3
7.1.2
6.12.7
6.12.6
6.12.5
6.12.3
6.12.2
6.12.1
6.12.0
6.11.0
6.10.0
6.5.3
6.5.2
6.5.1
6.5.0
6.4.0
6.3.0
5.12.0
5.11.4
5.11.3
5.11.2
5.11.1
5.11.0
5.8.7
5.8.6
5.8.5
5.8.4
5.8.3
5.8.2
5.8.1
5.8.0
5.7.0
5.6.0
5.5.2
5.5.1
5.4.0
5.2.0
5.1.3
5.1.2
5.1.1
4.12.4
4.12.3
4.12.2
4.12.1
4.12.0
4.11.8
4.11.7
4.11.6
4.11.5
4.11.4
4.11.3
4.11.2
4.11.1
4.11.0
4.10.24
4.10.23
4.10.22
4.10.21
4.10.20
4.10.19
4.10.18
4.10.17
4.10.16
4.10.15
4.10.14
4.10.13
4.10.12
4.10.11
4.10.10
4.10.9
4.10.8
4.10.7
4.10.6
4.10.5
4.10.4
4.10.3
4.10.2
4.10.1
4.10.0
4.9.18
4.9.17
4.9.16
4.9.15
4.9.14
4.9.13
4.9.12
4.9.11
4.9.10
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.1
4.8.0
4.7.5
4.7.3
4.7.2
4.7.1
4.7.0
4.6.0
2.4.0
0.7.16
ERP/1: RTP GST WebRTC ICE SDP H.264 H.265 MP4 MPEG-2 HLS HEVC
Current section
Files
Jump to
Current section
Files
src/ext/bpe_xml.erl
-module(bpe_xml).
-include_lib("bpe/include/bpe.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-compile(export_all).
-import(lists,[keyfind/3, keyreplace/4]).
attr(E) -> [ {N,V} || #xmlAttribute{name=N,value=V} <- E].
%%It is expected that bpmn:flowNodeRef are present only in bpmn:lane and only #xmlText{} and #xmlElement{name='bpmn:flowNodeRef'} are present there
find(E=[#xmlText{}, #xmlElement{name='bpmn:flowNodeRef'} | _],[]) ->
[ {X,[],{value,V}} || #xmlElement{name=X,content=[#xmlText{value=V}]} <- E];
find(E,[]) -> [ {X,find(Sub,[]),attr(A)} || #xmlElement{name=X,attributes=A,content=Sub} <- E];
find(E, I) -> [ {X,find(Sub,[]),attr(A)} || #xmlElement{name=X,attributes=A,content=Sub} <- E, X == I].
def() -> load("priv/sample.bpmn").
load(File) -> load(File, ?MODULE).
load(File,Module) ->
{ok,Bin} = file:read_file(File),
_Y = {#xmlElement{name=N,content=C}=_X,_} = xmerl_scan:string(binary_to_list(Bin)),
_E = {'bpmn:definitions',[{'bpmn:process',Elements,Attrs}],_} = {N,find(C,'bpmn:process'),attr(C)},
Name = proplists:get_value(id,Attrs),
Proc = reduce(Elements,#process{name=Name},Module),
Tasks = fillInOut(Proc#process.tasks, Proc#process.flows),
Tasks1 = fixRoles(Tasks, Proc#process.roles),
Proc#process{ id=[],
tasks = Tasks1,
roles=[],
events = [ #boundaryEvent{name='*', timeout=#timeout{spec={0,{0,30,0}}}}
| Proc#process.events ] }.
reduce([], Acc, _Module) ->
Acc;
reduce([{'bpmn:task',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#task{module=Module,name=Name}|Tasks]}, Module);
reduce([{'bpmn:startEvent',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#beginEvent{module=Module,name=Name}|Tasks],beginEvent=Name}, Module);
reduce([{'bpmn:endEvent',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#endEvent{module=Module,name=Name}|Tasks],endEvent=Name}, Module);
reduce([{'bpmn:sequenceFlow',_Body,Attrs}|T],#process{flows=Flows} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
Source = proplists:get_value(sourceRef,Attrs),
Target = proplists:get_value(targetRef,Attrs),
reduce(T,Process#process{flows=[#sequenceFlow{name=Name,source=Source,target=Target}|Flows]}, Module);
reduce([{'bpmn:parallelGateway',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#gateway{module=Module,name=Name,type=parallel}|Tasks]}, Module);
reduce([{'bpmn:exclusiveGateway',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#gateway{module=Module,name=Name,type=exclusive}|Tasks]}, Module);
reduce([{'bpmn:inclusiveGateway',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#gateway{module=Module,name=Name,type=inclusive}|Tasks]}, Module);
reduce([{'bpmn:complexGateway',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#gateway{module=Module,name=Name,type=complex}|Tasks]}, Module);
reduce([{'bpmn:gateway',_Body,Attrs}|T],#process{tasks=Tasks} = Process, Module) ->
Name = proplists:get_value(id,Attrs),
reduce(T,Process#process{tasks=[#gateway{module=Module,name=Name,type=none}|Tasks]}, Module);
reduce([{'bpmn:laneSet',Lanes,_Attrs}|T], Process, Module) ->
reduce(T,Process#process{roles = Lanes}, Module);
%%TODO? Maybe add support for those intries and remove them from this guard
reduce([{SkipType,_Body,_Attrs}|T],#process{} = Process, Module)
when SkipType == 'bpmn:dataObjectReference';
SkipType == 'bpmn:dataObject';
SkipType == 'bpmn:association';
SkipType == 'bpmn:textAnnotation' ->
skip,
reduce(T,Process, Module).
%%TODO?: Maybe use incoming/outgoing from XML itself instead of fillInOut
fillInOut(Tasks, []) -> Tasks;
fillInOut(Tasks, [#sequenceFlow{name=Name,source=Source,target=Target}|Flows]) ->
Tasks1 = key_push_value(Name, #gateway.out, Source, #gateway.name, Tasks),
Tasks2 = key_push_value(Name, #gateway.in, Target, #gateway.name, Tasks1),
fillInOut(Tasks2, Flows).
key_push_value(Value, ValueKey, ElemId, ElemIdKey, List) ->
Elem = keyfind(ElemId, ElemIdKey, List),
RecName = hd(tuple_to_list(Elem)),
if
RecName == beginEvent -> List;
RecName == endEvent -> List;
true ->
NewElem = setelement(ValueKey, Elem, [Value|element(ValueKey,Elem)]),
keyreplace(ElemId, ElemIdKey, List, NewElem)
end.
fixRoles(Tasks, []) -> Tasks;
fixRoles(Tasks, [Lane|Lanes]) ->
LaneAttributes = element(3,Lane),
RoleName = proplists:get_value(name,LaneAttributes),
Role = list_to_atom(RoleName),
TaskIdsToUpdateRoles = [T || {'bpmn:flowNodeRef',[],{value,T}} <- element(2,Lane)],
fixRoles(update_roles(TaskIdsToUpdateRoles, Tasks, Role), Lanes).
update_roles([], AllTasks, _Role) -> AllTasks;
update_roles([TaskId|Rest], AllTasks, Role) ->
update_roles(Rest,key_push_value(Role, #task.roles, TaskId, #task.name, AllTasks),Role).
action({request,_,_},P) -> {reply,P}.
auth(_) -> true.