Repository: ProcessMaker/nayra (php)

Issue:
Modify engine to work with multiple different BPMN documents at the same time
Remove the single storage reference in engine, and bring the possibility to work with multiple BPMN documents at the same time.


Pull request:
Modify engine to work with multiple different BPMN documents at the same time. Resolves #163
Resolves #163 

This PR includes:

- Remove single BPMN storage accessor in Engine
- Add reference to individual BPMN storage by instance
- Add reference to BPMN storage from any element


Patch:
diff --git a/src/ProcessMaker/Nayra/Bpmn/BaseTrait.php b/src/ProcessMaker/Nayra/Bpmn/BaseTrait.php
index 3723cbc..3915269 100755
--- a/src/ProcessMaker/Nayra/Bpmn/BaseTrait.php
+++ b/src/ProcessMaker/Nayra/Bpmn/BaseTrait.php
@@ -19,10 +19,17 @@ trait BaseTrait
     /**
      * Factory used to build this element.
      *
-     * @var StorageInterface $factory
+     * @var RepositoryInterface $factory
      */
     private $repository;
 
+    /**
+     * BPMN document of this object.
+     *
+     * @var StorageInterface $ownerDocument
+     */
+    private $ownerDocument;
+
     /**
      * BaseTrait constructor.
      *
@@ -72,6 +79,29 @@ trait BaseTrait
         return $this;
     }
 
+    /**
+     * Get the owner BPMN document of this object.
+     *
+     * @return \ProcessMaker\Nayra\Contracts\StorageInterface
+     */
+    public function getOwnerDocument()
+    {
+        return $this->ownerDocument;
+    }
+
+    /**
+     * Set the owner BPMN document of this object.
+     *
+     * @param \ProcessMaker\Nayra\Contracts\Repositories\StorageInterface $ownerDocument
+     *
+     * @return $this
+     */
+    public function setOwnerDocument(StorageInterface $ownerDocument)
+    {
+        $this->ownerDocument = $ownerDocument;
+        return $this;
+    }
+
     /**
      * Get properties.
      *
diff --git a/src/ProcessMaker/Nayra/Contracts/Bpmn/EntityInterface.php b/src/ProcessMaker/Nayra/Contracts/Bpmn/EntityInterface.php
index 5d0494b..2bcc875 100755
--- a/src/ProcessMaker/Nayra/Contracts/Bpmn/EntityInterface.php
+++ b/src/ProcessMaker/Nayra/Contracts/Bpmn/EntityInterface.php
@@ -2,6 +2,7 @@
 
 namespace ProcessMaker\Nayra\Contracts\Bpmn;
 
+use ProcessMaker\Nayra\Contracts\Repositories\StorageInterface;
 use ProcessMaker\Nayra\Contracts\RepositoryInterface;
 
 /**
@@ -56,7 +57,7 @@ interface EntityInterface
     public function addProperty($name, $value);
 
     /**
-     * @return \ProcessMaker\Nayra\Contracts\Repositories\StorageInterface
+     * @return \ProcessMaker\Nayra\Contracts\RepositoryInterface
      */
     public function getRepository();
 
@@ -98,4 +99,16 @@ interface EntityInterface
      * @return $this
      */
     public function setName($name);
+
+    /**
+     * @return \ProcessMaker\Nayra\Contracts\Repositories\StorageInterface
+     */
+    public function getOwnerDocument();
+
+    /**
+     * @param StorageInterface $ownerDocument
+     *
+     * @return $this
+     */
+    public function setOwnerDocument(StorageInterface $ownerDocument);
 }
diff --git a/src/ProcessMaker/Nayra/Contracts/Engine/EngineInterface.php b/src/ProcessMaker/Nayra/Contracts/Engine/EngineInterface.php
index 6c15c54..05eef9c 100755
--- a/src/ProcessMaker/Nayra/Contracts/Engine/EngineInterface.php
+++ b/src/ProcessMaker/Nayra/Contracts/Engine/EngineInterface.php
@@ -86,11 +86,11 @@ interface EngineInterface
      * Load an execution instance from the storage.
      *
      * @param string $id
-     * @param DataStoreInterface $data
+     * @param StorageInterface $storage
      *
      * @return ExecutionInstanceInterface
      */
-    public function loadExecutionInstance($id);
+    public function loadExecutionInstance($id, StorageInterface $storage);
 
     /**
      * Close all the execution instances.
@@ -115,13 +115,6 @@ interface EngineInterface
      */
     public function setDataStore(DataStoreInterface $dataStore);
 
-    /**
-     * Set the repository storage of the engine.
-     *
-     * @param StorageInterface $repository
-     */
-    public function setStorage(StorageInterface $repository);
-
     /**
      * Get the engine job manager for timer tasks and events.
      *
@@ -171,11 +164,4 @@ interface EngineInterface
      * @return EngineInterface
      */
     public function loadCollaboration(CollaborationInterface $collaboration);
