@Override
 public void onMessage(ShellResponseMsg shellMsg) {
   String command = shellMsg.getCommand();
   if (command == null) {
     throw new IllegalArgumentException("Command not found in bolt message: " + shellMsg);
   }
   if (command.equals("sync")) {
     setHeartbeat();
   } else if (command.equals("ack")) {
     setHeartbeat();
     handleAck(shellMsg.getId());
   } else if (command.equals("fail")) {
     setHeartbeat();
     handleFail(shellMsg.getId());
   } else if (command.equals("error")) {
     handleError(shellMsg.getMsg());
   } else if (command.equals("log")) {
     handleLog(shellMsg);
   } else if (command.equals("emit")) {
     handleEmit(shellMsg);
   } else if (command.equals("metrics")) {
     handleMetrics(shellMsg);
   }
 }
  private void handleEmit(ShellResponseMsg shellMsg) {
    List<Tuple> anchors = new ArrayList<Tuple>();
    List<String> recvAnchors = shellMsg.getAnchors();
    if (recvAnchors != null) {
      for (String anchor : recvAnchors) {
        Tuple t = _inputs.get(anchor);
        if (t == null) {
          throw new RuntimeException("Anchored onto " + anchor + " after ack/fail");
        }
        anchors.add(t);
      }
    }

    if (shellMsg.getTask() == 0) {
      List<Integer> outtasks = _collector.emit(shellMsg.getStream(), anchors, shellMsg.getTuple());
      if (shellMsg.areTaskIdsNeeded()) {
        Preconditions.checkNotNull(outtasks);
        _process.writeTaskIds(outtasks);
      }
    } else {
      _collector.emitDirect(
          (int) shellMsg.getTask(), shellMsg.getStream(), anchors, shellMsg.getTuple());
    }
  }