/*
  * Method to indicate a work start.
  */
 private void workStarted(final WorkItem workItem, final Work work) {
   WorkListener listener = workItems.get(workItem);
   if (listener != null) {
     workItem.setStatus(WorkEvent.WORK_STARTED);
     WorkEvent event = new WorkEvent(workItem);
     listener.workStarted(event);
   }
 }
 /*
  * Method to indicate a work completion.
  */
 private void workCompleted(
     final WorkItem workItem, final Work work, final WorkSchedulerException exception) {
   WorkListener listener = workItems.get(workItem);
   if (listener != null) {
     workItem.setStatus(WorkEvent.WORK_COMPLETED);
     workItem.setResult(work);
     workItem.setException(exception);
     WorkEvent event = new WorkEvent(workItem);
     listener.workCompleted(event);
     workItems.remove(workItem);
   }
 }
  /**
   * Schedules a unit of work asynchronously.
   *
   * @param work Work that needs to be scheduled.
   * @param workListener Work listener for callbacks.
   * @return Work Work item representing the asynchronous work
   */
  public WorkItem schedule(Work work, WorkListener workListener) throws IllegalArgumentException {

    WorkItem workItem = new WorkItem(UUID.randomUUID().toString(), work);
    if (workListener != null) {
      workItems.put(workItem, workListener);
    }
    workAccepted(workItem, work);
    if (scheduleWork(work, workItem)) {
      return workItem;
    } else {
      workItem.setStatus(WorkEvent.WORK_REJECTED);
      if (workListener != null) {
        workListener.workRejected(new WorkEvent(workItem));
      }
      throw new IllegalArgumentException("Unable to schedule work");
    }
  }