-
-    /**
-     * Get the repository storage of the engine.
-     *
-     * @return StorageInterface
-     */
-    public function getStorage();
 }
diff --git a/src/ProcessMaker/Nayra/Engine/EngineTrait.php b/src/ProcessMaker/Nayra/Engine/EngineTrait.php
index b3b8596..924d933 100755
--- a/src/ProcessMaker/Nayra/Engine/EngineTrait.php
+++ b/src/ProcessMaker/Nayra/Engine/EngineTrait.php
@@ -45,8 +45,6 @@ trait EngineTrait
      */
     private $dataStore;
 
-    private $storage;
-
     protected $jobManager;
 
     /**
@@ -149,11 +147,11 @@ trait EngineTrait
      * Load an execution instance from the storage.
      *
      * @param string $id
-     * @param DataStoreInterface $data
+     * @param StorageInterface $storage
      *
      * @return ExecutionInstanceInterface|null
      */
-    public function loadExecutionInstance($id)
+    public function loadExecutionInstance($id, StorageInterface $storage)
     {
         // If exists return the already loaded instance by id 
         foreach($this->executionInstances as $executionInstance) {
@@ -163,7 +161,7 @@ trait EngineTrait
         }
         // Create and load an instance by id
         $repository = $this->getRepository()->createExecutionInstanceRepository();
-        $executionInstance = $repository->loadExecutionInstanceByUid($id, $this->getStorage());
+        $executionInstance = $repository->loadExecutionInstanceByUid($id, $storage);
         if (!$executionInstance) {
             return;
         }
@@ -279,26 +277,6 @@ trait EngineTrait
         }
     }
 
