/**
   * Update the waiting threads according to the wakeup reason (dispatched element). The
   * corresponding waiting activity/thread is notified.
   */
  public void updateWaitingThreads() {
    if (waittimes != null) {
      //			IClockService clock =
      // (IClockService)interpreter.getServiceProvider().getService(IClockService.class);

      IClockService clock = interpreter.getClockService();
      for (Iterator it = waittimes.keySet().iterator(); it.hasNext(); ) {
        ProcessThread thread = (ProcessThread) it.next();
        if (((Number) waittimes.get(thread)).longValue() <= clock.getTime()) {
          it.remove();
          assert thread.isWaiting();
          BpmnPlanBodyInstance.this.notify(
              thread.getActivity(),
              thread,
              AbstractEventIntermediateTimerActivityHandler.TIMER_EVENT);
        }
      }
    }

    Object dispelem = state.getAttributeValue(rplan, OAVBDIRuntimeModel.plan_has_dispatchedelement);
    //		System.out.println("dispatched: "+dispelem);

    if (dispelem != null) {
      for (Iterator it = context.getAllThreads().iterator(); it.hasNext(); ) {
        ProcessThread thread = (ProcessThread) it.next();
        try {
          if (thread.isWaiting() && thread.getWaitFilter().filter(dispelem)) {
            BpmnPlanBodyInstance.this.notify(thread.getActivity(), thread, getFlyweight(dispelem));
          }
        } catch (Exception e) {
          // just catch filter exceptions.
        }
      }
    }
  }
  /**
   * Add a timer for a thread.
   *
   * @param thread The process thread that should wait.
   * @param duration The duration to wait for.
   */
  public void addTimer(final ProcessThread thread, final long duration) {
    assert duration == EventIntermediateTimerActivityHandler.TICK_TIMER || duration >= 0;

    if (waittimes == null) waittimes = new HashMap();

    // how to support tick timer?
    if (duration == EventIntermediateTimerActivityHandler.TICK_TIMER)
      throw new UnsupportedOperationException("Tick timers for bdi-bpmn have to be implemented.");

    // todo: check if asynchronous handling of waittimes is a problem?

    IClockService clock = interpreter.getClockService();
    Long ret = new Long(clock.getTime() + duration);
    waittimes.put(thread, ret);

    //		SServiceProvider.getService(interpreter.getServiceProvider(), IClockService.class)
    //			.addResultListener(interpreter.createResultListener(new DefaultResultListener()
    //		{
    //			public void resultAvailable(Object source, Object result)
    //			{
    //				IClockService clock = (IClockService)result;
    //				Long ret = new Long(clock.getTime()+duration);
    //				waittimes.put(thread, ret);
    //			}
    //		}));
  }
 /**
  * Get the current timeout of the process, i.e. the remaining time of the closest due intermediate
  * timer event.
  *
  * @return The current timeout or -1 for no timeout.
  */
 public long getTimeout() {
   long mindur = -1;
   if (waittimes != null) {
     String pool = getPool(getLastState());
     if (!POOL_UNDEFINED.equals(pool)) {
       IClockService clock = interpreter.getClockService();
       //				IClockService	clock	=
       // (IClockService)interpreter.getServiceProvider().getService(IClockService.class);
       for (Iterator it = waittimes.keySet().iterator(); it.hasNext(); ) {
         ProcessThread thread = (ProcessThread) it.next();
         if (thread.belongsTo(pool, null)) {
           long time = Math.max(((Number) waittimes.get(thread)).longValue() - clock.getTime(), 0);
           mindur = mindur == -1 ? time : time < mindur ? time : mindur;
         }
       }
     }
   }
   return mindur;
 }