Skip to content

Commit

Permalink
Merge pull request #183 from ProcessMaker/develop
Browse files Browse the repository at this point in the history
Add Conditional Events
  • Loading branch information
caleeli authored Sep 30, 2020
2 parents 9476e7d + 886a230 commit 405940e
Show file tree
Hide file tree
Showing 61 changed files with 1,279 additions and 478 deletions.
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "processmaker/nayra",
"description": "BPMN compliant engine",
"version": "1.0.3",
"version": "1.1.0",
"license": "Apache-2.0",
"autoload": {
"psr-4": {
Expand All @@ -18,7 +18,10 @@
]
}
},
"scripts": {
"test": "phpunit"
},
"require-dev": {
"phpunit/phpunit": "^5.7"
}
}
}
10 changes: 7 additions & 3 deletions src/ProcessMaker/Nayra/Bpmn/ActivitySubProcessTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ protected function initActivity()
$this->attachEvent(
ActivityInterface::EVENT_ACTIVITY_ACTIVATED,
function ($self, TokenInterface $token) {
$instance = $this->callSubprocess();
$instance = $this->callSubprocess($token);
$this->linkProcesses($token, $instance);
}
);
Expand All @@ -36,11 +36,15 @@ function ($self, TokenInterface $token) {
/**
* Call the subprocess
*
* @param \ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface $token
*
* @return ExecutionInstanceInterface
*/
protected function callSubprocess()
protected function callSubprocess(TokenInterface $token)
{
return $this->getCalledElement()->call();
$dataStore = $this->getRepository()->createDataStore();
$dataStore->setData($token->getInstance()->getDataStore()->getData());
return $this->getCalledElement()->call($dataStore);
}

/**
Expand Down
7 changes: 3 additions & 4 deletions src/ProcessMaker/Nayra/Bpmn/ActivityTransition.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace ProcessMaker\Nayra\Bpmn;

use ProcessMaker\Nayra\Bpmn\TransitionTrait;
use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TransitionInterface;
Expand All @@ -15,17 +14,17 @@
*/
class ActivityTransition implements TransitionInterface
{

use TransitionTrait;

/**
* Condition required to transit the element.
*
* @param TokenInterface $token
* @param TokenInterface|null $token
* @param \ProcessMaker\Nayra\Contracts\Engine\ExecutionInstanceInterface|null $executionInstance
*
* @return bool
*/
public function assertCondition(TokenInterface $token = null, ExecutionInstanceInterface $executionInstance)
public function assertCondition(TokenInterface $token = null, ExecutionInstanceInterface $executionInstance = null)
{
return $token->getStatus() === ActivityInterface::TOKEN_STATE_COMPLETED;
}
Expand Down
5 changes: 3 additions & 2 deletions src/ProcessMaker/Nayra/Bpmn/BaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use ProcessMaker\Nayra\Contracts\Repositories\StorageInterface;
use ProcessMaker\Nayra\Contracts\RepositoryInterface;
use ProcessMaker\Nayra\Contracts\Storage\BpmnDocumentInterface;
use ProcessMaker\Nayra\Contracts\Storage\BpmnElementInterface;
use ReflectionClass;

Expand Down Expand Up @@ -89,7 +90,7 @@ public function setRepository(RepositoryInterface $repository)
/**
* Get the owner BPMN document of this object.
*
* @return \ProcessMaker\Nayra\Contracts\StorageInterface
* @return \ProcessMaker\Nayra\Contracts\StorageInterface|BpmnDocumentInterface
*/
public function getOwnerDocument()
{
Expand Down Expand Up @@ -122,7 +123,7 @@ public function getBpmnElement()
/**
* Set DOM element of this object.
*
* @param \ProcessMaker\Nayra\Contracts\Repositories\StorageInterface $ownerDocument
* @param \ProcessMaker\Nayra\Contracts\Storage\BpmnElementInterface $bpmnElement
*
* @return $this
*/
Expand Down
59 changes: 19 additions & 40 deletions src/ProcessMaker/Nayra/Bpmn/BoundaryEventTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
use ProcessMaker\Nayra\Bpmn\Models\ErrorEventDefinition;
use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\BoundaryEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\CatchEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ErrorEventDefinitionInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ErrorInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\EventDefinitionInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\FlowInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\StateInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface;
use ProcessMaker\Nayra\Contracts\Engine\EngineInterface;
use ProcessMaker\Nayra\Contracts\Engine\ExecutionInstanceInterface;
use ProcessMaker\Nayra\Contracts\RepositoryInterface;

/**
Expand All @@ -26,8 +23,6 @@ trait BoundaryEventTrait
{
use CatchEventTrait;

private $triggerPlace;

/**
* Build the transitions that define the element.
*
Expand All @@ -36,25 +31,16 @@ trait BoundaryEventTrait
public function buildTransitions(RepositoryInterface $factory)
{
$this->setRepository($factory);
$this->triggerPlace = new State($this, CatchEventInterface::TOKEN_STATE_EVENT_CATCH);
$this->transition = new Transition($this);
$this->triggerPlace->connectTo($this->transition);

$this->triggerPlace->attachEvent(State::EVENT_TOKEN_ARRIVED, function (TokenInterface $token) {
$this->getRepository()
->getTokenRepository()
->persistCatchEventMessageArrives($this, $token);
$this->notifyEvent(BoundaryEventInterface::EVENT_BOUNDARY_EVENT_CATCH, $this, $token);
});
$this->buildEventDefinitionsTransitions(
BoundaryEventInterface::EVENT_BOUNDARY_EVENT_CATCH,
BoundaryEventInterface::EVENT_BOUNDARY_EVENT_CONSUMED
);

$this->transition->attachEvent(Transition::EVENT_AFTER_TRANSIT, function ($transition, Collection $tokens) {
foreach($tokens as $token) {
$this->getRepository()
->getTokenRepository()
->persistCatchEventMessageConsumed($this, $token);
$this->notifyEvent(BoundaryEventInterface::EVENT_BOUNDARY_EVENT_CONSUMED, $this, $token);

$this->getProcess()->getEngine()->nextState(function () use($token) {
foreach ($tokens as $token) {
$this->getProcess()->getEngine()->nextState(function () use ($token) {
// Cancel the attachedTo activity
if ($this->getCancelActivity()) {
foreach ($this->getAttachedTo()->getTokens($token->getInstance()) as $token) {
Expand Down Expand Up @@ -91,23 +77,6 @@ protected function buildConnectionTo(FlowInterface $targetFlow)
return $this;
}

/**
* To implement the MessageListener interface
*
* @param EventDefinitionInterface $message
* @param ExecutionInstanceInterface|null $instance
*
* @return $this
*/
public function execute(EventDefinitionInterface $message, ExecutionInstanceInterface $instance = null)
{
if ($instance !== null && $this->getAttachedTo()->getActiveState()->getTokens($instance)->count() > 0) {
// with a new token in the trigger place, the event catch element will be fired
$this->triggerPlace->addNewToken($instance);
}
return $this;
}

/**
* Register the BPMN elements with the engine.
*
Expand All @@ -126,7 +95,7 @@ public function registerWithEngine(EngineInterface $engine)
}
// Schedule timer events when Activity is Activated
$this->getAttachedTo()->attachEvent(ActivityInterface::EVENT_ACTIVITY_ACTIVATED, function (ActivityInterface $activity, TokenInterface $token) {
$this->scheduleTimerEvents($token);
$this->activateCatchEvent($token);
});
// Catch EVENT_ACTIVITY_EXCEPTION
$this->getAttachedTo()->attachEvent(ActivityInterface::EVENT_ACTIVITY_EXCEPTION, function (ActivityInterface $activity, TokenInterface $token) {
Expand All @@ -146,10 +115,10 @@ private function catchErrorEvent(TokenInterface $token, ErrorInterface $error =
{
$errorDef = new ErrorEventDefinition();
$error ? $errorDef->setError($error) : null;
foreach ($this->getEventDefinitions() as $eventDefinition) {
foreach ($this->getEventDefinitions() as $index => $eventDefinition) {
if ($eventDefinition instanceof ErrorEventDefinitionInterface
&& $eventDefinition->shouldCatchEventDefinition($errorDef)) {
$this->triggerPlace->addNewToken($token->getInstance());
$this->triggerPlace[$index]->addNewToken($token->getInstance());
}
}
}
Expand Down Expand Up @@ -197,4 +166,14 @@ public function setAttachedTo(ActivityInterface $activity)
{
return $this->setProperty(BoundaryEventInterface::BPMN_PROPERTY_ATTACHED_TO, $activity);
}

/**
* Get the active state of the element
*
* @return StateInterface
*/
public function getActiveState()
{
return $this->getAttachedTo()->getActiveState();
}
}
78 changes: 73 additions & 5 deletions src/ProcessMaker/Nayra/Bpmn/CatchEventTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@
namespace ProcessMaker\Nayra\Bpmn;

use ProcessMaker\Nayra\Contracts\Bpmn\CatchEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TimerEventDefinitionInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\EventDefinitionInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\StateInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface;
use ProcessMaker\Nayra\Contracts\Engine\EngineInterface;
use ProcessMaker\Nayra\Contracts\Engine\ExecutionInstanceInterface;

/**
* Implementation of the behavior for a catch event.
*
* @package ProcessMaker\Nayra\Bpmn
* @see CatchEventInterface
*/
trait CatchEventTrait
{
use FlowNodeTrait;

/**
* @var \ProcessMaker\Nayra\Contracts\Bpmn\StateInterface[]
*/
private $triggerPlace = [];

/**
* Initialize catch event.
*
Expand Down Expand Up @@ -58,12 +66,10 @@ public function registerCatchEvents(EngineInterface $engine)
*
* @return $this
*/
private function scheduleTimerEvents(TokenInterface $token = null)
private function activateCatchEvent(TokenInterface $token = null)
{
foreach ($this->getEventDefinitions() as $eventDefinition) {
if ($eventDefinition instanceof TimerEventDefinitionInterface) {
$eventDefinition->scheduleTimerEvents($this->getOwnerProcess()->getEngine(), $this, $token);
}
$eventDefinition->catchEventActivated($this->getOwnerProcess()->getEngine(), $this, $token);
}
return $this;
}
Expand All @@ -80,4 +86,66 @@ public function registerWithEngine(EngineInterface $engine)
$this->registerCatchEvents($engine);
return $this;
}

/**
* To implement the MessageListener interface
*
* @param EventDefinitionInterface $event
* @param ExecutionInstanceInterface|null $instance
* @param \ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface|null $token
*
* @return $this
*/
public function execute(EventDefinitionInterface $event, ExecutionInstanceInterface $instance = null, TokenInterface $token = null)
{
if ($instance !== null && $this->getActiveState()->getTokens($instance)->count() > 0) {
foreach ($this->getEventDefinitions() as $index => $eventDefinition) {
if ($eventDefinition->assertsRule($event, $this, $instance, $token)) {
$this->triggerPlace[$index]->addNewToken($instance);
$eventDefinition->execute($event, $this, $instance, $token);
}
}
}
return $this;
}

/**
* Get the active state of the element
*
* @return StateInterface
*/
public function getActiveState()
{
return null;
}

/**
* Build events definitions transitions
*
* @param string $catchedEventName
* @param string $consumedEventName
*
* @return void
*/
private function buildEventDefinitionsTransitions($catchedEventName, $consumedEventName)
{
$eventDefinitions = $this->getEventDefinitions();
foreach ($eventDefinitions as $index => $eventDefinition) {
$triggerPlace = new State($this, CatchEventInterface::TOKEN_STATE_EVENT_CATCH);
$triggerPlace->connectTo($this->transition);
$triggerPlace->attachEvent(State::EVENT_TOKEN_ARRIVED, function (TokenInterface $token) use ($catchedEventName) {
$this->getRepository()
->getTokenRepository()
->persistCatchEventMessageArrives($this, $token);
$this->notifyEvent($catchedEventName, $this, $token);
});
$triggerPlace->attachEvent(State::EVENT_TOKEN_CONSUMED, function (TokenInterface $token) use ($consumedEventName) {
$this->getRepository()
->getTokenRepository()
->persistCatchEventMessageConsumed($this, $token);
$this->notifyEvent($consumedEventName, $this, $token);
});
$this->triggerPlace[$index] = $triggerPlace;
}
}
}
4 changes: 2 additions & 2 deletions src/ProcessMaker/Nayra/Bpmn/CloseExceptionTransition.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ protected function initActivityTransition()
* Condition required to transit an activity in FAILING state.
*
* @param TokenInterface|null $token
* @param ExecutionInstanceInterface $executionInstance
* @param ExecutionInstanceInterface|null $executionInstance
*
* @return bool
*/
public function assertCondition(TokenInterface $token = null, ExecutionInstanceInterface $executionInstance)
public function assertCondition(TokenInterface $token = null, ExecutionInstanceInterface $executionInstance = null)
{
return $token->getStatus() === ActivityInterface::TOKEN_STATE_CLOSED;
}
Expand Down
Loading

0 comments on commit 405940e

Please sign in to comment.