@Override
  public void readFrom(ChannelBuffer data) {
    super.readFrom(data);

    command = data.readByte();
    groupType = data.readByte();
    actionNum = data.readByte();
    data.readByte();
    groupId = data.readInt();

    counterId = data.readInt();
    data.readBytes(4);

    this.actionList =
        this.actionFactory.parseActions(
            data, OFGlobal.OFP_MAX_ACTION_NUMBER_PER_GROUP * OFAction.MAXIMAL_LENGTH);
  }
  @Override
  public void writeTo(ChannelBuffer data) {
    super.writeTo(data);
    data.writeByte(command);
    data.writeByte(groupType);
    data.writeByte(actionNum);
    data.writeByte(0);
    data.writeInt(groupId);

    data.writeInt(counterId);
    data.writeZero(4);

    if (actionList == null) {
      data.writeZero(OFGlobal.OFP_MAX_ACTION_NUMBER_PER_GROUP * OFAction.MAXIMAL_LENGTH);
    } else {
      OFAction action;

      if (actionNum > actionList.size()) {
        throw new RuntimeException(
            "actionNum " + actionNum + " > actionList.size()" + actionList.size());
      }

      int i;
      for (i = 0; i < actionNum && i < OFGlobal.OFP_MAX_ACTION_NUMBER_PER_GROUP; i++) {
        action = actionList.get(i);
        if (action == null) {
          data.writeZero(OFAction.MAXIMAL_LENGTH);
        } else {
          action.writeTo(data);
          if (action.getLength() < OFAction.MAXIMAL_LENGTH) {
            data.writeZero(OFAction.MAXIMAL_LENGTH - action.getLength());
          }
        }
      }
      if (i < OFGlobal.OFP_MAX_ACTION_NUMBER_PER_GROUP) {
        data.writeZero((OFGlobal.OFP_MAX_ACTION_NUMBER_PER_GROUP - i) * OFAction.MAXIMAL_LENGTH);
      }
    }
  }