/**
   * Find the current dasextension::query::errors element or create a new one in the proper place in
   * the given dasextension element.
   *
   * @param dasExt - mandatory - must be a valid dasextension Element
   * @return
   */
  public ExtensibleElement getErrors(ExtensibleElement dasExt) {

    // get reference to the dasextension::query element in feed
    ExtensibleElement query = this.getQuery(dasExt);

    // get reference to the dasextension::query::errors element in feed
    QName errorsQname = new QName(this.dasextensionNamespace, "errors");
    ExtensibleElement errors = query.getExtension(errorsQname);
    if (NullChecker.isEmpty(errors)) {
      List<Element> queryChildren = query.getElements();
      if (NullChecker.isEmpty(queryChildren)) {
        // no children in query, so merely add errors element
        errors = query.addExtension(errorsQname);
      } else {
        // add errors after the last child
        errors = query.addExtension(errorsQname);
      }
    }
    return errors;
  }
 /**
  * Adds the given dasextension::query::parameters Element into the given feed. Note: This method
  * will merge the given queryParameters with any existing query::parameters in the given feed.
  *
  * @param feed - mandatory - must contain a valid feed::dasextension Element
  * @param queryParameters - mandatory - must contain a valid and non-empty
  *     dasextension::query::parameters Element.
  * @return
  */
 private Feed addQueryParameters(Feed feed, final ExtensibleElement queryParameters) {
   if (NullChecker.isNotEmpty(feed)) {
     if (NullChecker.isNotEmpty(queryParameters)) {
       // get reference to the dasextension element in feed
       ExtensibleElement dasExt =
           feed.getExtension(new QName(this.dasextensionNamespace, "dasextension"));
       if (NullChecker.isNotEmpty(dasExt)) {
         List<Element> queryParametersEntries = queryParameters.getElements();
         if (NullChecker.isNotEmpty(queryParametersEntries)) {
           // get or create the new dasextension::path::parameters Element
           ExtensibleElement queryParametersFeed = this.getQueryParameters(dasExt);
           // add in the dasextension::path::parameters::entry Elements
           for (Element curQueryParameterEntry : queryParametersEntries) {
             queryParametersFeed.addExtension(curQueryParameterEntry);
           }
         }
       }
     }
   }
   return feed;
 }
  /**
   * Places the org.osehra.integration.http.uri.UriInfo uriInfo instance's query parameter values
   * into the DAS dasextension Atom Feed at feed::dasextension::query::parameters. Notes: The feed
   * parameter must contain a constructed DAS dasextension Atom Feed. This method will remove any
   * existing feed::dasextension::query::parameters::entry elements before adding the new entries
   * from uriInfo.
   *
   * @param feed -mandatory - must contain a valid feed::dasextension Element
   * @param uriInfo - mandatory
   * @return
   */
  public Feed addQueryParameters(Feed feed, final javax.ws.rs.core.UriInfo uriInfo) {
    if (NullChecker.isNotEmpty(feed)) {
      // get reference to the dasextension element in feed
      ExtensibleElement dasExt =
          feed.getExtension(new QName(this.dasextensionNamespace, "dasextension"));
      if (NullChecker.isNotEmpty(dasExt)) {
        // check for a UriInfo to input
        if (NullChecker.isNotEmpty(uriInfo) && !(uriInfo.getQueryParameters().isEmpty())) {
          // get or create reference to the dasextension::query::parameters element in feed
          ExtensibleElement parameters = this.getQueryParameters(dasExt);

          // discard any existing path dasextension::path::parameter::entry elements
          List<Element> queryParameterEntries = parameters.getElements();
          if (NullChecker.isNotEmpty(queryParameterEntries)) {
            for (Element curQueryParameterEntry : queryParameterEntries) {
              curQueryParameterEntry.discard();
            }
          }

          // add the dasextension::query::parameters::entry elements from uriInfo
          QName entryQname = new QName(this.dasextensionNamespace, "entry");
          QName keyQname = new QName(this.dasextensionNamespace, "key");
          QName valueQname = new QName(this.dasextensionNamespace, "value");

          MultivaluedMap<String, String> queryParametersExt = uriInfo.getQueryParameters();
          Set<Map.Entry<String, List<String>>> queryParamsEntries = queryParametersExt.entrySet();
          for (Map.Entry<String, List<String>> queryParameterEntry : queryParamsEntries) {
            ExtensibleElement entry = parameters.addExtension(entryQname);
            ExtensibleElement key = entry.addExtension(keyQname);
            key.setText(queryParameterEntry.getKey());
            for (String entryValue : queryParameterEntry.getValue()) {
              ExtensibleElement value = entry.addExtension(valueQname);
              value.setText(entryValue);
            }
          }
        }
      }
    }
    return feed;
  }
  /**
   * Merge the elements in the given dasextensionToMerge Element into the feed::dasextension element
   * in the given feed. Note: The dasextension::path::parameters and dasextension::query::parameters
   * values in the given dasextensionToMerge Element will only be merged into the given feed if the
   * given feed does not already have these Elements.
   *
   * @param feed - mandatory - must contain a valid feed::dasextension Element
   * @param extensionToMerge - mandatory - must contain a valid dasextension Element
   * @return
   */
  public Feed mergeDasExtension(Feed feed, final Element dasextensionToMerge) {

    if (NullChecker.isNotEmpty(feed)) {
      if (NullChecker.isNotEmpty(dasextensionToMerge)) {

        QName mergeExtQname = dasextensionToMerge.getQName();
        String mergeExtTagName = mergeExtQname.getLocalPart();

        // if dasextensionToMerge isn't a dasextension, ignore it
        if ("dasextension".equals(mergeExtTagName)) {
          ExtensibleElement feedDasExt =
              feed.getExtension(new QName(this.dasextensionNamespace, "dasextension"));

          if (NullChecker.isNotEmpty(feedDasExt)) {
            // feed contains an existing dasextension, so merge other dasextensionToMerge with it:

            // merge dasextension::path::parameters if none are already in feed
            boolean feedPathParametersExists = this.pathParametersExists(feedDasExt);
            boolean mergePathParametersExists =
                this.pathParametersExists((ExtensibleElement) dasextensionToMerge);
            if (false == feedPathParametersExists) {
              if (mergePathParametersExists) {
                ExtensibleElement mergePathParameters =
                    this.getPathParameters((ExtensibleElement) dasextensionToMerge);
                feed = this.addPathParameters(feed, mergePathParameters);
              }
            }

            // merge dasextension::query::parameters if none are already in feed
            boolean feedQueryParametersExists = this.queryParametersExists(feedDasExt);
            boolean mergeQueryParametersExists =
                this.queryParametersExists((ExtensibleElement) dasextensionToMerge);
            if (false == feedQueryParametersExists) {
              if (mergeQueryParametersExists) {
                ExtensibleElement mergeQueryParameters =
                    this.getQueryParameters((ExtensibleElement) dasextensionToMerge);
                feed = this.addQueryParameters(feed, mergeQueryParameters);
              }
            }

            // collect all of the current dasextension sites::site elements
            List<Element> siteElements = new ArrayList<Element>();
            ExtensibleElement mergeSites = this.getSites((ExtensibleElement) dasextensionToMerge);
            if (NullChecker.isNotEmpty(mergeSites)) {
              siteElements.addAll(mergeSites.getElements());
            }

            // add in the site elements into the feed's dasextension
            for (final Element siteElement : siteElements) {
              feed = this.addSite(feed, (ExtensibleElement) siteElement);
            }

            // collect all of the merge dasextension errors::error elements
            List<Element> errorElements = new ArrayList<Element>();
            ExtensibleElement mergeErrors = this.getErrors((ExtensibleElement) dasextensionToMerge);
            if (NullChecker.isNotEmpty(mergeErrors)) {
              errorElements.addAll(mergeErrors.getElements());
            }

            // add in the error elements into the feed's dasextension
            for (final Element errorElement : errorElements) {
              feed = this.addError(feed, (ExtensibleElement) errorElement);
            }

          } else {
            // feed has no existing dasextension element, so add in dasextensionToMerge
            feed.addExtension(dasextensionToMerge);
          }
        }
      }
    }
    return feed;
  }
  /**
   * Adds a single site element into the DAS dasextension Atom Feed. i.e. adds one of the following
   * inside of feed::dasextension::query::sites: <site> <id></id> <name></name>
   * <expectedCount></expectedCount> <retrievedCount></retrievedCount> <status></status>
   * <error></error> </site> Notes: The feed parameter must contain a constructed DAS dasextension
   * Atom Feed. An existing site element with the same site::name value as the given siteName value
   * will be removed before the new site element is added.
   *
   * @param feed - mandatory - must contain a valid feed::dasextension Element
   * @param siteName - mandatory
   * @param siteId - optional
   * @param siteHttpStatus - mandatory
   * @param expectedCount - optional
   * @param retrievedCount - optional
   * @param siteErrorMessage - optional
   * @return
   */
  public Feed addSite(
      Feed feed,
      final String siteName,
      final String siteId,
      final int siteHttpStatus,
      final String expectedCount,
      final String retrievedCount,
      final String siteErrorMessage) {
    if (NullChecker.isNotEmpty(feed)) {
      // get reference to the dasextension element in feed
      ExtensibleElement dasExt =
          feed.getExtension(new QName(this.dasextensionNamespace, "dasextension"));
      if (NullChecker.isNotEmpty(dasExt)) {
        // get reference to the dasextension::query::sites element in feed
        ExtensibleElement sites = this.getSites(dasExt);

        // search for any existing site children by site::name value with
        // the new siteName, and if one is found, remove it
        List<Element> siteElements = sites.getElements();
        for (Element curSiteElement : siteElements) {
          List<Element> siteChildElements = curSiteElement.getElements();
          for (Element curSiteChildElement : siteChildElements) {
            if ("name".equals(curSiteChildElement.getQName().getLocalPart())) {
              if (siteName.equals(curSiteChildElement.getText())) {
                curSiteElement.discard();
              }
            }
          }
        }

        // add the dasextension::query::sites::site element
        QName siteQname = new QName(this.dasextensionNamespace, "site");
        ExtensibleElement site = sites.addExtension(siteQname);
        if (NullChecker.isNotEmpty(siteId)) {
          QName idQname = new QName(this.dasextensionNamespace, "id");
          ExtensibleElement idElement = site.addExtension(idQname);
          idElement.setText(siteId);
        }
        QName nameQname = new QName(this.dasextensionNamespace, "name");
        ExtensibleElement nameElement = site.addExtension(nameQname);
        nameElement.setText(siteName);
        if (NullChecker.isNotEmpty(expectedCount)) {
          QName expectedCountQname = new QName(this.dasextensionNamespace, "expectedCount");
          ExtensibleElement expectedCountElement = site.addExtension(expectedCountQname);
          expectedCountElement.setText(expectedCount);
        }
        if (NullChecker.isNotEmpty(retrievedCount)) {
          QName retrievedCountQname = new QName(this.dasextensionNamespace, "retrievedCount");
          ExtensibleElement retrievedCountElement = site.addExtension(retrievedCountQname);
          retrievedCountElement.setText(retrievedCount);
        }
        QName statusQname = new QName(this.dasextensionNamespace, "status");
        ExtensibleElement statusElement = site.addExtension(statusQname);
        String siteStatus = new Integer(siteHttpStatus).toString();
        statusElement.setText(siteStatus);
        if (NullChecker.isNotEmpty(siteErrorMessage)) {
          QName errorQname = new QName(this.dasextensionNamespace, "error");
          ExtensibleElement siteErrorElement = site.addExtension(errorQname);
          siteErrorElement.setText(siteErrorMessage);
        }
      }
    }
    return feed;
  }