/**
  *   process events
  *
  * @param Charcoal_IEventContext $context
  *
  * @return int
  *
  * @throws Charcoal_BusinessException|Charcoal_RuntimeException
  */
 public function processEvents($context)
 {
     $debug = $this->getSandbox()->isDebug() || $context->getProcedure()->isDebugMode();
     if ($debug) {
         log_debug('system,event', "processEvents start.");
     }
     //        $procedure = $context->getProcedure();
     //        $request   = $context->getRequest();
     //        $sequence  = $context->getSequence();
     //        $response  = $context->getResponse();
     $max_event_loop = $this->max_event_loop;
     $exit_code = 0;
     try {
         $queue = $this->queue;
         $timer_all = Charcoal_Benchmark::start();
         $loop_id = 0;
         while (!$queue->isEmpty()) {
             if ($debug) {
                 log_debug('system,event', "event queue(" . count($queue) . "): {$queue}");
             }
             // increment loop counter
             $loop_id++;
             // イベント一覧を優先度でソートする
             $queue->sortByPriority();
             /** @var Charcoal_IEvent $event */
             $event = $queue->dequeue();
             /** @var string $event_name */
             $event_name = $event->getObjectName();
             /** @var Charcoal_ObjectPath $event_id */
             $event_id = $event->getObjectPath();
             $delete_event = FALSE;
             $context->setEvent($event);
             // if this event loop exceeds [max_event_loop], thro exception
             if ($loop_id > $max_event_loop) {
                 log_warning("system,event", "[loop:{$loop_id}/{$event_name}] aborting by overflow maximum loop count[{$max_event_loop}].", "task_manager");
                 log_warning("system,event", "[loop:{$loop_id}/{$event_name}] event queue=[{$queue}].", "task_manager");
                 _throw(new Charcoal_EventLoopCounterOverflowException($max_event_loop));
             }
             if ($debug) {
                 log_debug('system,event', "[loop:{$loop_id}/{$event_name}] event loop start.");
             }
             // タスク一覧を優先度でソートする
             $key_priority = array();
             foreach ($this->tasks as $key => $task) {
                 $key_priority[$key] = ui($task->getPriority());
             }
             $a_task_list = uv($this->tasks);
             array_multisort($key_priority, SORT_DESC, $a_task_list);
             $this->tasks = v($a_task_list);
             // task list to remove on end of this loop
             $remove_tasks = NULL;
             // すべてのタスクにイベントをディスパッチする
             if ($debug) {
                 log_debug('system,event', "[loop:{$loop_id}/{$event_name}] task list: [{$this->tasks}]");
             }
             foreach ($this->tasks as $task) {
                 $task_name = $task->getObjectName();
                 $task_id = $task->getObjectPath();
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] event[{$event_name}] is dispatching to task[{$task_name}].");
                 }
                 // イベントフィルタ
                 $process = FALSE;
                 $event_filters = $task->getEventFilters();
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] task event filter: " . $event_filters);
                 }
                 foreach ($event_filters as $filter) {
                     if ($event_id->getObjectPathString() == us($filter)) {
                         $process = TRUE;
                         break;
                     }
                 }
                 if (!$process) {
                     if ($debug) {
                         log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] event[{$event_name}] is NOT found in task's event filters: [{$event_filters}]. Passing this task.");
                     }
                     continue;
                 }
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] event[{$event_name}] is found in task's event filters: [{$event_filters}].");
                 }
                 // task timer start
                 $timer_task = Charcoal_Benchmark::start();
                 $result = NULL;
                 try {
                     $result = $task->processEvent($context);
                     if ($debug) {
                         log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] returned from processEvent with result:" . print_r($result, true));
                     }
                 } catch (Charcoal_BusinessException $e) {
                     // just handle the exception
                     $exception_handled = $task->handleException($e, $context);
                     if (b($exception_handled)->isFalse()) {
                         // just re-throw the exception, if the exception was not handled by the task
                         throw $e;
                     }
                 } catch (Charcoal_RuntimeException $e) {
                     // write log and handle the exception
                     _catch($e);
                     $exception_handled = $task->handleException($e, $context);
                     if (b($exception_handled)->isFalse()) {
                         // write log and re-throw the exception, if the exception was not handled by the task
                         _throw($e);
                     }
                 }
                 // result value handling
                 $result_str = NULL;
                 if ($result === NULL) {
                     $result_str = 'NULL';
                 } elseif ($result === FALSE || $result instanceof Charcoal_Boolean && $result->isFalse()) {
                     $result_str = 'FALSE';
                     $result = FALSE;
                 } elseif ($result === TRUE || $result instanceof Charcoal_Boolean && $result->isTrue()) {
                     $result_str = 'TRUE';
                     $result = TRUE;
                 } else {
                     $msg = "processEvent() must return a [boolean] value. but returned:" . print_r($result, true);
                     log_error('system,event,error', $msg, self::TAG);
                     _throw(new Charcoal_ProcessEventAtTaskException($event, $task, $result, $msg));
                 }
                 // task timer stop
                 $elapse = Charcoal_Benchmark::stop($timer_task);
                 log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] event was processed by task. result=[{$result_str}] time=[{$elapse}]msec.");
                 // ポストアクション
                 $post_actions = $task->getPostActions();
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] task post actions: {$post_actions}");
                 }
                 if ($result && $post_actions) {
                     foreach ($post_actions as $key => $action) {
                         $target = NULL;
                         $action = us($action);
                         if (strpos(":", $action) !== FALSE) {
                             list($action, $target) = explode(":", trim($action));
                             if ($debug) {
                                 log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] post action[{$action}] with target[{$target}].");
                             }
                         } else {
                             $action = trim($action);
                             if ($debug) {
                                 log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] post action[{$action}].");
                             }
                         }
                         switch ($action) {
                             case "remove_task":
                                 // タスク実行リストからタスクを削除
                                 if (!$target) {
                                     $target = $task_id;
                                 }
                                 if ($target == $task_id) {
                                     if ($debug) {
                                         log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] task[{$target}] is marked to remove.");
                                     }
                                     $remove_tasks[] = $task_id;
                                 }
                                 break;
                             case "remove_event":
                                 // イベントを削除
                                 if (!$target) {
                                     $target = $event_id;
                                 }
                                 if ($target == $event_id) {
                                     if ($debug) {
                                         log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] event[{$target}] is marked to remove.");
                                     }
                                     $delete_event |= TRUE;
                                 }
                                 break;
                             case "continue_event":
                                 // イベントをキューに再投入
                                 break;
                         }
                     }
                 } else {
                     if ($debug) {
                         log_debug('system,event', "[loop:{$loop_id}/{$event_name}/{$task_name}] no post action is  defined for event.");
                     }
                 }
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}] task loop end.");
                 }
             }
             // task loop end
             // remove tasks
             if ($remove_tasks) {
                 foreach ($remove_tasks as $task_id) {
                     unset($this->tasks["{$task_id}"]);
                     if ($debug) {
                         log_debug('system,event', "[loop:{$loop_id}/{$event_name}] removed task: {$task_id}");
                     }
                 }
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}] next task list: [{$this->tasks}]");
                 }
             }
             if (!$delete_event) {
                 // push back the event into our event queue
                 $this->pushEvent($event);
             } else {
                 if ($debug) {
                     log_debug('system,event', "[loop:{$loop_id}/{$event_name}] event[{$event}] is removed.");
                 }
             }
             if ($debug) {
                 log_debug('system,event', "[loop:{$loop_id}/{$event_name}] event loop end.");
             }
         }
         // event loop end
         if ($queue->isEmpty()) {
             if ($debug) {
                 log_debug('system,event', "event queue is empty.");
             }
             $exit_code = Charcoal_Event::EXIT_CODE_OK;
         }
         // ログ
         $elapse = Charcoal_Benchmark::stop($timer_all);
         if ($debug) {
             log_debug('system,event', "event loop end. time=[{$elapse}]msec.");
         }
     } catch (Charcoal_RuntimeException $e) {
         _catch($e, true);
         if ($debug) {
             log_debug('system,event,debug', "an exception occured while processing event.");
         }
         _throw(new Charcoal_ProcessEventAtTaskManagerException($e));
     }
     if ($debug) {
         log_debug('system,event', "processEvents end: exit_code=" . print_r($exit_code, true));
     }
     return $exit_code;
 }