-    /**
-     * Get the repository storage of the engine.
-     *
-     * @return StorageInterface
-     */
-    public function getStorage()
-    {
-        return $this->storage;
-    }
-
-    /**
-     * Set the repository storage of the engine.
-     *
-     * @param StorageInterface $storage
-     */
-    public function setStorage(StorageInterface $storage)
-    {
-        $this->storage = $storage;
-    }
-
     /**
      * Get the engine job manager for timer tasks and events.
      *
diff --git a/src/ProcessMaker/Nayra/Storage/BpmnElement.php b/src/ProcessMaker/Nayra/Storage/BpmnElement.php
index 2fc2d60..63aff08 100644
--- a/src/ProcessMaker/Nayra/Storage/BpmnElement.php
+++ b/src/ProcessMaker/Nayra/Storage/BpmnElement.php
@@ -59,6 +59,7 @@ class BpmnElement extends DOMElement implements BpmnElementInterface
             }
         } else {
             $bpmnElement = $this->ownerDocument->getFactory()->create($classInterface);
+            $bpmnElement->setOwnerDocument($this->ownerDocument);
             $id ? $this->ownerDocument->indexBpmnElement($id, $bpmnElement) : null;
             $bpmnElement->setRepository($this->ownerDocument->getFactory());
             if ($bpmnElement instanceof CallableElementInterface) {


Test patch:
diff --git a/tests/Feature/Engine/LoadExecutionInstancesTest.php b/tests/Feature/Engine/LoadExecutionInstancesTest.php
index 881a11f..c81a139 100644
--- a/tests/Feature/Engine/LoadExecutionInstancesTest.php
+++ b/tests/Feature/Engine/LoadExecutionInstancesTest.php
@@ -127,14 +127,13 @@ class LoadExecutionInstancesTest extends EngineTestCase
         $bpmnRepository->setEngine($this->engine);
         $bpmnRepository->setFactory($this->repository);
         $this->engine->setRepository($this->repository);
-        $this->engine->setStorage($bpmnRepository);
         $bpmnRepository->load(__DIR__ . '/files/LoadTokens.bpmn');
 
         //Set test data to load the sequential process
         $this->prepareSequentialProcess($bpmnRepository);
 
         //Load the execution instance
-        $instance = $this->engine->loadExecutionInstance('executionInstanceId');
+        $instance = $this->engine->loadExecutionInstance('executionInstanceId', $bpmnRepository);
 
         //Get References by id
         $secondActivity = $bpmnRepository->getScriptTask('second');
@@ -166,14 +165,13 @@ class LoadExecutionInstancesTest extends EngineTestCase
         $bpmnRepository->setEngine($this->engine);
         $bpmnRepository->setFactory($this->repository);
         $this->engine->setRepository($this->repository);
-        $this->engine->setStorage($bpmnRepository);
         $bpmnRepository->load(__DIR__ . '/files/LoadTokens.bpmn');
 
         //Set test data to load the sequential process
         $this->prepareParallelProcess($bpmnRepository);
 
         //Load the execution instance
-        $instance = $this->engine->loadExecutionInstance('otherExecutionInstanceId');
+        $instance = $this->engine->loadExecutionInstance('otherExecutionInstanceId', $bpmnRepository);
 
         //Get References by id
         $secondActivity = $bpmnRepository->getScriptTask('task2');
@@ -220,14 +218,13 @@ class LoadExecutionInstancesTest extends EngineTestCase
         $bpmnRepository->setEngine($this->engine);
         $bpmnRepository->setFactory($this->repository);
         $this->engine->setRepository($this->repository);
-        $this->engine->setStorage($bpmnRepository);
         $bpmnRepository->load(__DIR__ . '/files/LoadTokens.bpmn');
 
         //Set test data to load the sequential process
         $this->prepareParallelProcessWithActivityCompleted($bpmnRepository);
 
         //Load the execution instance
-        $instance = $this->engine->loadExecutionInstance('otherExecutionInstanceId');
+        $instance = $this->engine->loadExecutionInstance('otherExecutionInstanceId', $bpmnRepository);
 
         //Get References by id
         $secondActivity = $bpmnRepository->getScriptTask('task2');
@@ -267,14 +264,13 @@ class LoadExecutionInstancesTest extends EngineTestCase
         $bpmnRepository = new BpmnDocument();
         $bpmnRepository->setEngine($this->engine);
         $bpmnRepository->setFactory($this->repository);
-        $this->engine->setStorage($bpmnRepository);
         $bpmnRepository->load(__DIR__ . '/files/LoadTokens.bpmn');
 
         //Set test data to load the sequential process
         $this->prepareParallelProcessWithException($bpmnRepository);
 
         //Load the execution instance
-        $instance = $this->engine->loadExecutionInstance('otherExecutionInstanceId');
+        $instance = $this->engine->loadExecutionInstance('otherExecutionInstanceId', $bpmnRepository);
 
         //Get References by id
         $thirdActivity = $bpmnRepository->getActivity('task3');
@@ -294,11 +290,10 @@ class LoadExecutionInstancesTest extends EngineTestCase
         $bpmnRepository = new BpmnDocument();
         $bpmnRepository->setEngine($this->engine);
         $bpmnRepository->setFactory($this->repository);
-        $this->engine->setStorage($bpmnRepository);
         $bpmnRepository->load(__DIR__ . '/files/LoadTokens.bpmn');
 
         //Load the execution instance
-        $instance = $this->engine->loadExecutionInstance('nonExistingInstance');
+        $instance = $this->engine->loadExecutionInstance('nonExistingInstance', $bpmnRepository);
 
         //Assertion: The returned value must be null
         $this->assertNull($instance);
@@ -315,15 +310,14 @@ class LoadExecutionInstancesTest extends EngineTestCase
         $bpmnRepository->setEngine($this->engine);
         $bpmnRepository->setFactory($this->repository);
         $this->engine->setRepository($this->repository);
-        $this->engine->setStorage($bpmnRepository);
         $bpmnRepository->load(__DIR__ . '/files/LoadTokens.bpmn');
 
         //Set test data to load the sequential process
         $this->prepareSequentialProcess($bpmnRepository);
 
         //Load the execution instance twice
-        $instance1 = $this->engine->loadExecutionInstance('executionInstanceId');
-        $instance2 = $this->engine->loadExecutionInstance('executionInstanceId');
+        $instance1 = $this->engine->loadExecutionInstance('executionInstanceId', $bpmnRepository);
+        $instance2 = $this->engine->loadExecutionInstance('executionInstanceId', $bpmnRepository);
 
         //Assertion: Both variables point to the same instance
         $this->assertEquals($instance1, $instance2);
diff --git a/tests/Feature/Engine/LoadFromBPMNFileTest.php b/tests/Feature/Engine/LoadFromBPMNFileTest.php
index a2f7739..ac99d41 100644
--- a/tests/Feature/Engine/LoadFromBPMNFileTest.php
+++ b/tests/Feature/Engine/LoadFromBPMNFileTest.php
@@ -77,6 +77,13 @@ class LoadFromBPMNFileTest extends EngineTestCase
         $activityB = $bpmnRepository->getScriptTask('ScriptTask_2');
         $endActivity = $bpmnRepository->getScriptTask('end');
 
+        //Assertion: Check reference to BpmnDocument
+        $this->assertEquals($bpmnRepository, $start->getOwnerDocument());
+        $this->assertEquals($bpmnRepository, $startActivity->getOwnerDocument());
+        $this->assertEquals($bpmnRepository, $activityA->getOwnerDocument());
+        $this->assertEquals($bpmnRepository, $activityB->getOwnerDocument());
+        $this->assertEquals($bpmnRepository, $endActivity->getOwnerDocument());
+
         //Start the process
         $start->start($instance);
         $this->engine->runToNextState();