/** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  private List<String> computeFavoriteSite(String username) {
    // find the link
    String link = OnPremiseUrlRegistry.getUserFavoriteSitesUrl(session, username);

    UrlBuilder url = new UrlBuilder(link);

    HttpUtils.Response resp = read(url, ErrorCodeRegistry.SITE_GENERIC);

    Map<String, Object> json = JsonUtils.parseObject(resp.getStream(), resp.getCharset());

    String[] s = OnPremiseUrlRegistry.PREFERENCE_SITES.split("\\.");
    for (int i = 0; i < s.length; i++) {
      if (json.get(s[i]) != null) {
        json = (Map<String, Object>) json.get(s[i]);
      }
    }

    List<String> tmpList = new ArrayList<String>();
    Map<String, Boolean> map = (Map<String, Boolean>) json.get(OnPremiseUrlRegistry.FAVOURITES);
    if (map != null) {
      for (Map.Entry<String, Boolean> entry : map.entrySet()) {
        if (entry.getValue()) {
          tmpList.add(entry.getKey());
        }
      }
    }

    return tmpList;
  }
  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  protected PagingResult<Site> computeSites(UrlBuilder url, ListingContext listingContext) {
    HttpUtils.Response resp = read(url, ErrorCodeRegistry.SITE_GENERIC);

    List<Object> json = JsonUtils.parseArray(resp.getStream(), resp.getCharset());
    int size = json.size();

    List<Site> result = new ArrayList<Site>();
    int fromIndex = 0, toIndex = size;
    Boolean hasMoreItems = false;

    // Define Listing Context
    if (listingContext != null) {
      fromIndex = (listingContext.getSkipCount() > size) ? size : listingContext.getSkipCount();

      // Case if skipCount > result size
      if (listingContext.getMaxItems() + fromIndex >= size) {
        toIndex = size;
        hasMoreItems = false;
      } else {
        toIndex = listingContext.getMaxItems() + fromIndex;
        hasMoreItems = true;
      }
    }

    String siteName = null;
    Map<String, Object> mapProperties = null;
    CacheSiteExtraProperties extraProperties = null;
    for (int i = fromIndex; i < toIndex; i++) {
      mapProperties = (Map<String, Object>) json.get(i);
      if (mapProperties != null) {
        siteName = JSONConverter.getString(mapProperties, OnPremiseConstant.SHORTNAME_VALUE);
        if (extraPropertiesCache.get(siteName) != null) {
          extraProperties = extraPropertiesCache.get(siteName);
          mapProperties.put(
              OnPremiseConstant.ISPENDINGMEMBER_VALUE, extraProperties.isPendingMember);
          mapProperties.put(OnPremiseConstant.ISMEMBER_VALUE, extraProperties.isMember);
          mapProperties.put(OnPremiseConstant.ISFAVORITE_VALUE, extraProperties.isFavorite);
        }
        result.add(SiteImpl.parseJson((Map<String, Object>) json.get(i)));
      }
    }

    if (listingContext != null) {
      Collections.sort(
          result,
          new AlphaComparator(listingContext.isSortAscending(), listingContext.getSortProperty()));
    }

    return new PagingResultImpl<Site>(result, hasMoreItems, size);
  }
  @SuppressWarnings("unchecked")
  private List<String> getUserSite(String personIdentifier) {
    HttpUtils.Response resp =
        read(getUserSitesUrl(personIdentifier, null), ErrorCodeRegistry.SITE_GENERIC);
    List<Object> json = JsonUtils.parseArray(resp.getStream(), resp.getCharset());
    int size = json.size();
    List<String> userSites = new ArrayList<String>(size);

    for (Object object : json) {
      userSites.add(
          JSONConverter.getString((Map<String, Object>) object, OnPremiseConstant.SHORTNAME_VALUE));
    }
    return userSites;
  }
  /**
   * Internal method to compute data from server and transform it as high level object.
   *
   * @param url : Alfresco REST API activity url
   * @param listingContext : listing context to apply to the paging result.
   * @return Paging Result of activity entry.
   */
  @SuppressWarnings("unchecked")
  protected PagingResult<ActivityEntry> computeActivities(
      UrlBuilder url, ListingContext listingContext) {
    try {
      // read and parse
      HttpUtils.Response resp = read(url, ErrorCodeRegistry.ACTIVITISTREAM_GENERIC);

      List<Object> json = JsonUtils.parseArray(resp.getStream(), resp.getCharset());
      int size = json.size();
      ArrayList<ActivityEntry> result = new ArrayList<ActivityEntry>(size);

      Boolean b = false;
      if (listingContext != null) {
        int fromIndex =
            (listingContext.getSkipCount() > size) ? size : listingContext.getSkipCount();

        // Case if skipCount > result size
        if (listingContext.getMaxItems() + fromIndex >= size) {
          json = json.subList(fromIndex, size);
          b = false;
        } else {
          json = json.subList(fromIndex, listingContext.getMaxItems() + fromIndex);
          b = true;
        }
      }

      if (json != null) {
        for (Object obj : json) {
          result.add(ActivityEntryImpl.parseJson((Map<String, Object>) obj));
        }
      }

      return new PagingResultImpl<ActivityEntry>(result, b, size);
    } catch (Exception e) {
      convertException(e);
    }
    return null;
  }
  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  protected List<JoinSiteRequestImpl> getJoinSiteRequests() {
    List<JoinSiteRequestImpl> requestList = new ArrayList<JoinSiteRequestImpl>();
    try {
      // build URL
      String link =
          OnPremiseUrlRegistry.getJoinRequestSiteUrl(session, session.getPersonIdentifier());
      UrlBuilder url = new UrlBuilder(link);

      // send and parse
      HttpUtils.Response resp = read(url, ErrorCodeRegistry.SITE_GENERIC);
      Map<String, Object> json = JsonUtils.parseObject(resp.getStream(), resp.getCharset());
      List<Object> jo = (List<Object>) json.get(OnPremiseConstant.DATA_VALUE);

      for (Object obj : jo) {
        requestList.add(JoinSiteRequestImpl.parseJson((Map<String, Object>) obj));
      }

    } catch (Exception e) {
      convertException(e);
    }
    return requestList;
  }
  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  protected String parseContainer(String link) {
    String n = null;

    UrlBuilder url = new UrlBuilder(link);
    HttpUtils.Response resp = HttpUtils.invokeGET(url, getSessionHttp());

    // check response code
    if (resp.getResponseCode() == HttpStatus.SC_NOT_FOUND) {
      return null;
    } else if (resp.getResponseCode() != HttpStatus.SC_OK) {
      convertStatusCode(resp, ErrorCodeRegistry.SITE_GENERIC);
    }

    Map<String, Object> json = JsonUtils.parseObject(resp.getStream(), resp.getCharset());

    if (json.size() == 1) {
      Map<String, Object> jo =
          (Map<String, Object>) ((List<Object>) json.get(OnPremiseConstant.CONTAINER_VALUE)).get(0);
      n = (String) jo.get(OnPremiseConstant.NODEREF_VALUE);
    }

    return n;
  }
  /**
   * Determine if the current user is member of the specific site.
   *
   * @param site :
   * @return true if the current user is member. False otherwise.
   */
  private boolean isMemberOf(Site site) {
    boolean isMember = false;
    try {
      // build URL
      String link =
          OnPremiseUrlRegistry.getMemberOfSiteUrl(
              session, site.getIdentifier(), session.getPersonIdentifier());
      UrlBuilder url = new UrlBuilder(link);

      // send and parse
      HttpUtils.Response resp = read(url, ErrorCodeRegistry.SITE_GENERIC);
      Map<String, Object> json = JsonUtils.parseObject(resp.getStream(), resp.getCharset());
      if (json != null) {
        isMember = true;
      }
    } catch (AlfrescoServiceException e) {
      if (e.getErrorCode() == 400) {
        isMember = false;
      } else {
        convertException(e);
      }
    }
    return isMember;
  }
  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  public Site joinSite(Site site) {
    if (isObjectNull(site)) {
      throw new IllegalArgumentException(
          String.format(
              Messagesl18n.getString("ErrorCodeRegistry.GENERAL_INVALID_ARG_NULL"), "site"));
    }

    Site updatedSite = null;

    try {
      String link = null;
      UrlBuilder url = null;
      HttpUtils.Response resp = null;
      JSONObject jo = null;
      Map<String, Object> json = null;

      // Check isMember because on onPremise theres no error message if
      // the user is already member of a site.
      if (isMemberOf(site)) {
        throw new AlfrescoServiceException(
            ErrorCodeRegistry.SITE_ALREADY_MEMBER,
            Messagesl18n.getString("ErrorCodeRegistry.SITE_ALREADY_MEMBER"));
      }

      switch (site.getVisibility()) {
        case PUBLIC:
          // Prepare URL
          link = OnPremiseUrlRegistry.getJoinPublicSiteUrl(session, site.getIdentifier());
          url = new UrlBuilder(link);

          // prepare json data
          jo = new JSONObject();
          jo.put(OnPremiseConstant.ROLE_VALUE, DEFAULT_ROLE);
          JSONObject jp = new JSONObject();
          jp.put(OnPremiseConstant.USERNAME_VALUE, session.getPersonIdentifier());
          jo.put(OnPremiseConstant.PERSON_VALUE, jp);

          final JsonDataWriter formData = new JsonDataWriter(jo);

          // send and parse
          resp =
              post(
                  url,
                  formData.getContentType(),
                  new HttpUtils.Output() {
                    public void write(OutputStream out) throws IOException {
                      formData.write(out);
                    }
                  },
                  ErrorCodeRegistry.SITE_GENERIC);

          // By default Contains informations about authority &
          // membership
          json = JsonUtils.parseObject(resp.getStream(), resp.getCharset());

          updateExtraPropertyCache(site.getIdentifier(), false, true, site.isFavorite());
          updatedSite = new SiteImpl(site, false, true, site.isFavorite());
          validateUpdateSite(updatedSite, ErrorCodeRegistry.SITE_GENERIC);
          break;

        case MODERATED:
          if (hasJoinRequest(site)) {
            throw new AlfrescoServiceException(
                ErrorCodeRegistry.SITE_ALREADY_MEMBER,
                Messagesl18n.getString("ErrorCodeRegistry.SITE_ALREADY_MEMBER.request"));
          }

          link = OnPremiseUrlRegistry.getJoinModeratedSiteUrl(session, site.getIdentifier());
          url = new UrlBuilder(link);

          // prepare json data
          jo = new JSONObject();
          jo.put(OnPremiseConstant.INVITATIONTYPE_VALUE, SiteVisibility.MODERATED.value());
          jo.put(OnPremiseConstant.INVITEEUSERNAME_VALUE, session.getPersonIdentifier());
          jo.put(OnPremiseConstant.INVITEECOMMENTS_VALUE, null);
          jo.put(OnPremiseConstant.INVITEEROLENAME_VALUE, DEFAULT_ROLE);

          final JsonDataWriter formDataM = new JsonDataWriter(jo);

          // send and parse
          resp =
              post(
                  url,
                  formDataM.getContentType(),
                  new HttpUtils.Output() {
                    public void write(OutputStream out) throws IOException {
                      formDataM.write(out);
                    }
                  },
                  ErrorCodeRegistry.SITE_GENERIC);
          json = JsonUtils.parseObject(resp.getStream(), resp.getCharset());
          Map<String, Object> jmo = (Map<String, Object>) json.get(OnPremiseConstant.DATA_VALUE);
          if (jmo != null) {
            updateExtraPropertyCache(site.getIdentifier(), true, false, site.isFavorite());
            updatedSite = new SiteImpl(site, true, false, site.isFavorite());
            validateUpdateSite(updatedSite, ErrorCodeRegistry.SITE_GENERIC);
          } else {
            throw new AlfrescoServiceException(
                ErrorCodeRegistry.SITE_GENERIC,
                Messagesl18n.getString("ErrorCodeRegistry.SITE_NOT_JOINED.parsing"));
          }
          break;
        case PRIVATE:
          throw new AlfrescoServiceException(
              ErrorCodeRegistry.SITE_GENERIC,
              Messagesl18n.getString("ErrorCodeRegistry.SITE_NOT_JOINED.private"));
        default:
          throw new IllegalArgumentException(
              String.format(
                  Messagesl18n.getString("ErrorCodeRegistry.GENERAL_INVALID_ARG_NULL"),
                  "visibility"));
      }
    } catch (Exception e) {
      convertException(e);
    }

    return updatedSite;
  }