class PoTransaction {

  public final void processOpening(PoTransaction.SessionSetting.AccessLevel accessLevel) {
    currentAccessLevel = accessLevel;

    // create a sublist of AbstractPoCommandBuilder to be sent atomically
    List<AbstractPoCommandBuilder<? extends AbstractPoResponseParser>> poAtomicCommands =
        new ArrayList<AbstractPoCommandBuilder<? extends AbstractPoResponseParser>>();

    AtomicInteger neededSessionBufferSpace = new AtomicInteger();
    AtomicBoolean overflow = new AtomicBoolean();

    for (AbstractPoCommandBuilder<? extends AbstractPoResponseParser> commandBuilder :
        poCommandManager.getPoCommandBuilders()) {
      // check if the command is a modifying one and get it status (overflow yes/no,
      // neededSessionBufferSpace)
      // if the command overflows the session buffer in atomic modification mode, an exception
      // is raised.
      if (checkModifyingCommand(commandBuilder, overflow, neededSessionBufferSpace)) {
        if (overflow.get()) {
          // Open the session with the current commands
          processAtomicOpening(currentAccessLevel, poAtomicCommands);
          // Closes the session, resets the modifications buffer counters for the next
          // round (set the contact mode to avoid the transmission of the ratification)
          processAtomicClosing(
              null, SessionSetting.RatificationMode.CLOSE_RATIFIED, ChannelControl.KEEP_OPEN);
          resetModificationsBufferCounter();
          // Clear the list and add the command that did not fit in the PO modifications
          // buffer. We also update the usage counter without checking the result.
          poAtomicCommands.clear();
          poAtomicCommands.add(commandBuilder);
          // just update modifications buffer usage counter, ignore result (always false)
          isSessionBufferOverflowed(neededSessionBufferSpace.get());
        } else {
          // The command fits in the PO modifications buffer, just add it to the list
          poAtomicCommands.add(commandBuilder);
        }
      } else {
        // This command does not affect the PO modifications buffer
        poAtomicCommands.add(commandBuilder);
      }
    }

    processAtomicOpening(currentAccessLevel, poAtomicCommands);

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

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

}