public void crawl(SearchPerformer performer, CrawlableSearchResult sr) {
   if (performer != null && !performer.isStopped()) {
     try {
       SearchTask task = new CrawlTask(this, performer, sr, getOrder(performer.getToken()));
       submitSearchTask(task);
     } catch (Throwable e) {
       LOG.warn("Error scheduling crawling of search result: " + sr);
     }
   } else {
     LOG.warn("Search performer is null or stopped, review your logic");
   }
 }
  @Override
  public void perform(SearchPerformer performer) {
    if (performer != null) {
      if (performer.getToken() < 0) {
        throw new IllegalArgumentException("Search token id mut be >= 0");
      }

      performer.registerListener(new PerformerResultListener(this));

      SearchTask task = new PerformTask(this, performer, getOrder(performer.getToken()));

      submitSearchTask(task);
    } else {
      LOG.warn("Search performer is null, review your logic");
    }
  }
  void checkIfFinished(SearchPerformer performer) {
    SearchTask pendingTask = null;

    synchronized (tasks) {
      Iterator<SearchTask> it = tasks.iterator();
      while (it.hasNext() && pendingTask == null) {
        SearchTask task = it.next();
        if (task.getToken() == performer.getToken() && !task.isStopped()) {
          pendingTask = task;
        }

        if (task.isStopped()) {
          it.remove();
        }
      }
    }

    if (pendingTask == null) {
      onFinished(performer.getToken());
    }
  }
 public void stop() {
   performer.stop();
 }
 public boolean isStopped() {
   return performer.isStopped();
 }
 public long getToken() {
   return performer.getToken();
 }