Packages
mozart
0.2.10
1.0.1
1.0.0
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Mozart is an Elixir based BPM platform. It provides a powerful and highly readable DSL for implementing executable business process models.
Current section
Files
Jump to
Current section
Files
lib/mozart/bpm_process.ex
defmodule Mozart.BpmProcess do
alias Mozart.Task.Service
alias Mozart.Task.User
alias Mozart.Task.Subprocess
alias Mozart.Task.Parallel
alias Mozart.Task.Service
alias Mozart.Task.Rule
alias Mozart.Task.Case
alias Mozart.Task.Receive
alias Mozart.Task.Send
alias Mozart.Task.Timer
alias Mozart.Data.ProcessModel
defmacro __using__(_opts) do
quote do
import Mozart.BpmProcess
@tasks []
@processes []
@capture_subtasks false
@subtasks []
@subtask_sets []
@before_compile Mozart.BpmProcess
end
end
@doc """
Used to implement a business process model. Arguments are a name followed by one or
more task functions. Example:
```
defprocess "two timer task process" do
timer_task("one second timer task", duration: 1000)
timer_task("two second timer task", duration: 2000)
end
```
"""
defmacro defprocess(name, do: body) do
quote do
process = %ProcessModel{name: unquote(name)}
unquote(body)
tasks = set_next_tasks(@tasks)
tasks = tasks ++ List.flatten(@subtask_sets)
process = Map.put(process, :tasks, tasks)
initial_task_name = Map.get(hd(tasks), :name)
process = Map.put(process, :initial_task, initial_task_name)
@processes [process | @processes]
@tasks []
@subtasks []
@subtask_sets []
end
end
@doc false
def set_next_tasks([task]), do: [task]
def set_next_tasks([task1, task2 | rest]) do
task1 = Map.put(task1, :next, task2.name)
[task1 | set_next_tasks([task2 | rest])]
end
@doc false
defmacro insert_new_task(task) do
quote do
if @capture_subtasks do
@subtasks @subtasks ++ [unquote(task)]
else
@tasks @tasks ++ [unquote(task)]
end
end
end
defmacro parallel_task(name, routes) do
quote do
task = %Parallel{name: unquote(name), multi_next: unquote(routes)}
insert_new_task(task)
end
end
defmacro route(do: tasks) do
quote do
@capture_subtasks true
unquote(tasks)
first = hd(@subtasks)
@subtasks set_next_tasks(@subtasks)
@subtask_sets [@subtasks | @subtask_sets]
@subtasks []
@capture_subtasks false
first.name
end
end
@doc false
def parse_inputs(inputs_string) do
Enum.map(String.split(inputs_string, ","), fn input -> String.to_atom(input) end)
end
@doc false
def parse_user_groups(groups_string) do
String.split(groups_string, ",")
end
defmacro case_task(name, cases) do
quote do
case_task = %Case{name: unquote(name), cases: unquote(cases)}
insert_new_task(case_task)
end
end
defmacro case_i(expr, do: tasks) do
quote do
@capture_subtasks true
unquote(tasks)
first = hd(@subtasks)
@subtasks set_next_tasks(@subtasks)
@subtask_sets [@subtasks | @subtask_sets]
@subtasks []
@capture_subtasks false
%{expression: unquote(expr), next: first.name}
end
end
defmacro timer_task(name, duration: duration) do
quote do
task = %Timer{name: unquote(name), timer_duration: unquote(duration)}
insert_new_task(task)
end
end
defmacro rule_task(name, inputs: inputs, rule_table: rule_table) do
quote do
inputs = parse_inputs(unquote(inputs))
rule_table = Tablex.new(unquote(rule_table))
rule_task = %Rule{name: unquote(name), inputs: inputs, rule_table: rule_table}
insert_new_task(rule_task)
end
end
defmacro subprocess_task(name, model: subprocess_name) do
quote do
subprocess =
%Subprocess{name: unquote(name), sub_process_model_name: unquote(subprocess_name)}
insert_new_task(subprocess)
end
end
defmacro send_task(name, message: message) do
quote do
task = %Send{name: unquote(name), message: unquote(message)}
insert_new_task(task)
end
end
defmacro service_task(name, function: func, inputs: inputs) do
quote do
function = unquote(func)
inputs = parse_inputs(unquote(inputs))
service =
%Service{name: unquote(name), function: function, inputs: inputs}
insert_new_task(service)
end
end
defmacro receive_task(name, selector: function) do
quote do
task = %Receive{name: unquote(name), message_selector: unquote(function)}
insert_new_task(task)
end
end
defmacro user_task(name, groups: groups) do
quote do
groups = parse_user_groups(unquote(groups))
user_task = %User{name: unquote(name), assigned_groups: groups}
insert_new_task(user_task)
end
end
defmacro __before_compile__(_env) do
quote do
def get_processes, do: Enum.reverse(@processes)
def get_process(name), do: Enum.find(@processes, fn p -> p.name == name end)
def load_processes do
process_names = Enum.map(@processes, fn p -> p.name end)
IO.puts("loading processes[#{inspect(process_names)}]")
end
end
end
end