class WriteTask implements Future<ReadWriteResult> {

    @Override
    public ReadWriteResult get() {

        final ReadWriteResult readWriteResult = new ReadWriteResult();
        try {
            File file = getWriteOrderFile();

            if (null != workerCurrentTape) {
                if (canWriteOnTape()) {
                    doWrite(file);
                } else {
                    unloadThenLoadTapeAndWrite(file);
                }
            } else {
                loadTapeAndWrite(file);
            }

            retryable().execute(() -> updateTarReferential(file));

            readWriteResult.setStatus(StatusCode.OK);
            readWriteResult.setOrderState(QueueState.COMPLETED);

        } catch (ReadWriteException e) {
            LOGGER.error(e);
            readWriteResult.setCode(e.getReadWriteErrorCode());
            switch (e.getReadWriteErrorCode()) {
                case KO_LABEL_DISCORDING:
                case KO_LABEL_DISCORDING_NOT_EMPTY_TAPE:
                case KO_UNKNOWN_CURRENT_POSITION:
                    // TODO: 28/03/19 perhaps just rewind and retry
                    // TODO: rewind, goto position file count, retry write file
                    // TODO: ugly fix
                    workerCurrentTape.setTapeState(TapeState.CONFLICT);
                    LOGGER.warn(MSG_PREFIX + TAPE_MSG + workerCurrentTape.getCode() +
                        " is marked as conflict (incident close tape)");
                    try {
                        retryable().execute(() -> doUpdateTapeCatalog(workerCurrentTape));
                    } catch (ReadWriteException ex) {
                        LOGGER.error(ex);
                    }

                    readWriteResult.setStatus(StatusCode.FATAL);
                    readWriteResult.setOrderState(QueueState.READY);
                    break;
                case KO_ON_WRITE_TO_TAPE:
                    // FIXME: 19/03/19 error while write file in the tape. perhaps timeout ?!!
                    // Mark tape state conflict and retry with new tape
                    if (--cartridgeRetry >= 0) {
                        workerCurrentTape.setTapeState(TapeState.CONFLICT);
                        LOGGER.warn(MSG_PREFIX + TAPE_MSG + workerCurrentTape.getCode() +
                            " is marked as conflict (incident close tape)");
                        return get();
                    } else {
                        readWriteResult.setStatus(StatusCode.FATAL);
                        readWriteResult.setOrderState(QueueState.READY);
                    }
                    break;
                case KO_ON_END_OF_TAPE:
                    workerCurrentTape.setTapeState(TapeState.FULL);
                    // Re-call get, to unload current tape, load new tape then do write
                    // TODO: 28/03/19 best is to get read orders on this tape before unload
                    // TODO: read may needs rewind that can take a lot of time. unload load tape maybe better and faster than taking read orders
                    return get();
                case KO_ON_GOTO_FILE_COUNT:
                case KO_ON_REWIND_FSF_BSF_TAPE:
                case KO_REWIND_BEFORE_UNLOAD_TAPE:
                    // Error maybe IO exception or tape corrupted or timeout
                case TAPE_LOCATION_CONFLICT_ON_LOAD:
                case TAPE_LOCATION_CONFLICT_ON_UNLOAD:
                case TAPE_LOCATION_UNKNOWN:
                    // TODO: should a re-init of tape catalog
                case TAPE_NOT_FOUND_IN_CATALOG:
                    // demands to load a new tape from external
                case NO_EMPTY_SLOT_FOUND:
                    // Someone have manually modified library
                case NULL_CURRENT_TAPE:
                case KO_ON_READ_FROM_TAPE:
                case KO_ON_REWIND_TAPE:
                    // drive is open (drive empty) , tape is corrupted ? timeout ? drive is busy?
                case KO_ON_LOAD_TAPE:
                    // drive is online (already have a tape loaded)? timeout ? drive is busy?
                case KO_ON_UNLOAD_TAPE:
                    // drive is open (drive empty) ? timeout ? drive is busy?
                case KO_ON_READ_LABEL:
                case KO_DB_PERSIST:
                case KO_TAPE_CURRENT_POSITION_GREATER_THAN_FILE_COUNT:
                case KO_ON_STATUS:
                case KO_ON_LOAD_THEN_STATUS:
                case KO_ON_UNLOAD_THEN_STATUS:
                    readWriteResult.setStatus(StatusCode.FATAL);
                    readWriteResult.setOrderState(QueueState.READY);
                    break;

                case FILE_NOT_FOUND:
                    // File delete or not generated
                    // Mark write order as error state
                case INTERNAL_ERROR_SERVER:
                default:
                    readWriteResult.setStatus(StatusCode.FATAL);
                    readWriteResult.setOrderState(QueueState.ERROR);
            }
        }

        readWriteResult.setCurrentTape(workerCurrentTape);
        return readWriteResult;
    }

    public  WriteTask(
        WriteOrder writeOrder, TapeCatalog workerCurrentTape, TapeLibraryService tapeLibraryService,
        TapeCatalogService tapeCatalogService,
        ArchiveReferentialRepository archiveReferentialRepository, String inputTarPath,
        boolean forceOverrideNonEmptyCartridges);

}