class AbstractIso7816CommandBuilder extends AbstractApduCommandBuilder {

  protected ApduRequest setApduRequest(
      byte cla, SeCommand command, byte p1, byte p2, byte[] dataIn, Byte le) {
    boolean case4;
    /* sanity check */
    if (dataIn != null && le != null && le != 0) {
      throw new IllegalArgumentException(
          "Le must be equal to 0 when not null and ingoing data are present.");
    }

    /* Buffer allocation */
    byte[] apdu = allocateBuffer(dataIn, le);

    /* Build APDU buffer from provided arguments */
    apdu[0] = cla;
    apdu[1] = command.getInstructionByte();
    apdu[2] = p1;
    apdu[3] = p2;

    /* ISO7618 case determination and Le management */
    if (dataIn != null) {
      /* append Lc and ingoing data */
      apdu[4] = (byte) dataIn.length;
      System.arraycopy(dataIn, 0, apdu, 5, dataIn.length);
      if (le != null) {
        /*
         * case4: ingoing and outgoing data, Le is always set to 0 (see Calypso Reader
         * Recommendations - T84)
         */
        case4 = true;
        apdu[apdu.length - 1] = le;
      } else {
        /* case3: ingoing data only, no Le */
        case4 = false;
      }
    } else {
      if (le != null) {
        /* case2: outgoing data only */
        apdu[4] = le;
      } else {
        /* case1: no ingoing, no outgoing data, P3/Le = 0 */
        apdu[4] = (byte) 0x00;
      }
      case4 = false;
    }

    return new ApduRequest(command.getName(), apdu, case4);
  }

  public  AbstractIso7816CommandBuilder(SeCommand commandReference, ApduRequest request);

}