public function testCheckProcess()
 {
     $id = '_unit_pr_check_';
     $processChecker = new wfAuthoring_models_classes_ProcessChecker($this->proc);
     $activity1 = $this->authoringService->createActivity($this->proc, "{$id}Activity_1");
     $activity1->editPropertyValues(new core_kernel_classes_Property(PROPERTY_ACTIVITIES_ISINITIAL), GENERIS_TRUE);
     $connector1 = $this->authoringService->createConnector($activity1);
     $then1 = $this->authoringService->createConditionalActivity($connector1, 'then', null, "{$id}Activity_2");
     //create "Activity_2"
     $else1 = $this->authoringService->createConditionalActivity($connector1, 'else', null, '', true);
     //create another connector
     $this->assertEquals($connector1->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_TYPE))->getUri(), INSTANCE_TYPEOFCONNECTORS_CONDITIONAL);
     $activityService = wfEngine_models_classes_ActivityService::singleton();
     $this->assertTrue($activityService->isActivity($then1));
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $this->assertTrue($connectorService->isConnector($else1));
     $transitionRule = $connector1->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_TRANSITIONRULE));
     $this->assertEquals($then1->getUri(), $transitionRule->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_TRANSITIONRULES_THEN))->getUri());
     $this->assertEquals($else1->getUri(), $transitionRule->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_TRANSITIONRULES_ELSE))->getUri());
     //create a sequential a
     $connector2 = $this->authoringService->createConnector($then1);
     $lastActivity = $this->authoringService->createSequenceActivity($connector2, null, "{$id}Activity_3");
     //connector "else1": connect the "then" to the activity "then1" and the "else" to
     $then2 = $this->authoringService->createConditionalActivity($else1, 'then', $connector2);
     //connect to the activity $then1
     $else2 = $this->authoringService->createConditionalActivity($else1, 'else', $lastActivity);
     //connect to the connector of the activity $then1
     $this->assertEquals($then2->getUri(), $connector2->getUri());
     $this->assertEquals($else2->getUri(), $lastActivity->getUri());
     $this->assertTrue($processChecker->check());
 }
 /**
  * Builds a simple Diagram of the Process
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param  Resource process
  * @return string
  */
 public static function buildDiagramData(core_kernel_classes_Resource $process)
 {
     $returnValue = (string) '';
     common_Logger::i("Building diagram for " . $process->getLabel());
     $authoringService = wfAuthoring_models_classes_ProcessService::singleton();
     $activityService = wfEngine_models_classes_ActivityService::singleton();
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $activityCardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
     $activities = $authoringService->getActivitiesByProcess($process);
     $todo = array();
     foreach ($activities as $activity) {
         if ($activityService->isInitial($activity)) {
             $todo[] = $activity;
         }
     }
     $currentLevel = 0;
     $diagram = new wfAuthoring_models_classes_ProcessDiagram();
     $done = array();
     while (!empty($todo)) {
         $nextLevel = array();
         $posOnLevel = 0;
         foreach ($todo as $item) {
             $next = array();
             if ($activityService->isActivity($item)) {
                 // add this activity
                 $diagram->addActivity($item, 54 + 200 * $posOnLevel + 10 * $currentLevel, 35 + 80 * $currentLevel);
                 $next = array_merge($next, $activityService->getNextConnectors($item));
                 common_Logger::d('Activity added ' . $item->getUri());
             } elseif ($connectorService->isConnector($item)) {
                 // add this connector
                 $diagram->addConnector($item, 100 + 200 * $posOnLevel + 10 * $currentLevel, 40 + 80 * $currentLevel);
                 $next = array_merge($next, $connectorService->getNextActivities($item));
             } else {
                 common_Logger::w('unexpected ressource in process ' . $item->getUri());
             }
             //replace cardinalities
             foreach ($next as $key => $destination) {
                 if ($activityCardinalityService->isCardinality($destination)) {
                     // not represented on diagram
                     $next[$key] = $activityCardinalityService->getDestination($destination);
                 }
             }
             //add arrows
             foreach ($next as $destination) {
                 $diagram->addArrow($item, $destination);
             }
             $posOnLevel++;
             $nextLevel = array_merge($nextLevel, $next);
         }
         $done = array_merge($done, $todo);
         $todo = array_diff($nextLevel, $done);
         $currentLevel++;
     }
     $returnValue = $diagram->toJSON();
     return (string) $returnValue;
 }
 public function __construct()
 {
     //init services
     $this->activityService = wfEngine_models_classes_ActivityService::singleton();
     $this->processVariableService = wfEngine_models_classes_VariableService::singleton();
     $this->authoringService = wfAuthoring_models_classes_ProcessService::singleton();
     $this->activityExecutionService = wfEngine_models_classes_ActivityExecutionService::singleton();
     $this->connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $this->processVariablesClass = new core_kernel_classes_Class(CLASS_PROCESSVARIABLES);
     $this->propertyIsSample = new core_kernel_classes_Property(PROPERTY_IS_SAMPLE);
 }
 /**
  * tests initialization
  */
 public function setUp()
 {
     TaoPhpUnitTestRunner::initTest();
     $this->authoringService = wfAuthoring_models_classes_ProcessService::singleton();
     $this->variableService = wfEngine_models_classes_VariableService::singleton();
     $processDefinitionClass = new core_kernel_classes_Class(CLASS_PROCESS);
     $this->processDefinition = $processDefinitionClass->createInstance('ProcessForUnitTest', 'Unit test');
     //define activities and connectors
     $activity = $this->authoringService->createActivity($this->processDefinition, 'activity for interactive service unit test');
     if ($activity instanceof core_kernel_classes_Resource) {
         $this->activity = $activity;
     } else {
         $this->fail('fail to create a process definition resource');
     }
     $this->service = wfEngine_models_classes_ConnectorService::singleton();
 }
 /**
  * Short description of method createConnector
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param core_kernel_classes_Resource sourceStep
  * @param string label
  * @throws Exception
  * @return core_kernel_classes_Resource
  */
 public function createConnector(core_kernel_classes_Resource $sourceStep, $label = '')
 {
     $returnValue = null;
     $label = empty($label) ? $sourceStep->getLabel() . "_c" : $label;
     $connectorClass = new core_kernel_classes_Class(CLASS_CONNECTORS);
     $returnValue = $connectorClass->createInstance($label, "created by ProcessService.Class");
     if (is_null($returnValue)) {
         throw new Exception("the connector cannot be created for the activity {$sourceStep->getUri()}");
     }
     $activityService = wfEngine_models_classes_ActivityService::singleton();
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     //associate the connector to the activity
     $sourceStep->setPropertyValue(new core_kernel_classes_Property(PROPERTY_STEP_NEXT), $returnValue);
     //set the activity reference of the connector:
     $activityRefProp = new core_kernel_classes_Property(PROPERTY_CONNECTORS_ACTIVITYREFERENCE);
     if ($activityService->isActivity($sourceStep)) {
         $returnValue->setPropertyValue($activityRefProp, $sourceStep);
     } elseif ($connectorService->isConnector($sourceStep)) {
         $returnValue->setPropertyValue($activityRefProp, $sourceStep->getUniquePropertyValue($activityRefProp));
     } else {
         throw new Exception("invalid resource type for the activity parameter: {$sourceStep->getUri()}");
     }
     return $returnValue;
 }
 /**
  * Short description of method connectorNode
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param  Resource connector
  * @param  string nodeClass
  * @param  boolean recursive
  * @return array
  */
 public function connectorNode(core_kernel_classes_Resource $connector, $nodeClass = '', $recursive = false)
 {
     $returnValue = array();
     $connectorData = array();
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     //		$activityService = wfEngine_models_classes_ActivityService::singleton();
     //type of connector:
     //if not null, get the information on the next activities. Otherwise, return an "empty" connector node, indicating that the node has just been created, i.e. at the same time as an activity
     $connectorType = $connector->getOnePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_TYPE), false);
     if (is_null($connectorType)) {
         //create default connector node:
         $returnValue = $this->addNodePrefix($this->defaultConnectorNode($connector), $nodeClass);
         return $returnValue;
     } else {
         //if it is a conditional type
         if ($connectorType->getUri() == INSTANCE_TYPEOFCONNECTORS_CONDITIONAL) {
             //get the rule
             $connectorRule = $connector->getOnePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_TRANSITIONRULE), false);
             if (!is_null($connectorRule)) {
                 //continue getting connector data:
                 $connectorData[] = $this->conditionNode($connectorRule);
                 //get the "THEN"
                 $then = $connectorRule->getOnePropertyValue(new core_kernel_classes_Property(PROPERTY_TRANSITIONRULES_THEN), false);
                 if (!is_null($then)) {
                     $portData = array('id' => 0, 'label' => 'then', 'multiplicity' => 1);
                     if ($connectorService->isConnector($then)) {
                         $connectorActivityReference = $then->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_ACTIVITYREFERENCE))->getUri();
                         if ($connectorActivityReference == $this->currentActivity->getUri() && !in_array($then->getUri(), $this->addedConnectors)) {
                             if ($recursive) {
                                 $connectorData[] = $this->connectorNode($then, 'then', true, $portData);
                             } else {
                                 $connectorData[] = $this->activityNode($then, 'then', false, $portData);
                             }
                         } else {
                             $connectorData[] = $this->activityNode($then, 'then', true, $portData);
                         }
                     } else {
                         $connectorData[] = $this->activityNode($then, 'then', true, $portData);
                     }
                 }
                 //same for the "ELSE"
                 $else = $connectorRule->getOnePropertyValue(new core_kernel_classes_Property(PROPERTY_TRANSITIONRULES_ELSE), false);
                 if (!is_null($else)) {
                     $portData = array('id' => 1, 'label' => 'else', 'multiplicity' => 1);
                     if ($connectorService->isConnector($else)) {
                         $connectorActivityReference = $else->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_ACTIVITYREFERENCE))->getUri();
                         if ($connectorActivityReference == $this->currentActivity->getUri() && !in_array($else->getUri(), $this->addedConnectors)) {
                             if ($recursive) {
                                 $connectorData[] = $this->connectorNode($else, 'else', true, $portData);
                             } else {
                                 $connectorData[] = $this->activityNode($else, 'else', false, $portData);
                             }
                         } else {
                             $connectorData[] = $this->activityNode($else, 'else', true, $portData);
                         }
                     } else {
                         $connectorData[] = $this->activityNode($else, 'else', true, $portData);
                     }
                 }
             }
         } elseif ($connectorType->getUri() == INSTANCE_TYPEOFCONNECTORS_SEQUENCE) {
             $next = $connector->getOnePropertyValue(new core_kernel_classes_Property(PROPERTY_STEP_NEXT), false);
             if (!is_null($next)) {
                 $connectorData[] = $this->activityNode($next, 'next', true);
                 //the default portData array will do
             }
         } elseif ($connectorType->getUri() == INSTANCE_TYPEOFCONNECTORS_PARALLEL) {
             $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
             $variableService = wfEngine_models_classes_VariableService::singleton();
             $nextActivitiesCollection = $connector->getPropertyValuesCollection(new core_kernel_classes_Property(PROPERTY_STEP_NEXT));
             $portId = 0;
             foreach ($nextActivitiesCollection->getIterator() as $nextActivity) {
                 if ($cardinalityService->isCardinality($nextActivity)) {
                     $activity = $cardinalityService->getDestination($nextActivity);
                     $cardinality = $cardinalityService->getCardinality($nextActivity);
                     $number = $cardinality instanceof core_kernel_classes_Resource ? '^' . $variableService->getCode($cardinality) : $cardinality;
                     $connectorData[] = $this->activityNode($activity, 'next', true, array('id' => $portId, 'multiplicity' => $number, 'label' => $activity->getLabel()), "(count : {$number})");
                     $portId++;
                 }
             }
         } elseif ($connectorType->getUri() == INSTANCE_TYPEOFCONNECTORS_JOIN) {
             $next = $connector->getOnePropertyValue(new core_kernel_classes_Property(PROPERTY_STEP_NEXT), false);
             if (!is_null($next)) {
                 $connectorData[] = $this->activityNode($next, 'next', true);
                 //the default portData array will do
             }
         } else {
             throw new Exception("unknown connector type: {$connectorType->getLabel()} for connector {$connector->getUri()}");
         }
         if (empty($portInfo)) {
             $portInfo = array('id' => 0, 'label' => 'next', 'multiplicity' => 1);
         } else {
             if (!isset($portInfo['id'])) {
                 $portInfo['id'] = 0;
             }
             if (!isset($portInfo['id'])) {
                 $portInfo['label'] = 'next';
             }
             if (!isset($portInfo['id'])) {
                 $portInfo['multiplicity'] = 1;
             }
         }
         //add to data
         $returnValue = array('data' => $connectorType->getLabel() . ":" . $connector->getLabel(), 'attributes' => array('id' => tao_helpers_Uri::encode($connector->getUri()), 'class' => 'node-connector'), 'type' => trim(strtolower($connectorType->getLabel())), 'port' => $nodeClass, 'portData' => $portInfo);
         $returnValue = self::addNodePrefix($returnValue, $nodeClass);
         if (!empty($connectorData)) {
             $returnValue['children'] = $connectorData;
         }
         $this->addedConnectors[] = $connector->getUri();
     }
     return (array) $returnValue;
 }
 /**
  * Short description of method __construct
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param  Resource process
  * @return mixed
  */
 public function __construct(core_kernel_classes_Resource $process)
 {
     $this->process = $process;
     $this->activityService = wfEngine_models_classes_ActivityService::singleton();
     $this->connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $this->authoringService = wfAuthoring_models_classes_ProcessService::singleton();
     parent::__construct();
 }
 /**
  * Short description of method getSplitConnectorNewActivities
  *
  * @access public
  * @author Somsack Sipasseuth, <*****@*****.**>
  * @param  Resource activityExecution
  * @param  Resource currentConnector
  * @return array
  */
 public function getSplitConnectorNewActivities(core_kernel_classes_Resource $activityExecution, core_kernel_classes_Resource $currentConnector)
 {
     $returnValue = array();
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
     foreach ($connectorService->getNextActivities($currentConnector) as $cardinality) {
         if ($cardinalityService->isCardinality($cardinality)) {
             $activity = $cardinalityService->getDestination($cardinality);
             if (!is_null($activity)) {
                 try {
                     $count = $cardinalityService->getCardinality($cardinality, $activityExecution);
                 } catch (wfEngine_models_classes_ProcessExecutionException $e) {
                     $count = 0;
                     //in case the parallel variable is not set
                 }
                 for ($i = 0; $i < $count; $i++) {
                     $returnValue[] = $activity;
                 }
             }
         }
     }
     return (array) $returnValue;
 }
 /**
  * Short description of method setParallelActivities
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param  Resource connectorInstance
  * @param  array newActivitiesArray
  * @return boolean
  */
 public function setParallelActivities(core_kernel_classes_Resource $connectorInstance, $newActivitiesArray = array())
 {
     $returnValue = (bool) false;
     $this->setConnectorType($connectorInstance, new core_kernel_classes_Resource(INSTANCE_TYPEOFCONNECTORS_PARALLEL));
     $propNextActivities = new core_kernel_classes_Property(PROPERTY_STEP_NEXT);
     $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
     //remove old property values:
     $nextActivitiesCollection = $connectorInstance->getPropertyValuesCollection($propNextActivities);
     $oldSplitVariablesByActivity = array();
     foreach ($nextActivitiesCollection->getIterator() as $activityMultiplicityResource) {
         if ($cardinalityService->isCardinality($activityMultiplicityResource)) {
             //record the old split variables values in case it is needed (TODO: optimize this process)
             $activity = $cardinalityService->getDestination($activityMultiplicityResource);
             $splitVars = $cardinalityService->getSplitVariables($activityMultiplicityResource);
             if (!empty($splitVars)) {
                 $oldSplitVariablesByActivity[$activity->getUri()] = $splitVars;
             }
             //delete it
             $activityMultiplicityResource->delete();
         }
     }
     $returnValue = $connectorInstance->removePropertyValues($propNextActivities);
     //finally, set the next activities values to the parallel connector:
     $joinConnector = null;
     $processFlow = new wfEngine_models_classes_ProcessFlow();
     $i = 0;
     foreach ($newActivitiesArray as $activityUri => $count) {
         $activity = new core_kernel_classes_Resource($activityUri);
         //set multiplicity to the parallel connector:
         $cardinality = $cardinalityService->createCardinality($activity, $count);
         if (isset($oldSplitVariablesByActivity[$activityUri])) {
             if (!empty($oldSplitVariablesByActivity[$activityUri]) && !$cardinalityService->editSplitVariables($cardinality, $oldSplitVariablesByActivity[$activityUri])) {
                 throw new Exception('cannot set split variables to new cardinality resources');
             }
         }
         $returnValue = $connectorInstance->setPropertyValue($propNextActivities, $cardinality);
         //set multiplicity to the merge connector:
         $previousActvityUri = '';
         if ($i == 0) {
             //use the ProcessFlow service to find if a merge connector exists for the current parallel connector:
             //do it only once:
             $processFlow->resetCheckedResources();
             $joinConnector = $processFlow->findJoinFromActivityForward($activity);
             if (!is_null($joinConnector)) {
                 //if it exists, we erase all previous activities:
                 //the previous acitivites must be related to the *exact* same activity-multiplicity objects as the parallel but not necessarily the same (e.g. parallel thread with more than 1 acitivty)
                 //we suppose that the previous activities of the found merge connector come *exactly* from the thread generated by its parallel connector (condition for a valid process design)
                 $prevActivities = wfEngine_models_classes_ConnectorService::singleton()->getPreviousActivities($joinConnector);
                 foreach ($prevActivities as $activityMultiplicityResource) {
                     if ($cardinalityService->isCardinality($activityMultiplicityResource)) {
                         $activityMultiplicityResource->delete();
                     }
                     $prevActivities->removePropertyValues(new core_kernel_classes_Property(PROPERTY_STEP_NEXT));
                 }
                 /*
                 $prevActivitiesCollection = $joinConnector->getPropertyValuesCollection($propPreviousActivities);
                 foreach ($prevActivitiesCollection->getIterator() as $activityMultiplicityResource){
                 	if($cardinalityService->isCardinality($activityMultiplicityResource)){
                 		$activityMultiplicityResource->delete();
                 	}
                 }
                 $returnValue = $joinConnector->removePropertyValues($propPreviousActivities);
                 */
             }
             $toPop = $processFlow->getCheckedActivities();
             $previousActvityUri = array_pop($toPop);
         }
         if (!is_null($joinConnector)) {
             if (empty($previousActvityUri)) {
                 //if there are more than 1 activity in the newActivitiesArray:
                 $processFlow->resetCheckedResources();
                 $joinConnector = $processFlow->findJoinFromActivityForward($activity);
                 $previousActvityUri = array_pop($processFlow->getCheckedActivities());
             }
             if (!empty($previousActvityUri)) {
                 $previous = new core_kernel_classes_Resource($previousActvityUri);
                 $cardinality = $cardinalityService->createCardinality($joinConnector, $count);
                 $returnValue = $previous->setPropertyValues(new core_kernel_classes_Property(PROPERTY_STEP_NEXT), $cardinality);
                 /*
                 $multiplicity = $cardinalityService->createCardinality($previous, $count);
                 $returnValue = $joinConnector->setPropertyValue($propPreviousActivities, $multiplicity);
                 */
             }
         }
         $i++;
     }
     return (bool) $returnValue;
 }
 public static function nextActivityElements(core_kernel_classes_Resource $connector, $type, $allowCreation = true, $includeConnectors = true, $optionsWidget = 'Combobox')
 {
     $returnValue = array();
     $authorizedOptionsWidget = array('Combobox', 'Checkbox');
     if (!in_array($optionsWidget, $authorizedOptionsWidget)) {
         throw new Exception('Wrong type of widget');
         return $returnValue;
     }
     $idPrefix = '';
     $nextActivity = null;
     $propTransitionRule = new core_kernel_classes_Property(PROPERTY_CONNECTORS_TRANSITIONRULE);
     $propNextActivities = new core_kernel_classes_Property(PROPERTY_STEP_NEXT);
     //find the next activity if available
     switch (strtolower($type)) {
         case 'next':
             $nextActivityCollection = $connector->getPropertyValuesCollection($propNextActivities);
             foreach ($nextActivityCollection->getIterator() as $activity) {
                 if ($activity instanceof core_kernel_classes_Resource) {
                     $nextActivity = $activity;
                     //we take the last one...(note: there should be only one though)
                 }
             }
             $idPrefix = 'next';
             break;
         case 'then':
             $transitionRuleCollection = $connector->getPropertyValuesCollection($propTransitionRule);
             foreach ($transitionRuleCollection->getIterator() as $transitionRule) {
                 if ($transitionRule instanceof core_kernel_classes_Resource) {
                     foreach ($transitionRule->getPropertyValuesCollection(new core_kernel_classes_Property(PROPERTY_TRANSITIONRULES_THEN))->getIterator() as $then) {
                         if ($then instanceof core_kernel_classes_Resource) {
                             $nextActivity = $then;
                         }
                     }
                 }
             }
             $idPrefix = 'then';
             break;
         case 'else':
             $transitionRuleCollection = $connector->getPropertyValuesCollection($propTransitionRule);
             foreach ($transitionRuleCollection->getIterator() as $transitionRule) {
                 if ($transitionRule instanceof core_kernel_classes_Resource) {
                     foreach ($transitionRule->getPropertyValuesCollection(new core_kernel_classes_Property(PROPERTY_TRANSITIONRULES_ELSE))->getIterator() as $else) {
                         if ($else instanceof core_kernel_classes_Resource) {
                             $nextActivity = $else;
                         }
                     }
                 }
             }
             $idPrefix = 'else';
             break;
         case 'parallel':
             $nextActivity = array();
             $nextActivityCollection = $connector->getPropertyValuesCollection($propNextActivities);
             foreach ($nextActivityCollection->getIterator() as $cardinality) {
                 if ($cardinality instanceof core_kernel_classes_Resource) {
                     $nextActivity[] = $cardinality;
                 }
             }
             $idPrefix = 'parallel';
             break;
         case 'join':
             // should only have one following activity
             $nextActivity = $connector->getOnePropertyValue($propNextActivities);
             $idPrefix = $type;
             break;
         default:
             throw new Exception("unknown type for the next activity");
     }
     $activityOptions = array();
     $connectorOptions = array();
     if ($allowCreation) {
         //create the activity label element (used only in case of new activity craetion)
         $elementActivityLabel = tao_helpers_form_FormFactory::getElement($idPrefix . "_activityLabel", 'Textbox');
         $elementActivityLabel->setDescription(__('Label'));
         //add the "creating" option
         $activityOptions["newActivity"] = __("create new activity");
         $connectorOptions["newConnector"] = __("create new connector");
     }
     //the activity associated to the connector:
     $referencedActivity = $connector->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_CONNECTORS_ACTIVITYREFERENCE));
     //mandatory property value, initiated at the connector creation
     if ($referencedActivity instanceof core_kernel_classes_Resource) {
         $processDefClass = new core_kernel_classes_Class(CLASS_PROCESS);
         $processes = $processDefClass->searchInstances(array(PROPERTY_PROCESS_ACTIVITIES => $referencedActivity->getUri()), array('like' => false));
         if (count($processes) > 0) {
             $process = array_shift($processes);
             if (!empty($process)) {
                 //get list of activities and connectors for the current process:
                 $connectorClass = new core_kernel_classes_Class(CLASS_CONNECTORS);
                 $processAuthoringService = wfAuthoring_models_classes_ProcessService::singleton();
                 $activities = $processAuthoringService->getActivitiesByProcess($process);
                 foreach ($activities as $activityTemp) {
                     //include activities options:
                     $encodedUri = tao_helpers_Uri::encode($activityTemp->getUri());
                     $activityOptions[$encodedUri] = $activityTemp->getLabel();
                     if (strtolower($type) == 'parallel') {
                         $elementHidden = tao_helpers_form_FormFactory::getElement("{$encodedUri}_num_hidden", 'Hidden');
                         $returnValue[$idPrefix . '_' . $activityTemp->getUri()] = $elementHidden;
                     }
                     //include connectors options:
                     if ($includeConnectors) {
                         $connectors = $connectorClass->searchInstances(array(PROPERTY_CONNECTORS_ACTIVITYREFERENCE => $activityTemp->getUri()), array('like' => false));
                         foreach ($connectors as $connectorTemp) {
                             if ($connector->getUri() != $connectorTemp->getUri()) {
                                 $connectorOptions[tao_helpers_Uri::encode($connectorTemp->getUri())] = $connectorTemp->getLabel();
                             }
                         }
                     }
                 }
             }
         }
     }
     //create the description element
     $elementDescription = tao_helpers_form_FormFactory::getElement($idPrefix, 'Free');
     $elementDescription->setValue(strtoupper($type) . ' :');
     //create the activity select element:
     $elementActivities = tao_helpers_form_FormFactory::getElement($idPrefix . "_activityUri", $optionsWidget);
     $elementActivities->setDescription(__('Activity'));
     $elementActivities->setOptions($activityOptions);
     $elementChoice = null;
     $elementConnectors = null;
     if ($includeConnectors) {
         //the default radio button to select between the 3 possibilities:
         $elementChoice = tao_helpers_form_FormFactory::getElement($idPrefix . "_activityOrConnector", 'Radiobox');
         $elementChoice->setDescription(__('Activity or Connector'));
         $options = array("activity" => __("Activity"), "connector" => __("Connector"));
         $elementChoice->setOptions($options);
         //create the connector select element:
         $elementConnectors = tao_helpers_form_FormFactory::getElement($idPrefix . "_connectorUri", $optionsWidget);
         $elementConnectors->setDescription(__('Connector'));
         $elementConnectors->setOptions($connectorOptions);
     }
     if (!empty($nextActivity)) {
         if (is_array($nextActivity) && $optionsWidget == 'Checkbox') {
             if (strtolower($type) == 'parallel') {
                 $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
                 foreach ($nextActivity as $cardinality) {
                     $activity = $cardinalityService->getDestination($cardinality);
                     $number = $cardinalityService->getCardinality($cardinality);
                     if (isset($returnValue[$idPrefix . '_' . $activity->getUri()])) {
                         $returnValue[$idPrefix . '_' . $activity->getUri()]->setValue($number instanceof core_kernel_classes_Resource ? tao_helpers_Uri::encode($number->getUri()) : intval($number));
                     }
                     $elementActivities->setValue($activity->getUri());
                     //no need for tao_helpers_Uri::encode
                 }
             } else {
                 foreach ($nextActivity as $activity) {
                     $elementActivities->setValue($activity->getUri());
                     //no need for tao_helpers_Uri::encode
                 }
             }
         } elseif ($nextActivity instanceof core_kernel_classes_Resource) {
             $aService = wfEngine_models_classes_ActivityService::singleton();
             if ($aService->isActivity($nextActivity)) {
                 if ($includeConnectors) {
                     $elementChoice->setValue("activity");
                 }
                 $elementActivities->setValue($nextActivity->getUri());
                 //no need for tao_helpers_Uri::encode
             }
             $conmectorService = wfEngine_models_classes_ConnectorService::singleton();
             if ($conmectorService->isConnector($nextActivity) && $includeConnectors) {
                 $elementChoice->setValue("connector");
                 $elementConnectors->setValue($nextActivity->getUri());
             }
         }
     }
     //put all elements in the return value:
     $returnValue[$idPrefix . '_description'] = $elementDescription;
     if ($includeConnectors) {
         $returnValue[$idPrefix . '_choice'] = $elementChoice;
     }
     $returnValue[$idPrefix . '_activities'] = $elementActivities;
     if ($allowCreation) {
         $returnValue[$idPrefix . '_label'] = $elementActivityLabel;
     }
     if ($includeConnectors) {
         $returnValue[$idPrefix . '_connectors'] = $elementConnectors;
     }
     return $returnValue;
 }
 public function testParallelJoinActivities()
 {
     $activityA = $this->authoringService->createActivity($this->proc, 'A');
     $connectorA = $this->authoringService->createConnector($activityA);
     $activityB = $this->authoringService->createSequenceActivity($connectorA, null, 'B');
     $connectorB = $this->authoringService->createConnector($activityB);
     //create the parallel branch 'C' acivities and connectors
     $activityC = $this->authoringService->createActivity($this->proc, 'C');
     $connectorC = $this->authoringService->createConnector($activityC);
     $activityC1 = $this->authoringService->createSequenceActivity($connectorC, null, 'C1');
     $connectorC1 = $this->authoringService->createConnector($activityC1);
     $activityC2 = $this->authoringService->createSequenceActivity($connectorC1, null, 'C2');
     $connectorC2 = $this->authoringService->createConnector($activityC2);
     //create the parallel branch 'D' activities and connectors
     $activityD = $this->authoringService->createActivity($this->proc, 'D');
     $connectorD = $this->authoringService->createConnector($activityD);
     //create the merging actvity F
     $activityF = $this->authoringService->createActivity($this->proc, 'F');
     $connectorF = $this->authoringService->createConnector($activityF);
     $newActivitiesArray = array($activityC->getUri() => 2, $activityD->getUri() => 3);
     $this->assertTrue($this->authoringService->setParallelActivities($connectorB, $newActivitiesArray));
     $nextActivitiesCollection = $connectorB->getPropertyValuesCollection(new core_kernel_classes_Property(PROPERTY_STEP_NEXT));
     $this->assertEquals($nextActivitiesCollection->count(), 2);
     //merge all activity D instance to F:
     $this->authoringService->createJoinActivity($connectorD, $activityF, '', $activityD);
     $activitiyClass = new core_kernel_classes_Class(CLASS_ACTIVITIES);
     $nexts = wfEngine_models_classes_ConnectorService::singleton()->getPreviousActivities($connectorD);
     $this->assertEquals(count($nexts), 2);
     //2 cardinality resources
 }
 /**
  * Return dispatched process variables values, by activity definiiton
  *
  * @access public
  * @author Somsack Sipasseuth, <*****@*****.**>
  * @param  Resource activityExecution
  * @param  Resource connector
  * @return array
  */
 public function getSplitVariables(core_kernel_classes_Resource $activityExecution, core_kernel_classes_Resource $connector)
 {
     $returnValue = array();
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
     $allSplitVariables = array();
     foreach ($connectorService->getNextActivities($connector) as $cardinality) {
         if ($cardinalityService->isCardinality($cardinality)) {
             $splitVars = $cardinalityService->getSplitVariables($cardinality);
             $activity = $cardinalityService->getDestination($cardinality);
             if (!is_null($activity) && !empty($splitVars)) {
                 $allSplitVariables[$activity->getUri()] = $splitVars;
             }
         }
     }
     $codeProperty = new core_kernel_classes_Property(PROPERTY_PROCESSVARIABLES_CODE);
     foreach ($allSplitVariables as $activityUri => $splitVariables) {
         $returnValue[$activityUri] = array();
         foreach ($splitVariables as $splitVariable) {
             if ($splitVariable instanceof core_kernel_classes_Resource) {
                 $codeLiteral = $splitVariable->getOnePropertyValue($codeProperty);
                 if (!is_null($codeLiteral) && $codeLiteral instanceof core_kernel_classes_Literal) {
                     $code = $codeLiteral->literal;
                     $serialisedValues = $activityExecution->getOnePropertyValue(new core_kernel_classes_Property($splitVariable->getUri()));
                     if (!empty($serialisedValues) && $serialisedValues instanceof core_kernel_classes_Literal) {
                         $values = unserialize($serialisedValues);
                         if ($values && is_array($values) && !empty($values)) {
                             $count = count($values);
                             for ($i = 0; $i < $count; $i++) {
                                 if (!isset($returnValue[$activityUri][$i])) {
                                     $returnValue[$activityUri][$i] = array();
                                 }
                                 $returnValue[$activityUri][$i][$code] = $values[$i];
                             }
                         }
                     }
                 }
             }
         }
     }
     return (array) $returnValue;
 }
 /**
  * Short description of method __construct
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param  string cloneLabel
  */
 public function __construct($cloneLabel = '')
 {
     $this->cloneLabel = $cloneLabel;
     $this->authoringService = wfAuthoring_models_classes_ProcessService::singleton();
     $this->activityService = wfEngine_models_classes_ActivityService::singleton();
     $this->connectorService = wfEngine_models_classes_ConnectorService::singleton();
     $this->initCloningVariables();
 }
 /**
  * The method creates the array representation the default connector node to fill the jsTree 
  *
  * @access public
  * @author CRP Henri Tudor - TAO Team - {@link http://www.tao.lu}
  * @param core_kernel_classes_Resource activity
  * @param string nodeClass
  * @param boolean goto
  * @return array
  */
 public function activityNode(core_kernel_classes_Resource $activity, $nodeClass = '', $goto = false, $portInfo = array(), $labelSuffix = '')
 {
     $nodeData = array();
     $class = '';
     $linkAttribute = 'id';
     $activityService = wfEngine_models_classes_ActivityService::singleton();
     $connectorService = wfEngine_models_classes_ConnectorService::singleton();
     if ($activityService->isActivity($activity)) {
         $class = 'node-activity';
     } elseif ($connectorService->isConnector($activity)) {
         $class = 'node-connector';
     } else {
         return $nodeData;
         //unknown type
     }
     if ($goto) {
         $class .= "-goto";
         $linkAttribute = "rel";
     }
     if (empty($portInfo)) {
         $portInfo = array('id' => 0, 'label' => 'next', 'multiplicity' => 1);
     } else {
         if (!isset($portInfo['id'])) {
             $portInfo['id'] = 0;
         }
         if (!isset($portInfo['id'])) {
             $portInfo['label'] = 'next';
         }
         if (!isset($portInfo['id'])) {
             $portInfo['multiplicity'] = 1;
         }
     }
     $nodeData = array('data' => $activity->getLabel() . ' ' . $labelSuffix, 'attributes' => array($linkAttribute => tao_helpers_Uri::encode($activity->getUri()), 'class' => $class), 'port' => $nodeClass, 'portData' => $portInfo);
     $nodeData = self::addNodePrefix($nodeData, $nodeClass);
     return $nodeData;
 }
 /**
  * Short description of method trigger
  *
  * @access public
  * @author Somsack Sipasseuth, <*****@*****.**>
  * @param  Resource connector
  * @param  Resource activityExecution
  * @param  Resource processExecution
  * @return int
  */
 public function trigger(core_kernel_classes_Resource $connector, core_kernel_classes_Resource $activityExecution, core_kernel_classes_Resource $processExecution = null)
 {
     $returnValue = (int) 0;
     if (!is_null($connector) && !is_null($activityExecution)) {
         //initialize properties
         $connectorUserNotifiedProp = new core_kernel_classes_Property(PROPERTY_CONNECTORS_USER_NOTIFIED);
         $connectorRoleNotifiedProp = new core_kernel_classes_Property(PROPERTY_CONNECTORS_ROLE_NOTIFIED);
         $connectorNextActivitiesProp = new core_kernel_classes_Property(PROPERTY_STEP_NEXT);
         $activityExecutionUserProp = new core_kernel_classes_Property(PROPERTY_ACTIVITY_EXECUTION_CURRENT_USER);
         $activityAclModeProp = new core_kernel_classes_Property(PROPERTY_ACTIVITIES_ACL_MODE);
         $activityAclUserProp = new core_kernel_classes_Property(PROPERTY_ACTIVITIES_RESTRICTED_USER);
         $activityAclRoleProp = new core_kernel_classes_Property(PROPERTY_ACTIVITIES_RESTRICTED_ROLE);
         $connectorService = wfEngine_models_classes_ConnectorService::singleton();
         $transitionRuleService = wfEngine_models_classes_TransitionRuleService::singleton();
         $roleService = wfEngine_models_classes_RoleService::singleton();
         $activityExecutionService = wfEngine_models_classes_ActivityExecutionService::singleton();
         $processExecutionService = wfEngine_models_classes_ProcessExecutionService::singleton();
         if (is_null($processExecution)) {
             $processExecution = $activityExecutionService->getRelatedProcessExecution($activityExecution);
         }
         $users = array();
         //get the notifications mode defined for that connector
         $notifyModes = $connector->getPropertyValuesCollection(new core_kernel_classes_Property(PROPERTY_CONNECTORS_NOTIFY));
         foreach ($notifyModes->getIterator() as $notify) {
             $nextActivities = array();
             //get the users regarding the notification mode
             switch ($notify->getUri()) {
                 //users directly defined
                 case INSTANCE_NOTIFY_USER:
                     foreach ($connector->getPropertyValues($connectorUserNotifiedProp) as $userUri) {
                         if (!in_array($userUri, $users)) {
                             $users[] = $userUri;
                         }
                     }
                     break;
                     //users from roles directly defined
                 //users from roles directly defined
                 case INSTANCE_NOTIFY_ROLE:
                     foreach ($connector->getPropertyValues($connectorRoleNotifiedProp) as $roleUri) {
                         foreach ($roleService->getUsers(new core_kernel_classes_Resource($roleUri)) as $userUri) {
                             if (!in_array($userUri, $users)) {
                                 $users[] = $userUri;
                             }
                         }
                     }
                     break;
                     //get the users who have executed the previous activity
                 //get the users who have executed the previous activity
                 case INSTANCE_NOTIFY_PREVIOUS:
                     $previousActivities = array();
                     $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
                     foreach ($connectorService->getPreviousActivities($connector) as $prevActivity) {
                         if ($cardinalityService->isCardinality($prevActivity)) {
                             $previousActivities[] = $cardinalityService->getSource($prevActivity)->getUri();
                         } else {
                             $previousActivities[] = $prevActivity->getUri();
                         }
                     }
                     $activity = $activityExecutionService->getExecutionOf($activityExecution);
                     //check activity execution against connector
                     if (in_array($activity->getUri(), $previousActivities)) {
                         $activityExecutionUser = $activityExecutionService->getActivityExecutionUser($activityExecution);
                         if (!is_null($activityExecutionUser)) {
                             if (!in_array($activityExecutionUser->getUri(), $users)) {
                                 $users[] = $activityExecutionUser->getUri();
                             }
                         }
                     }
                     break;
                     //get the users
                 //get the users
                 case INSTANCE_NOTIFY_THEN:
                     if ($connectorService->getType($connector)->getUri() == INSTANCE_TYPEOFCONNECTORS_CONDITIONAL) {
                         $transitionRule = $connectorService->getTransitionRule($connector);
                         if ($transitionRule instanceof core_kernel_classes_Resource) {
                             $then = $transitionRuleService->getThenActivity($transitionRule);
                             if ($then instanceof core_kernel_classes_Resource) {
                                 $nextActivities[] = $then->getUri();
                             }
                         }
                     } else {
                         //wrong connector type!
                         break;
                     }
                     //do not break, continue to the INSTANCE_NOTIFY_NEXT case
                 case INSTANCE_NOTIFY_ELSE:
                     if (empty($nextActivities)) {
                         if ($connectorService->getType($connector)->getUri() == INSTANCE_TYPEOFCONNECTORS_CONDITIONAL) {
                             $transitionRule = $connectorService->getTransitionRule($connector);
                             if ($transitionRule instanceof core_kernel_classes_Resource) {
                                 $else = $transitionRuleService->getElseActivity($transitionRule);
                                 if ($else instanceof core_kernel_classes_Resource) {
                                     $nextActivities[] = $else->getUri();
                                 }
                             }
                         } else {
                             //wrong connector type!
                             break;
                         }
                     }
                     //do not break, continue to the INSTANCE_NOTIFY_NEXT case
                 case INSTANCE_NOTIFY_NEXT:
                     if (empty($nextActivities)) {
                         $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
                         foreach ($connectorService->getNextActivities($connector) as $nextActivity) {
                             if ($cardinalityService->isCardinality($nextActivity)) {
                                 $nextActivities[] = $cardinalityService->getDestination($nextActivity)->getUri();
                             } else {
                                 $nextActivities[] = $nextActivity->getUri();
                             }
                         }
                     }
                     $nextActivityExecutions = $activityExecutionService->getFollowing($activityExecution);
                     foreach ($nextActivityExecutions as $activityExec) {
                         $activity = $activityExecutionService->getExecutionOf($activityExec);
                         if (!in_array($activity->getUri(), $nextActivities)) {
                             //invalid activity exec
                             continue;
                         }
                         //check if it is among the next activity of the connector:
                         $mode = $activityExecutionService->getAclMode($activityExec);
                         if ($mode instanceof core_kernel_classes_Resource) {
                             switch ($mode->getUri()) {
                                 case INSTANCE_ACL_USER:
                                     $restrictedUser = $activityExecutionService->getRestrictedUser($activityExec);
                                     //@TODO: implemente multiple restricted users?
                                     if (!is_null($restrictedUser)) {
                                         if (!in_array($restrictedUser->getUri(), $users)) {
                                             $users[] = $restrictedUser->getUri();
                                         }
                                     }
                                     break;
                                 case INSTANCE_ACL_ROLE:
                                 case INSTANCE_ACL_ROLE_RESTRICTED_USER:
                                 case INSTANCE_ACL_ROLE_RESTRICTED_USER_INHERITED:
                                     $restrictedRole = $activityExecutionService->getRestrictedRole($activityExec);
                                     //@TODO: implemente multiple restricted roles?
                                     if (!is_null($restrictedRole)) {
                                         foreach ($roleService->getUsers($restrictedRole) as $userUri) {
                                             if (!in_array($userUri, $users)) {
                                                 $users[] = $userUri;
                                             }
                                         }
                                     }
                                     break;
                             }
                         }
                     }
                     break;
             }
         }
         //build notification message for every user here:
         foreach ($users as $userUri) {
             if ($this->createNotification($connector, new core_kernel_classes_Resource($userUri), $activityExecution, $processExecution)) {
                 //get message from connector:
                 //replace SPX in message bodies
                 $returnValue++;
             }
         }
     }
     return (int) $returnValue;
 }