@SuppressWarnings("unchecked")
  @Override
  public List<Map<String, Object>> searchForUsers(final Map<String, String> query) {

    LOGGER.debug("Searching for users with query terms '{}'", query);

    // Assemble searchTerms[] in expected way
    final List<String> searchTerms = new ArrayList<String>();
    final Map<String, String[]> params = new HashMap<String, String[]>();
    for (final Map.Entry<String, String> y : query.entrySet()) {
      searchTerms.add(y.getKey());
      params.put(y.getKey(), new String[] {y.getValue()});
    }

    // Build the URL
    final StringBuilder bld = new StringBuilder(REST_URI_SEARCH_PREFIX);
    for (final String key : params.keySet()) {
      bld.append("&{").append(key).append("}");
    }
    final String url = bld.toString();

    LOGGER.debug("Invoking REST enpoint with URL '{}'", url);

    // Add serchTerms[] to the params
    params.put(PARAM_SEARCH_TERMS, searchTerms.toArray(new String[0]));

    final CrossContextRestApiInvoker rest = new PatchedSimpleCrossContextRestApiInvoker();
    final HttpServletRequest req = requestForCrossContextGet();
    final HttpServletResponse res = responseForCrossContextGet();
    final Object origWebAsyncManager = req.getAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE);
    req.removeAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE);

    RestResponse rr;
    try {
      rr = rest.invoke(req, res, url, params);
    } finally {
      req.setAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, origWebAsyncManager);
    }

    final ObjectMapper mapper = new ObjectMapper();
    Map<String, List<Map<String, Object>>> value = null;
    try {
      value = mapper.readValue(rr.getWriterOutput(), Map.class);
    } catch (final Exception e) {
      final String msg = "Failed to search for users with the specified query:  " + query;
      throw new PersonAttributesSearchException(msg, e);
    }

    final List<Map<String, Object>> rslt = value.get(PEOPLE_KEY);
    if (rslt == null) {
      // Odd... should at least be an empty list
      final String msg = "Search for users returned no list for the specified query:  " + query;
      throw new PersonAttributesSearchException(msg);
    }

    LOGGER.debug("Retrieved the following people for query {}:  {}", query, rslt);

    return rslt;
  }
  @SuppressWarnings("unchecked")
  @Override
  public PersonAttributesResult getAttributes(final String username)
      throws ObjectNotFoundException {

    LOGGER.debug("Fetching attributes for user '{}'", username);

    final Map<String, String[]> params = new HashMap<String, String[]>();
    params.put(PARAM_USERNAME, new String[] {username});

    final CrossContextRestApiInvoker rest = new PatchedSimpleCrossContextRestApiInvoker();
    final HttpServletRequest req = requestForCrossContextGet();
    final HttpServletResponse res = responseForCrossContextGet();
    final Object origWebAsyncManager = req.getAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE);
    req.removeAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE);

    RestResponse rr;
    try {
      rr = rest.invoke(req, res, REST_URI_PERSON, params);
    } finally {
      req.setAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, origWebAsyncManager);
    }

    final ObjectMapper mapper = new ObjectMapper();
    Map<String, Map<String, Map<String, List<String>>>> value = null;
    try {
      value = mapper.readValue(rr.getWriterOutput(), Map.class);
    } catch (final Exception e) {
      final String msg = "Failed to access attributes for the specified person:  " + username;
      throw new UPortalSecurityException(msg, e);
    }

    final Map<String, Map<String, List<String>>> person = value.get(PERSON_KEY);
    if (person == null) {
      // No match...
      throw new ObjectNotFoundException("The specified person is unrecognized", username);
    }
    final Map<String, List<String>> rslt = person.get(ATTRIBUTES_KEY);
    if (rslt == null) {
      throw new ObjectNotFoundException(
          "No attributes are available for the specified person", username);
    }

    LOGGER.debug("Retrieved the following attributes for user {}:  {}", username, rslt.toString());

    return convertAttributes(rslt);
  }