/**
  * Generates the file name of the done file, if supported by the underlying input type
  *
  * @param user the user who uploaded or will upload the file
  * @param inputType the file set type
  * @param fileUserIdentifier the file identifier
  * @param fileType the file type
  * @return the file name, starting with the directory path
  */
 protected String generateDoneFileName(
     Person user, BatchInputFileSetType inputType, String fileUserIdentifier, Date creationDate) {
   if (!isFileUserIdentifierProperlyFormatted(fileUserIdentifier)) {
     throw new IllegalArgumentException(
         "The file set identifier is not properly formatted: " + fileUserIdentifier);
   }
   return inputType.getDoneFileDirectoryPath()
       + File.separator
       + inputType.getDoneFileName(user, fileUserIdentifier, creationDate);
 }
  /**
   * @see
   *     org.kuali.kfs.sys.batch.service.BatchInputFileSetService#save(org.kuali.rice.kim.api.identity.Person,
   *     org.kuali.kfs.sys.batch.BatchInputFileSetType, java.lang.String, java.util.Map)
   */
  public Map<String, String> save(
      Person user,
      BatchInputFileSetType inputType,
      String fileUserIdentifier,
      Map<String, InputStream> typeToStreamMap)
      throws AuthorizationException, FileStorageException {
    // add a step for file directory checking
    prepareDirectories(getRequiredDirectoryNames());

    Date creationDate = SpringContext.getBean(DateTimeService.class).getCurrentDate();
    // check user is authorized to upload a file for the batch type
    Map<String, File> typeToTempFiles =
        copyStreamsToTemporaryDirectory(
            user, inputType, fileUserIdentifier, typeToStreamMap, creationDate);

    // null the map, because it's full of exhausted input streams that are useless
    typeToStreamMap = null;

    if (!inputType.validate(typeToTempFiles)) {
      deleteTempFiles(typeToTempFiles);
      LOG.error(
          "Upload file validation failed for user "
              + user.getName()
              + " identifier "
              + fileUserIdentifier);
      throw new ValidationException(
          "File validation failed: " + GlobalVariables.getMessageMap().getErrorMessages());
    }

    byte[] buf = new byte[1024];

    Map<String, String> typeToFileNames = new LinkedHashMap<String, String>();
    Map<String, File> typeToFiles = new LinkedHashMap<String, File>();
    try {
      for (String fileType : inputType.getFileTypes()) {
        File tempFile = typeToTempFiles.get(fileType);
        String saveFileName =
            inputType.getDirectoryPath(fileType) + File.separator + tempFile.getName();
        try {
          InputStream fileContents = new FileInputStream(tempFile);
          File fileToSave = new File(saveFileName);

          copyInputStreamToFile(fileContents, fileToSave, buf);
          fileContents.close();
          typeToFileNames.put(fileType, saveFileName);
          typeToFiles.put(fileType, fileToSave);
        } catch (IOException e) {
          LOG.error("unable to save contents to file " + saveFileName, e);
          throw new RuntimeException("errors encountered while writing file " + saveFileName, e);
        }
      }
    } finally {
      deleteTempFiles(typeToTempFiles);
    }

    String doneFileName =
        inputType.getDoneFileDirectoryPath()
            + File.separator
            + inputType.getDoneFileName(user, fileUserIdentifier, creationDate);
    File doneFile = new File(doneFileName);
    try {
      doneFile.createNewFile();

      typeToFiles.put(KFSConstants.DONE_FILE_TYPE, doneFile);
    } catch (IOException e) {
      LOG.error("unable to create done file", e);
      throw new RuntimeException("unable to create done file", e);
    }

    inputType.process(typeToFiles);

    return typeToFileNames;
  }