/**
   * **************************************************
   *
   * <p>private Map<String, JazzChangeSet> accept(Collection<String> changeSets) throws IOException,
   * InterruptedException {
   *
   * <p>**************************************************
   */
  private Map<String, JazzChangeSet> accept(Collection<String> changeSets)
      throws IOException, InterruptedException {
    // output to console.
    PrintStream output = listener.getLogger();
    output.println("  RTC SCM - Jazz Client: Accept...");
    String version =
        getVersion(); // TODO The version should be checked when configuring the Jazz Executable

    String[] streams = configuration.getStreamNames();
    Map<String, JazzChangeSet> returnObject = new LinkedHashMap<String, JazzChangeSet>();

    for (int i = 0; i < streams.length; i++) {
      configuration.setStreamIndex(i);
      AcceptCommand cmd =
          new AcceptCommand(configuration, changeSets, version, listener, jazzExecutable);
      Map<String, JazzChangeSet> acceptResults = execute(cmd);
      // for debugging
      /*
         output.println("DEBUG: results of calling accept...");
         for (String key : acceptResults.keySet()) {
      output.println("DEBUG: accept key = " + key + ": " + acceptResults.get(key).toStringDetails());
         }
         */

      returnObject.putAll(acceptResults);
    }

    return returnObject;
  }
  /**
   * **************************************************
   *
   * <p>private int joinWithPossibleTimeout(ProcStarter proc, final TaskListener listener,
   * StringBuffer strBuf, AbstractBuild currentBuild) throws IOException, InterruptedException
   *
   * <p>**************************************************
   */
  protected int joinWithPossibleTimeout(
      ProcStarter proc,
      final TaskListener listener,
      StringBuffer strBuf,
      AbstractBuild currentBuild,
      String stringToHide)
      throws IOException, InterruptedException {
    boolean useTimeout = configuration.isUseTimeout();
    long timeoutValue = configuration.getTimeoutValue();

    int result = -1;

    try {
      PipedInputStream pis = null;
      if (strBuf != null) {
        PipedOutputStream pos = new PipedOutputStream();
        pis = new PipedInputStream(pos, 1000000);
        proc = proc.stdout(pos);
      }

      hudson.Proc procStarted = proc.start();
      if (useTimeout) {
        result = procStarted.joinWithTimeout(timeoutValue, TimeUnit.SECONDS, listener);
      } else {
        result = procStarted.join();
      }

      if (strBuf != null) {
        byte[] stdoutDataArr = new byte[pis.available()];
        pis.read(stdoutDataArr, 0, stdoutDataArr.length);
        String stdoutStr = new String(stdoutDataArr);
        if (stringToHide != null) {
          stdoutStr = stdoutStr.replaceAll(stringToHide, "****");
        }
        strBuf.append(stdoutStr);
        PrintStream output = listener.getLogger();
        output.println(stdoutStr);
      }
    } catch (InterruptedException e) {
      throw e;
    } catch (Exception e) {
      if (listener != null) {
        listener.error("Exception caught in joinWithPossibleTimeout: " + e);
      }
    }

    return result;
  } // End: joinWithPossibleTimeout(...)
  /**
   * **************************************************
   *
   * <p>private Map<String, JazzChangeSet> compare() throws IOException, InterruptedException {
   *
   * <p>**************************************************
   */
  private Map<String, JazzChangeSet> compare() throws IOException, InterruptedException {

    PrintStream output = listener.getLogger();
    output.println("  RTC SCM - Jazz Client: compare...");

    Map<String, JazzChangeSet> returnObject = new LinkedHashMap<String, JazzChangeSet>();
    String[] streams = configuration.getStreamNames();

    for (int i = 0; i < streams.length; i++) {
      configuration.setStreamIndex(i);
      CompareCommand cmd = new CompareCommand(configuration);
      returnObject.putAll(execute(cmd));
    }

    return returnObject;
  }
  /**
   * **************************************************
   *
   * <p>public boolean workspaceExists() throws IOException, InterruptedException {
   *
   * <p>Call <tt>scm history</tt> command.
   *
   * <p>
   *
   * <p>Will check if the workspace exists.
   *
   * @return <tt>true</tt> on exists
   * @throws IOException
   * @throws InterruptedException **************************************************
   */
  public boolean workspaceExists(AbstractBuild build) throws IOException, InterruptedException {
    // output to console.
    PrintStream output = listener.getLogger();
    Command cmd = new HistoryCommand(configuration);
    output.println(
        "  RTC SCM - Jazz Client: Run History command to determine if workspace exists - it is OK if an error is returned below: (Problem running 'history')");

    // Get variables from system.
    String jobName = "";

    try {
      jobName = build.getEnvironment(null).get("JOB_NAME");
    } catch (Exception e) {
      listener.error("" + e);
    }
    // Add the abstract build to the configuration.
    // This call happens before the load and accept so we can set these items for later use.
    configuration.setBuild(build);
    configuration.setTaskListener(listener);
    configuration.setJobName(jobName);
    configuration.consoleOut("    -- Initializing build object --");

    StringBuffer strBuf = new StringBuffer();
    joinWithPossibleTimeout(run(cmd.getArguments()), listener, strBuf, build, null);
    boolean result = true;
    String stdOut = strBuf.toString();

    if (stdOut.contains("did not match any workspaces") || stdOut.contains("Unmatched workspace")) {
      listener.error("The workspace probably doesn't exist.");

      output.println("  RTC SCM - Jazz Client: Specified workspace does not exist...");

      result = false;
    } else {
      output.println("  RTC SCM - Jazz Client: Specified workspace already exists...");
    }
    return result;
  }
  /**
   * **************************************************
   *
   * <p>public List<JazzChangeSet> accept() throws IOException, InterruptedException {
   *
   * <p>Call <tt>scm accept</tt> command.
   *
   * <p>
   *
   * @return all changeSets accepted, complete with affected paths and related work items
   * @throws IOException
   * @throws InterruptedException **************************************************
   */
  public List<JazzChangeSet> accept() throws IOException, InterruptedException {
    // output to console.
    PrintStream output = listener.getLogger();
    output.println("  RTC SCM - Jazz Client: Accepting changes...");
    String defaultWS = configuration.getWorkspaceName();

    // configuration.display("JazzClient - accept(1)");

    Map<String, JazzChangeSet> compareCmdResults = compare();

    output.println("      -------------------------------------");
    if (!compareCmdResults.isEmpty()) {
      output.println(
          "      -- " + compareCmdResults.values().size() + " Code Changes - Detected --");

      // Remove any changesets that are component additions
      //	what happens if the addition is the only change?
      //	does accept command change for components/changesets
      // output.println(compareCmdResults.keySet().size() + " changesets.");
      boolean componentsChanged = false;
      if (compareCmdResults.containsKey("Added component")) {
        compareCmdResults.remove("Added component");
        componentsChanged = true;
      }
      // output.println(compareCmdResults.keySet().size() + " changesets AFTER.");

      Map<String, JazzChangeSet> acceptResults = accept(compareCmdResults.keySet());

      if (componentsChanged) {
        load();
      }

      // Merge the data from the accept command into the original compare results data
      for (Map.Entry<String, JazzChangeSet> entry : compareCmdResults.entrySet()) {
        JazzChangeSet basicItem = entry.getValue();
        JazzChangeSet extraItem = acceptResults.get(entry.getKey());
        if (extraItem != null) basicItem.copyItemsFrom(extraItem);
      }

      output.println("      -- Code Changes - 'Accept' Complete");
    } else {
      output.println("      -- NO Code Changes Detected");
    }
    output.println("      -------------------------------------");

    return new ArrayList<JazzChangeSet>(compareCmdResults.values());
  }