class PoTransaction {

  public final void processVerifyPin(byte[] pin) {
    Assert.getInstance()
        .notNull(pin, "pin")
        .isEqual(pin.length, CalypsoPoUtils.PIN_LENGTH, "PIN length");

    if (!calypsoPo.isPinFeatureAvailable()) {
      throw new CalypsoPoTransactionIllegalStateException("PIN is not available for this PO.");
    }

    if (poCommandManager.hasCommands()) {
      throw new CalypsoPoTransactionIllegalStateException(
          "No commands should have been prepared prior to a PIN submission.");
    }

    if (poSecuritySettings != null
        && PinTransmissionMode.ENCRYPTED.equals(poSecuritySettings.getPinTransmissionMode())) {
      poCommandManager.addRegularCommand(new PoGetChallengeCmdBuild(calypsoPo.getPoClass()));

      // transmit and receive data with the PO
      processAtomicPoCommands(poCommandManager.getPoCommandBuilders(), ChannelControl.KEEP_OPEN);

      // sets the flag indicating that the commands have been executed
      poCommandManager.notifyCommandsProcessed();

      // Get the encrypted PIN with the help of the SAM
      byte[] cipheredPin =
          samCommandProcessor.getCipheredPinData(CalypsoPoUtils.getPoChallenge(), pin, null);
      poCommandManager.addRegularCommand(
          new VerifyPinCmdBuild(
              calypsoPo.getPoClass(), PinTransmissionMode.ENCRYPTED, cipheredPin));
    } else {
      poCommandManager.addRegularCommand(
          new VerifyPinCmdBuild(calypsoPo.getPoClass(), PinTransmissionMode.PLAIN, pin));
    }

    // transmit and receive data with the PO
    processAtomicPoCommands(poCommandManager.getPoCommandBuilders(), channelControl);

    // sets the flag indicating that the commands have been executed
    poCommandManager.notifyCommandsProcessed();
  }

  public  PoTransaction(SeResource<CalypsoPo> poResource, PoSecuritySettings poSecuritySettings);
  public  PoTransaction(SeResource<CalypsoPo> poResource);

}