/**
  * Short description of method createJoinActivity
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @param  Resource connectorInstance
  * @param  Resource followingActivity
  * @param  string newActivityLabel
  * @param  Resource previousActivity
  * @return core_kernel_classes_Resource
  */
 public function createJoinActivity(core_kernel_classes_Resource $connectorInstance, core_kernel_classes_Resource $followingActivity = null, $newActivityLabel = '', core_kernel_classes_Resource $previousActivity = null)
 {
     $returnValue = null;
     $this->setConnectorType($connectorInstance, new core_kernel_classes_Resource(INSTANCE_TYPEOFCONNECTORS_JOIN));
     $propNextActivity = new core_kernel_classes_Property(PROPERTY_STEP_NEXT);
     if (is_null($previousActivity)) {
         throw new wfEngine_models_classes_ProcessDefinitonException('no previous activity found to be connected to the next activity');
     }
     if (is_null($followingActivity)) {
         $followingActivity = $this->createActivityFromConnector($connectorInstance, $newActivityLabel);
         $previousActivity->removePropertyValues(new core_kernel_classes_Property(PROPERTY_STEP_NEXT));
     } else {
         //search if a join connector already leads to the following activity:
         $connectorClass = new core_kernel_classes_Class(CLASS_CONNECTORS);
         $connectors = $connectorClass->searchInstances(array(PROPERTY_STEP_NEXT => $followingActivity->getUri(), PROPERTY_CONNECTORS_TYPE => INSTANCE_TYPEOFCONNECTORS_JOIN), array('like' => false, 'recursive' => 0));
         $found = false;
         foreach ($connectors as $connector) {
             //important: check that the connector found is NOT the same as the current one:
             if ($connectorInstance->getUri() != $connector->getUri()) {
                 //delete old connector,
                 wfAuthoring_models_classes_ConnectorService::singleton()->delete($connectorInstance);
                 //and associate the activity to that one the existing one via a set property value to the "previous activities" property
                 $connectorInstance = $connector;
                 $found = true;
                 break;
                 //one join connector allowed for a next activity
             } else {
                 //nothing to do, since the connector is already
                 //it would be the case when one re-save the join connector with the same following activity
                 return 'same activity';
             }
         }
     }
     if (!$followingActivity instanceof core_kernel_classes_Resource) {
         throw new wfEngine_models_classes_ProcessDefinitonException('Non resource as following activity in ' . __FUNCTION__);
     }
     $connectorInstance->editPropertyValues($propNextActivity, $followingActivity->getUri());
     $connectorInstance->setLabel(__("Merge to ") . $followingActivity->getLabel());
     //check multiplicity  (according to the cardinality defined in the related parallel connector):
     $processFlow = new wfEngine_models_classes_ProcessFlow();
     $cardinalityService = wfEngine_models_classes_ActivityCardinalityService::singleton();
     $multiplicity = 1;
     //default multiplicity, if no multiple parallel activity
     $parallelConnector = null;
     $parallelConnector = $processFlow->findParallelFromActivityBackward($previousActivity);
     if (!is_null($parallelConnector)) {
         //count the number of time theprevious activity must be set as the previous activity of the join connector
         $nextActivitiesCollection = $parallelConnector->getPropertyValuesCollection(new core_kernel_classes_Property(PROPERTY_STEP_NEXT));
         foreach ($nextActivitiesCollection->getIterator() as $nextActivityCardinality) {
             if (in_array($cardinalityService->getDestination($nextActivityCardinality)->getUri(), $processFlow->getCheckedActivities())) {
                 $multiplicity = $cardinalityService->getCardinality($nextActivityCardinality);
                 break;
             }
         }
     }
     if ($multiplicity) {
         $oldPreviousActivityCardinality = null;
         //update the cardinality of the corresponding previous activity if exists
         $prevActivities = wfEngine_models_classes_ConnectorService::singleton()->getPreviousActivities($connectorInstance);
         foreach ($prevActivities as $cardinality) {
             if ($cardinalityService->isCardinality($cardinality)) {
                 if ($cardinalityService->getSource($cardinality)->getUri() == $previousActivity->getUri()) {
                     $oldPreviousActivityCardinality = $cardinality;
                     $cardinalityService->editCardinality($oldPreviousActivityCardinality, $multiplicity);
                     break;
                 }
             } else {
                 common_Logger::w('Resource ' . $cardinality->getUri() . ' not a cardinality');
             }
         }
         //if it does not exists, create a new cardinality resource and assign it to the join connector:
         if (is_null($oldPreviousActivityCardinality)) {
             $cardinality = $cardinalityService->createCardinality($connectorInstance, $multiplicity);
             $previousActivity->setPropertyValue(new core_kernel_classes_Property(PROPERTY_STEP_NEXT), $connectorInstance);
         }
     } else {
         throw new wfEngine_models_classes_ProcessDefinitonException('unexpected null multiplicity in join connector');
     }
     $returnValue = $followingActivity;
     return $returnValue;
 }
 /**
  * Get the estimated number of execution of this activity
  *
  * @access public
  * @author Somsack Sipasseuth, <*****@*****.**>
  * @param  Resource activity
  * @return int
  */
 public function getEstimatedExecutionCount(core_kernel_classes_Resource $activity)
 {
     $returnValue = (int) 0;
     $processFlow = new wfEngine_models_classes_ProcessFlow();
     $parallelConnector = $processFlow->findParallelFromActivityBackward($activity);
     if (!is_null($parallelConnector)) {
         $returnValue = count($parallelConnector->getPropertyValues(new core_kernel_classes_Property(PROPERTY_STEP_NEXT)));
     } else {
         $returnValue = 1;
     }
     return (int) $returnValue;
 }