/**
   * Processes the list of files and performs any processing required to import that data into the
   * repository. If during processing it handles file(s) which should not be handled by downstream
   * import handlers, then it should remove them from the set of files provided.
   *
   * @param importFileSet the set of files to be imported - any files handled to completion by this
   *     Import Handler should remove this files from this list
   * @param comment the import comment provided
   * @param overwrite indicates if the process is authorized to overwrite existing content in the
   *     repository
   * @throws ImportException indicates a significant error during import processing
   */
  @Override
  public void doImport(
      final Iterable<ImportSource.IRepositoryFileBundle> importFileSet,
      final String destinationPath,
      final String comment,
      final boolean overwrite)
      throws ImportException {
    if (null == importFileSet || StringUtils.isEmpty(destinationPath)) {
      throw new IllegalArgumentException();
    }

    // Ensure the destination path is valid
    Assert.notNull(
        getParentId(RepositoryFilenameUtils.normalize(destinationPath + RepositoryFile.SEPARATOR)));

    // Iterate through the file set
    for (Iterator<IRepositoryFileBundle> iterator = importFileSet.iterator();
        iterator.hasNext(); ) {
      final ImportSource.IRepositoryFileBundle bundle =
          (ImportSource.IRepositoryFileBundle) iterator.next();

      // Make sure we don't try to do anything in a system-defined folder
      final String bundlePathName =
          RepositoryFilenameUtils.concat(computeBundlePath(bundle), bundle.getFile().getName());
      if (isSystemPath(bundlePathName)) {
        log.trace("Skipping [" + bundlePathName + "] since it is in admin / system folders");
        continue;
      }
      final String repositoryFilePath =
          RepositoryFilenameUtils.concat(destinationPath, bundlePathName);
      log.trace("Processing [" + bundlePathName + "]");

      // See if the destination already exists in the repository
      final RepositoryFile file = repository.getFile(repositoryFilePath);
      if (file != null) {
        if (file.isFolder() != bundle.getFile().isFolder()) {
          log.warn(
              "Entry already exists in the repository - but it is a "
                  + (file.isFolder() ? "folder" : "file")
                  + " and the entry to be imported is a "
                  + (bundle.getFile().isFolder() ? "folder" : "file"));
        }

        if (!overwrite) {
          log.trace("File already exists in repository and overwrite is false - skipping");
        } else if (file.isFolder()) {
          log.trace("Folder already exists - skip");
        } else {
          // It is a file we can overwrite...
          log.trace("Updating...");
          copyFileToRepository(bundle, bundlePathName, repositoryFilePath, file, comment);
        }
        // We handled this file (even if by doing nothing)
        iterator.remove();
        continue;
      }

      // The file doesn't exist - if it is a folder then this is easy
      if (bundle.getFile().isFolder()) {
        log.trace("Creating folder [" + bundlePathName + "]");
        final Serializable parentId = getParentId(repositoryFilePath);
        if (bundle.getAcl() != null) {
          repository.createFolder(parentId, bundle.getFile(), bundle.getAcl(), comment);
        } else {
          repository.createFolder(parentId, bundle.getFile(), comment);
        }
        iterator.remove();
      } else {
        // It is a file ...
        if (copyFileToRepository(bundle, bundlePathName, repositoryFilePath, null, comment)) {
          iterator.remove();
        }
      }
    }
  }
  public void importFile(IPlatformImportBundle bundle)
      throws PlatformImportException, DomainIdNullException, DomainAlreadyExistsException,
          DomainStorageException, IOException {

    RepositoryFileImportBundle importBundle = (RepositoryFileImportBundle) bundle;
    ZipInputStream zipImportStream = new ZipInputStream(bundle.getInputStream());
    SolutionRepositoryImportSource importSource =
        new SolutionRepositoryImportSource(zipImportStream);
    LocaleFilesProcessor localeFilesProcessor = new LocaleFilesProcessor();
    setOverwriteFile(bundle.overwriteInRepository());
    // importSession.set(ImportSession.getSession());

    IPlatformImporter importer = PentahoSystem.get(IPlatformImporter.class);

    cachedImports = new HashMap<String, RepositoryFileImportBundle.Builder>();

    // Process Manifest Settings
    ExportManifest manifest = getImportSession().getManifest();
    String manifestVersion = null;
    if (manifest != null) {
      manifestVersion = manifest.getManifestInformation().getManifestVersion();
    }
    // Process Metadata
    if (manifest != null) {

      // import the users
      Map<String, List<String>> roleToUserMap = importUsers(manifest.getUserExports());
      // import the roles
      importRoles(manifest.getRoleExports(), roleToUserMap);

      List<ExportManifestMetadata> metadataList = manifest.getMetadataList();
      for (ExportManifestMetadata exportManifestMetadata : metadataList) {

        String domainId = exportManifestMetadata.getDomainId();
        boolean overWriteInRepository = isOverwriteFile();
        RepositoryFileImportBundle.Builder bundleBuilder =
            new RepositoryFileImportBundle.Builder()
                .charSet("UTF-8")
                .hidden(false)
                // let the parent bundle control whether or not to preserve DSW settings
                .preserveDsw(bundle.isPreserveDsw())
                .overwriteFile(overWriteInRepository)
                .mime("text/xmi+xml")
                .withParam("domain-id", domainId);

        cachedImports.put(exportManifestMetadata.getFile(), bundleBuilder);
      }

      // Process Mondrian
      List<ExportManifestMondrian> mondrianList = manifest.getMondrianList();
      for (ExportManifestMondrian exportManifestMondrian : mondrianList) {

        String catName = exportManifestMondrian.getCatalogName();
        Parameters parametersMap = exportManifestMondrian.getParameters();
        StringBuilder parametersStr = new StringBuilder();
        for (String s : parametersMap.keySet()) {
          parametersStr.append(s).append("=").append(parametersMap.get(s)).append(sep);
        }

        RepositoryFileImportBundle.Builder bundleBuilder =
            new RepositoryFileImportBundle.Builder()
                .charSet("UTF_8")
                .hidden(false)
                .name(catName)
                .overwriteFile(isOverwriteFile())
                .mime("application/vnd.pentaho.mondrian+xml")
                .withParam("parameters", parametersStr.toString())
                .withParam("domain-id", catName); // TODO: this is
        // definitely
        // named wrong
        // at the very
        // least.
        // pass as param if not in parameters string
        String xmlaEnabled = "" + exportManifestMondrian.isXmlaEnabled();
        bundleBuilder.withParam("EnableXmla", xmlaEnabled);

        cachedImports.put(exportManifestMondrian.getFile(), bundleBuilder);

        String annotationsFile = exportManifestMondrian.getAnnotationsFile();
        if (annotationsFile != null) {
          RepositoryFileImportBundle.Builder annotationsBundle =
              new RepositoryFileImportBundle.Builder()
                  .path(
                      MondrianCatalogRepositoryHelper.ETC_MONDRIAN_JCR_FOLDER
                          + RepositoryFile.SEPARATOR
                          + catName)
                  .name("annotations.xml")
                  .charSet("UTF_8")
                  .overwriteFile(isOverwriteFile())
                  .mime("text/xml")
                  .hidden(false)
                  .withParam("domain-id", catName);
          cachedImports.put(annotationsFile, annotationsBundle);
        }
      }
    }

    importMetaStore(manifest, bundle.overwriteInRepository());

    for (IRepositoryFileBundle file : importSource.getFiles()) {
      String fileName = file.getFile().getName();
      String actualFilePath = file.getPath();
      if (manifestVersion != null) {
        fileName = ExportFileNameEncoder.decodeZipFileName(fileName);
        actualFilePath = ExportFileNameEncoder.decodeZipFileName(actualFilePath);
      }
      String repositoryFilePath =
          RepositoryFilenameUtils.concat(
              PentahoPlatformImporter.computeBundlePath(actualFilePath), fileName);

      if (this.cachedImports.containsKey(repositoryFilePath)) {

        byte[] bytes = IOUtils.toByteArray(file.getInputStream());
        RepositoryFileImportBundle.Builder builder = cachedImports.get(repositoryFilePath);
        builder.input(new ByteArrayInputStream(bytes));

        importer.importFile(build(builder));
        continue;
      }
      RepositoryFileImportBundle.Builder bundleBuilder = new RepositoryFileImportBundle.Builder();

      InputStream bundleInputStream = null;

      String decodedFilePath = file.getPath();
      RepositoryFile decodedFile = file.getFile();
      if (manifestVersion != null) {
        decodedFile =
            new RepositoryFile.Builder(decodedFile)
                .path(decodedFilePath)
                .name(fileName)
                .title(fileName)
                .build();
        decodedFilePath = ExportFileNameEncoder.decodeZipFileName(file.getPath());
      }

      if (file.getFile().isFolder()) {
        bundleBuilder.mime("text/directory");
        bundleBuilder.file(decodedFile);
        fileName = repositoryFilePath;
        repositoryFilePath = importBundle.getPath();
      } else {
        byte[] bytes = IOUtils.toByteArray(file.getInputStream());
        bundleInputStream = new ByteArrayInputStream(bytes);
        // If is locale file store it for later processing.
        if (localeFilesProcessor.isLocaleFile(file, importBundle.getPath(), bytes)) {
          log.trace("Skipping [" + repositoryFilePath + "], it is a locale property file");
          continue;
        }
        bundleBuilder.input(bundleInputStream);
        bundleBuilder.mime(solutionHelper.getMime(fileName));

        String filePath =
            (decodedFilePath.equals("/") || decodedFilePath.equals("\\")) ? "" : decodedFilePath;
        repositoryFilePath = RepositoryFilenameUtils.concat(importBundle.getPath(), filePath);
      }

      bundleBuilder.name(fileName);
      bundleBuilder.path(repositoryFilePath);

      String sourcePath;
      if (decodedFilePath.startsWith("/")) {
        sourcePath = RepositoryFilenameUtils.concat(decodedFilePath.substring(1), fileName);
      } else {
        if (file.getFile().isFolder()) {
          sourcePath = fileName;
        } else {
          sourcePath = RepositoryFilenameUtils.concat(decodedFilePath, fileName);
        }
      }

      // This clause was added for processing ivb files so that it would not try process acls on
      // folders that the user
      // may not have rights to such as /home or /public
      if (manifest != null
          && manifest.getExportManifestEntity(sourcePath) == null
          && file.getFile().isFolder()) {
        continue;
      }

      getImportSession().setCurrentManifestKey(sourcePath);

      bundleBuilder.charSet(bundle.getCharset());
      bundleBuilder.overwriteFile(bundle.overwriteInRepository());
      bundleBuilder.hidden(isFileHidden(bundle, sourcePath));
      bundleBuilder.applyAclSettings(bundle.isApplyAclSettings());
      bundleBuilder.retainOwnership(bundle.isRetainOwnership());
      bundleBuilder.overwriteAclSettings(bundle.isOverwriteAclSettings());
      bundleBuilder.acl(getImportSession().processAclForFile(sourcePath));
      IPlatformImportBundle platformImportBundle = build(bundleBuilder);
      importer.importFile(platformImportBundle);

      if (bundleInputStream != null) {
        bundleInputStream.close();
        bundleInputStream = null;
      }
    }
    if (manifest != null) {
      List<JobScheduleRequest> scheduleList = manifest.getScheduleList();
      if (scheduleList != null) {
        SchedulerResource schedulerResource = new SchedulerResource();
        for (JobScheduleRequest jobScheduleRequest : scheduleList) {
          try {
            Response response = createSchedulerJob(schedulerResource, jobScheduleRequest);
            if (response.getStatus() == Response.Status.OK.getStatusCode()) {
              if (response.getEntity() != null) {
                // get the schedule job id from the response and add it to the import session
                ImportSession.getSession()
                    .addImportedScheduleJobId(response.getEntity().toString());
              }
            }
          } catch (Exception e) {
            // there is a scenario where if the file scheduled has a space in the path, that it
            // won't work. the di server
            // replaces spaces with underscores and the export mechanism can't determine if it needs
            // this to happen or not
            // so, if we failed to import and there is a space in the path, try again but this time
            // with replacing the space(s)
            if (jobScheduleRequest.getInputFile().contains(" ")
                || jobScheduleRequest.getOutputFile().contains(" ")) {
              log.info(
                  "Could not import schedule, attempting to replace spaces with underscores and retrying: "
                      + jobScheduleRequest.getInputFile());

              jobScheduleRequest.setInputFile(
                  jobScheduleRequest.getInputFile().replaceAll(" ", "_"));
              jobScheduleRequest.setOutputFile(
                  jobScheduleRequest.getOutputFile().replaceAll(" ", "_"));
              try {
                Response response = createSchedulerJob(schedulerResource, jobScheduleRequest);
                if (response.getStatus() == Response.Status.OK.getStatusCode()) {
                  if (response.getEntity() != null) {
                    // get the schedule job id from the response and add it to the import session
                    ImportSession.getSession()
                        .addImportedScheduleJobId(response.getEntity().toString());
                  }
                }
              } catch (Exception ex) {
                throw new PlatformImportException(
                    Messages.getInstance()
                        .getString(
                            "SolutionImportHandler.ERROR_0001_ERROR_CREATING_SCHEDULE",
                            e.getMessage()));
              }
            } else {
              throw new PlatformImportException(
                  Messages.getInstance()
                      .getString(
                          "SolutionImportHandler.ERROR_0001_ERROR_CREATING_SCHEDULE",
                          e.getMessage()));
            }
          }
        }
      }

      // Add Pentaho Connections
      List<org.pentaho.database.model.DatabaseConnection> datasourceList =
          manifest.getDatasourceList();
      if (datasourceList != null) {
        IDatasourceMgmtService datasourceMgmtSvc = PentahoSystem.get(IDatasourceMgmtService.class);
        for (org.pentaho.database.model.DatabaseConnection databaseConnection : datasourceList) {
          if (databaseConnection.getDatabaseType() == null) {
            // don't try to import the connection if there is no type it will cause an error
            // However, if this is the DI Server, and the connection is defined in a ktr, it will
            // import automatically
            log.warn(
                "Can't import connection "
                    + databaseConnection.getName()
                    + " because it doesn't have a databaseType");
            continue;
          }
          try {
            IDatabaseConnection existingDBConnection =
                datasourceMgmtSvc.getDatasourceByName(databaseConnection.getName());
            if (existingDBConnection != null && existingDBConnection.getName() != null) {
              if (isOverwriteFile()) {
                databaseConnection.setId(existingDBConnection.getId());
                datasourceMgmtSvc.updateDatasourceByName(
                    databaseConnection.getName(), databaseConnection);
              }
            } else {
              datasourceMgmtSvc.createDatasource(databaseConnection);
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    }
    // Process locale files.
    localeFilesProcessor.processLocaleFiles(importer);
  }