/**
   * Submit a request to the server which expects an execution id in response, and return a single
   * QueuedItemResult parsed from the response.
   *
   * @param tempxml xml temp file (or null)
   * @param otherparams parameters for the request
   * @param requestPath
   * @return a single QueuedItemResult
   * @throws com.dtolabs.rundeck.core.dispatcher.CentralDispatcherException if an error occurs
   */
  private QueuedItemResult submitRunRequest(
      final File tempxml, final HashMap<String, String> otherparams, final String requestPath)
      throws CentralDispatcherException {

    final HashMap<String, String> params = new HashMap<String, String>();
    if (null != otherparams) {
      params.putAll(otherparams);
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(requestPath, params, tempxml, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    final Document resultDoc = response.getResultDoc();

    if (null != resultDoc.selectSingleNode("/result/execution")
        && null != resultDoc.selectSingleNode("/result/execution/@id")) {
      final Node node = resultDoc.selectSingleNode("/result/execution/@id");
      final String succeededId = node.getStringValue();
      final String name = "adhoc";
      String url = createExecutionURL(succeededId);
      url = makeAbsoluteURL(url);
      logger.info("\t[" + succeededId + "] <" + url + ">");
      return QueuedItemResultImpl.successful("Succeeded queueing " + name, succeededId, url, name);
    }
    return QueuedItemResultImpl.failed("Server response contained no success information.");
  }
  /**
   * Submit a request to the server which expects a list of execution items in the response, and
   * return a single QueuedItemResult parsed from the response.
   *
   * @param tempxml xml temp file (or null)
   * @param otherparams parameters for the request
   * @param requestPath
   * @return a single QueuedItemResult
   * @throws com.dtolabs.rundeck.core.dispatcher.CentralDispatcherException if an error occurs
   */
  private QueuedItemResult submitExecutionRequest(
      final File tempxml, final HashMap<String, String> otherparams, final String requestPath)
      throws CentralDispatcherException {

    final HashMap<String, String> params = new HashMap<String, String>();
    if (null != otherparams) {
      params.putAll(otherparams);
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(requestPath, params, tempxml, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    final ArrayList<QueuedItem> list = parseExecutionListResult(response);
    if (null == list || list.size() < 1) {

      return QueuedItemResultImpl.failed("Server response contained no success information.");
    } else {

      final QueuedItem next = list.iterator().next();
      return QueuedItemResultImpl.successful(
          "Succeeded queueing " + next.getName(), next.getId(), next.getUrl(), next.getName());
    }
  }
  private ArrayList<QueuedItem> parseExecutionListResult(final WebserviceResponse response) {
    final Document resultDoc = response.getResultDoc();

    final Node node = resultDoc.selectSingleNode("/result/executions");
    final List items = node.selectNodes("execution");
    final ArrayList<QueuedItem> list = new ArrayList<QueuedItem>();
    if (null != items && items.size() > 0) {
      for (final Object o : items) {
        final Node node1 = (Node) o;
        final String id = node1.selectSingleNode("@id").getStringValue();
        final Node jobname = node1.selectSingleNode("job/name");
        final Node desc = node1.selectSingleNode("description");
        final String name;
        if (null != jobname) {
          name = jobname.getStringValue();
        } else {
          name = desc.getStringValue();
        }
        String url = node1.selectSingleNode("@href").getStringValue();
        url = makeAbsoluteURL(url);
        logger.info("\t" + ": " + name + " [" + id + "] <" + url + ">");
        list.add(QueuedItemResultImpl.createQueuedItem(id, url, name));
      }
    }
    return list;
  }
  public Collection<QueuedItem> listDispatcherQueue() throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("xmlreq", "true");

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(RUNDECK_LIST_EXECUTIONS_PATH, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    validateResponse(response);

    ////////////////////
    // parse result list of queued items, return the collection of QueuedItems
    ///////////////////

    final Document resultDoc = response.getResultDoc();

    final Node node = resultDoc.selectSingleNode("/result/items");
    final List items = node.selectNodes("item");
    final ArrayList<QueuedItem> list = new ArrayList<QueuedItem>();
    if (null != items && items.size() > 0) {
      for (final Object o : items) {
        final Node node1 = (Node) o;
        final String id = node1.selectSingleNode("id").getStringValue();
        final String name = node1.selectSingleNode("name").getStringValue();
        String url = node1.selectSingleNode("url").getStringValue();
        url = makeAbsoluteURL(url);
        logger.info("\t" + ": " + name + " [" + id + "] <" + url + ">");
        list.add(QueuedItemResultImpl.createQueuedItem(id, url, name));
      }
    }

    return list;
  }
  /**
   * Submit a request to the server which expects a list of queued item results in the response, and
   * return a single QueuedItemResult parsed from the response.
   *
   * @param tempxml xml temp file (or null)
   * @param otherparams parameters for the request
   * @param requestPath
   * @return a single QueuedItemResult
   * @throws CentralDispatcherException if an error occurs
   */
  private QueuedItemResult submitQueueRequest(
      final File tempxml, final HashMap<String, String> otherparams, final String requestPath)
      throws CentralDispatcherException {

    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("xmlreq", "true");
    if (null != otherparams) {
      params.putAll(otherparams);
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(requestPath, params, tempxml, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    ////////////////////
    // parse result list of execution responses.  this implementation handles multiple responses,
    // but only
    // returns a single QueuedItem (the first one found).
    // TODO: update to return multiple QueuedItems when multiple job queue requests are supported
    ///////////////////

    final Document resultDoc = response.getResultDoc();

    final int succeeded;
    final int failed;

    Node node = resultDoc.selectSingleNode("/result/succeeded/@count");
    if (null != node) {
      succeeded = Integer.parseInt(node.getStringValue());
    } else {
      succeeded = -1;
    }
    node = resultDoc.selectSingleNode("/result/failed/@count");
    if (null != node) {
      failed = Integer.parseInt(node.getStringValue());
    } else {
      failed = -1;
    }
    final String succeededId;
    if (succeeded > 0) {
      logger.info("Succeeded queueing " + succeeded + " Job" + (succeeded > 1 ? "s" : "") + ":");
      final List nodes = resultDoc.selectNodes("/result/succeeded/execution");
      final Node node1 = (Node) nodes.iterator().next();
      final String index = node1.selectSingleNode("@index").getStringValue();
      final String id = node1.selectSingleNode("id").getStringValue();
      succeededId = id;
      final String name = node1.selectSingleNode("name").getStringValue();
      String url = node1.selectSingleNode("url").getStringValue();
      url = makeAbsoluteURL(url);
      logger.info("\t" + index + ": " + name + " [" + id + "] <" + url + ">");
      return QueuedItemResultImpl.successful("Succeeded queueing " + name, succeededId, url, name);
    }
    if (failed > 0) {
      final String s1 = "Failed to queue " + failed + " Job" + (failed > 1 ? "s" : "") + ":";
      logger.error(s1);
      final List nodes = resultDoc.selectNodes("/result/failed/execution");
      final Node node1 = (Node) nodes.iterator().next();
      final String index = node1.selectSingleNode("@index").getStringValue();
      final String id =
          null != node1.selectSingleNode("id")
              ? node1.selectSingleNode("id").getStringValue()
              : null;
      String url =
          null != node1.selectSingleNode("url")
              ? node1.selectSingleNode("url").getStringValue()
              : null;
      url = makeAbsoluteURL(url);
      final String error =
          null != node1.selectSingleNode("error")
              ? node1.selectSingleNode("error").getStringValue()
              : null;
      final String message =
          null != node1.selectSingleNode("message")
              ? node1.selectSingleNode("message").getStringValue()
              : null;
      final String errmsg =
          error
              + (null != id ? " [" + id + "] <" + url + ">" : "")
              + (null != message ? " : " + message : "");
      final String s2 = index + ": " + errmsg;
      logger.error(s2);
      return QueuedItemResultImpl.failed(errmsg);
    }
    return QueuedItemResultImpl.failed("Server response contained no success information.");
  }