@Override
  public boolean transformationElementRead(String xml, RepositoryImportFeedbackInterface feedback) {
    try {
      Document doc = XMLHandler.loadXMLString(getOrCreateDb(), xml);
      Node transformationNode =
          XMLHandler.getSubNode(doc, RepositoryExportSaxParser.STRING_TRANSFORMATION);
      if (!importTransformation(transformationNode, feedback)) {
        return false;
      }
      transformationNumber++;
    } catch (Exception e) {
      // Some unexpected error occurred during transformation import
      // This is usually a problem with a missing plugin or something
      // like that...
      //
      feedback.showError(
          BaseMessages.getString(
              PKG, "RepositoryImporter.UnexpectedErrorDuringTransformationImport.Title"),
          BaseMessages.getString(
              PKG, "RepositoryImporter.UnexpectedErrorDuringTransformationImport.Message"),
          e);

      if (!feedback.askContinueOnErrorQuestion(
          BaseMessages.getString(PKG, "RepositoryImporter.DoYouWantToContinue.Title"),
          BaseMessages.getString(PKG, "RepositoryImporter.DoYouWantToContinue.Message"))) {
        return false;
      }
    }
    return true;
  }
 private RepositoryDirectoryInterface getTargetDirectory(
     String directoryPath, String dirOverride, RepositoryImportFeedbackInterface feedback)
     throws KettleException {
   RepositoryDirectoryInterface targetDirectory = null;
   if (dirOverride != null) {
     targetDirectory = rep.findDirectory(directoryPath);
     if (targetDirectory == null) {
       feedback.addLog(
           BaseMessages.getString(
               PKG,
               "RepositoryImporter.CreateDir.Log",
               directoryPath,
               getRepositoryRoot().toString()));
       targetDirectory = rep.createRepositoryDirectory(getRepositoryRoot(), directoryPath);
     }
   } else {
     targetDirectory = baseDirectory.findDirectory(directoryPath);
     if (targetDirectory == null) {
       feedback.addLog(
           BaseMessages.getString(
               PKG, "RepositoryImporter.CreateDir.Log", directoryPath, baseDirectory.toString()));
       targetDirectory = rep.createRepositoryDirectory(baseDirectory, directoryPath);
     }
   }
   return targetDirectory;
 }
 private void saveJobToRepo(JobMeta jobMeta, RepositoryImportFeedbackInterface feedback)
     throws KettleException {
   try {
     jobMeta.lookupRepositoryReferences(rep);
   } catch (LookupReferencesException e) {
     // log and continue; might fail from exports performed before PDI-5294
     feedback.addLog(
         BaseMessages.getString(
             PKG,
             "RepositoryImporter.LookupRepoRefsError.Log",
             jobMeta.getName(),
             RepositoryObjectType.JOB));
     feedback.addLog(
         BaseMessages.getString(
             PKG,
             "RepositoryImporter.LookupRepoRefsError.Log.Cause",
             e.objectTypePairsToString()));
   }
   rep.save(jobMeta, "import object reference specification", null);
 }
  protected boolean importJob(Node jobnode, RepositoryImportFeedbackInterface feedback)
      throws KettleException {
    // Load the job from the XML node.
    //
    JobMeta jobMeta = createJobMetaForNode(jobnode);
    feedback.setLabel(
        BaseMessages.getString(
            PKG,
            "RepositoryImporter.ImportJob.Label",
            Integer.toString(jobNumber),
            jobMeta.getName()));
    validateImportedElement(importRules, jobMeta);

    // What's the directory path?
    String directoryPath =
        Const.NVL(XMLHandler.getTagValue(jobnode, "directory"), Const.FILE_SEPARATOR);

    if (jobDirOverride != null) {
      directoryPath = jobDirOverride;
    }

    if (directoryPath.startsWith("/")) {
      // remove the leading root, we don't need it.
      directoryPath = directoryPath.substring(1);
    }

    // If we have a set of source directories to limit ourselves to, consider this.
    //
    if (limitDirs.size() > 0 && Const.indexOfString(directoryPath, limitDirs) < 0) {
      // Not in the limiting set of source directories, skip the import of this transformation...
      //
      feedback.addLog(
          BaseMessages.getString(
              PKG,
              "RepositoryImporter.SkippedJobNotPartOfLimitingDirectories.Log",
              jobMeta.getName()));
      return true;
    }

    RepositoryDirectoryInterface targetDirectory =
        getTargetDirectory(directoryPath, jobDirOverride, feedback);

    // OK, we loaded the job from XML and all went well...
    // See if the job already exists!
    ObjectId existintId = rep.getJobId(jobMeta.getName(), targetDirectory);
    if (existintId != null && askOverwrite) {
      overwrite = feedback.jobOverwritePrompt(jobMeta);
      askOverwrite = feedback.isAskingOverwriteConfirmation();
    } else {
      updateDisplay();
    }

    if (existintId == null || overwrite) {
      replaceSharedObjects(jobMeta);
      jobMeta.setRepositoryDirectory(targetDirectory);
      jobMeta.setObjectId(existintId);
      patchJobEntries(jobMeta);
      try {
        saveJobMeta(jobMeta);

        if (jobMeta.hasRepositoryReferences()) {
          referencingObjects.add(
              new RepositoryObject(
                  jobMeta.getObjectId(),
                  jobMeta.getName(),
                  jobMeta.getRepositoryDirectory(),
                  null,
                  null,
                  RepositoryObjectType.JOB,
                  null,
                  false));
        }

        feedback.addLog(
            BaseMessages.getString(
                PKG,
                "RepositoryImporter.JobSaved.Log",
                Integer.toString(jobNumber),
                jobMeta.getName()));
      } catch (Exception e) {
        feedback.addLog(
            BaseMessages.getString(
                PKG,
                "RepositoryImporter.ErrorSavingJob.Log",
                Integer.toString(jobNumber),
                jobMeta.getName(),
                Const.getStackTracker(e)));

        if (!feedback.askContinueOnErrorQuestion(
            BaseMessages.getString(PKG, "RepositoryImporter.DoYouWantToContinue.Title"),
            BaseMessages.getString(PKG, "RepositoryImporter.DoYouWantToContinue.Message"))) {
          return false;
        }
      }
    } else {
      feedback.addLog(
          BaseMessages.getString(
              PKG, "RepositoryImporter.SkippedExistingJob.Log", jobMeta.getName()));
    }
    return true;
  }
  /**
   * @param transnode The XML DOM node to read the transformation from
   * @return false if the import should be canceled.
   * @throws KettleException in case there is an unexpected error
   */
  protected boolean importTransformation(Node transnode, RepositoryImportFeedbackInterface feedback)
      throws KettleException {
    //
    // Load transformation from XML into a directory, possibly created!
    //
    TransMeta transMeta = createTransMetaForNode(transnode); // ignore shared objects
    feedback.setLabel(
        BaseMessages.getString(
            PKG,
            "RepositoryImporter.ImportTrans.Label",
            Integer.toString(transformationNumber),
            transMeta.getName()));

    validateImportedElement(importRules, transMeta);

    // What's the directory path?
    String directoryPath =
        Const.NVL(XMLHandler.getTagValue(transnode, "info", "directory"), Const.FILE_SEPARATOR);
    if (transDirOverride != null) {
      directoryPath = transDirOverride;
    }

    if (directoryPath.startsWith("/")) {
      // remove the leading root, we don't need it.
      directoryPath = directoryPath.substring(1);
    }

    // If we have a set of source directories to limit ourselves to, consider this.
    //
    if (limitDirs.size() > 0 && Const.indexOfString(directoryPath, limitDirs) < 0) {
      // Not in the limiting set of source directories, skip the import of this transformation...
      //
      feedback.addLog(
          BaseMessages.getString(
              PKG,
              "RepositoryImporter.SkippedTransformationNotPartOfLimitingDirectories.Log",
              transMeta.getName()));
      return true;
    }

    RepositoryDirectoryInterface targetDirectory =
        getTargetDirectory(directoryPath, transDirOverride, feedback);

    // OK, we loaded the transformation from XML and all went well...
    // See if the transformation already existed!
    ObjectId existingId = rep.getTransformationID(transMeta.getName(), targetDirectory);
    if (existingId != null && askOverwrite) {
      overwrite = feedback.transOverwritePrompt(transMeta);
      askOverwrite = feedback.isAskingOverwriteConfirmation();
    } else {
      updateDisplay();
    }

    if (existingId == null || overwrite) {
      replaceSharedObjects(transMeta);
      transMeta.setObjectId(existingId);
      transMeta.setRepositoryDirectory(targetDirectory);
      patchMappingSteps(transMeta);

      try {
        // Keep info on who & when this transformation was created...
        if (transMeta.getCreatedUser() == null || transMeta.getCreatedUser().equals("-")) {
          transMeta.setCreatedDate(new Date());
          if (rep.getUserInfo() != null) {
            transMeta.setCreatedUser(rep.getUserInfo().getLogin());
          } else {
            transMeta.setCreatedUser(null);
          }
        }
        saveTransMeta(transMeta);
        feedback.addLog(
            BaseMessages.getString(
                PKG,
                "RepositoryImporter.TransSaved.Log",
                Integer.toString(transformationNumber),
                transMeta.getName()));

        if (transMeta.hasRepositoryReferences()) {
          referencingObjects.add(
              new RepositoryObject(
                  transMeta.getObjectId(),
                  transMeta.getName(),
                  transMeta.getRepositoryDirectory(),
                  null,
                  null,
                  RepositoryObjectType.TRANSFORMATION,
                  null,
                  false));
        }

      } catch (Exception e) {
        feedback.addLog(
            BaseMessages.getString(
                PKG,
                "RepositoryImporter.ErrorSavingTrans.Log",
                Integer.toString(transformationNumber),
                transMeta.getName(),
                Const.getStackTracker(e)));

        if (!feedback.askContinueOnErrorQuestion(
            BaseMessages.getString(PKG, "RepositoryImporter.DoYouWantToContinue.Title"),
            BaseMessages.getString(PKG, "RepositoryImporter.DoYouWantToContinue.Message"))) {
          return false;
        }
      }
    } else {
      feedback.addLog(
          BaseMessages.getString(
              PKG, "RepositoryImporter.SkippedExistingTransformation.Log", transMeta.getName()));
    }
    return true;
  }
  @Override
  public synchronized void importAll(
      RepositoryImportFeedbackInterface feedback,
      String fileDirectory,
      String[] filenames,
      RepositoryDirectoryInterface baseDirectory,
      boolean overwrite,
      boolean continueOnError,
      String versionComment) {
    this.baseDirectory = baseDirectory;
    this.overwrite = overwrite;
    this.continueOnError = continueOnError;
    this.versionComment = versionComment;

    String importPathCompatibility =
        System.getProperty(Const.KETTLE_COMPATIBILITY_IMPORT_PATH_ADDITION_ON_VARIABLES, "N");
    this.needToCheckPathForVariables = "N".equalsIgnoreCase(importPathCompatibility);

    askReplace = Props.getInstance().askAboutReplacingDatabaseConnections();

    if (askReplace) {
      if (feedback instanceof HasOverwritePrompter) {
        Props.getInstance().setProperty(IMPORT_ASK_ABOUT_REPLACE_CS, "Y");
        Props.getInstance().setProperty(IMPORT_ASK_ABOUT_REPLACE_DB, "Y");
        Props.getInstance().setProperty(IMPORT_ASK_ABOUT_REPLACE_PS, "Y");
        Props.getInstance().setProperty(IMPORT_ASK_ABOUT_REPLACE_SS, "Y");
        this.overwritePrompter = ((HasOverwritePrompter) feedback).getOverwritePrompter();
      } else {
        this.overwritePrompter =
            new OverwritePrompter() {

              @Override
              public boolean overwritePrompt(String arg0, String arg1, String arg2) {
                throw new RuntimeException(
                    BaseMessages.getString(PKG, "RepositoryImporter.CannotPrompt.Label"));
              }
            };
      }
    } else {
      final boolean replaceExisting = Props.getInstance().replaceExistingDatabaseConnections();
      this.overwritePrompter =
          new OverwritePrompter() {

            @Override
            public boolean overwritePrompt(String arg0, String arg1, String arg2) {
              return replaceExisting;
            }
          };
    }

    referencingObjects = new ArrayList<RepositoryObject>();

    feedback.setLabel(BaseMessages.getString(PKG, "RepositoryImporter.ImportXML.Label"));
    try {

      loadSharedObjects();

      RepositoryImportLocation.setRepositoryImportLocation(baseDirectory);

      for (int ii = 0; ii < filenames.length; ++ii) {

        final String filename =
            (!Const.isEmpty(fileDirectory))
                ? fileDirectory + Const.FILE_SEPARATOR + filenames[ii]
                : filenames[ii];
        if (log.isBasic()) {
          log.logBasic("Import objects from XML file [" + filename + "]");
        }
        feedback.addLog(BaseMessages.getString(PKG, "RepositoryImporter.WhichFile.Log", filename));

        // To where?
        feedback.setLabel(BaseMessages.getString(PKG, "RepositoryImporter.WhichDir.Label"));

        // Read it using SAX...
        //
        try {
          RepositoryExportSaxParser parser = new RepositoryExportSaxParser(filename, feedback);
          parser.parse(this);
        } catch (Exception e) {
          addException(e);
          feedback.showError(
              BaseMessages.getString(PKG, "RepositoryImporter.ErrorGeneral.Title"),
              BaseMessages.getString(PKG, "RepositoryImporter.ErrorGeneral.Message"),
              e);
        }
      }

      // Correct those jobs and transformations that contain references to other objects.
      for (RepositoryObject repoObject : referencingObjects) {
        switch (repoObject.getObjectType()) {
          case TRANSFORMATION:
            TransMeta transMeta = rep.loadTransformation(repoObject.getObjectId(), null);
            saveTransformationToRepo(transMeta, feedback);
            break;
          case JOB:
            JobMeta jobMeta = rep.loadJob(repoObject.getObjectId(), null);
            saveJobToRepo(jobMeta, feedback);
            break;
          default:
            throw new KettleException(
                BaseMessages.getString(PKG, "RepositoryImporter.ErrorDetectFileType"));
        }
      }

      feedback.addLog(BaseMessages.getString(PKG, "RepositoryImporter.ImportFinished.Log"));
    } catch (Exception e) {
      addException(e);
      feedback.showError(
          BaseMessages.getString(PKG, "RepositoryImporter.ErrorGeneral.Title"),
          BaseMessages.getString(PKG, "RepositoryImporter.ErrorGeneral.Message"),
          e);
    } finally {
      // set the repository import location to null when done!
      RepositoryImportLocation.setRepositoryImportLocation(null);
    }
  }