/**
   * {@inheritDoc}
   *
   * <p>Handles messages received from other clients on this channel, as well as server
   * notifications about other clients joining and leaving this channel.
   */
  public void receivedMessage(ClientChannel channel, SessionId sender, byte[] message) {
    ByteBuffer buf = ByteBuffer.wrap(message);

    byte opcode = buf.get();

    switch (opcode) {
      case OP_JOINED:
        memberList.addClient(ChatClient.getSessionId(buf));
        break;
      case OP_LEFT:
        memberList.removeClient(ChatClient.getSessionId(buf));
        break;
      case OP_MESSAGE:
        {
          byte[] contents = new byte[buf.remaining()];
          buf.get(contents);
          // The server sends us a separate, private echoback in this
          // application; those were from us originally, so use our
          // own SessionId (instead of null).
          outputArea.append(
              String.format(
                  "%s: %s\n",
                  (sender != null) ? sender : myChatClient.getSessionId(), new String(contents)));
          break;
        }
      default:
        System.err.format("Unknown opcode 0x%02X\n", opcode);
    }
  }