@Override
  public void send(final T myData) throws NetworkException, InterruptedException {
    LOG.entering("GatherSender", "send", myData);
    // I am an intermediate node or a leaf.
    LOG.fine("I am " + this);

    if (init.compareAndSet(false, true)) {
      LOG.fine(this + " Communication group initializing.");
      commGroupClient.initialize();
      LOG.fine(this + " Communication group initialized.");
    }

    try {
      LOG.finest(this + " Waiting for children.");
      final byte[] gatheredData = topology.recvFromChildren();
      final byte[] encodedMyData = dataCodec.encode(myData);

      try (final ByteArrayOutputStream bstream = new ByteArrayOutputStream();
          final DataOutputStream dstream = new DataOutputStream(bstream)) {
        dstream.writeUTF(netService.getMyId().toString());
        dstream.writeInt(encodedMyData.length);
        dstream.write(encodedMyData);
        dstream.write(gatheredData);
        final byte[] mergedData = bstream.toByteArray();

        LOG.fine(this + " Sending merged value to parent.");
        topology.sendToParent(mergedData, ReefNetworkGroupCommProtos.GroupCommMessage.Type.Gather);
      }
    } catch (final ParentDeadException e) {
      throw new RuntimeException("ParentDeadException", e);
    } catch (final IOException e) {
      throw new RuntimeException("IOException", e);
    }
    LOG.exiting("GatherSender", "send");
  }
 @Override
 public void initialize() throws ParentDeadException {
   topology.initialize();
 }
 @Override
 public void onNext(final GroupCommunicationMessage msg) {
   topology.handle(msg);
 }