/**
   * Favorite or unfavorite a site.
   *
   * @param site : Site object to manage
   * @param addSite : true to favorite the site. False to unfavorite the site.
   */
  private Site favoriteSite(Site site, boolean addSite) {
    if (isObjectNull(site)) {
      throw new IllegalArgumentException(
          String.format(
              Messagesl18n.getString("ErrorCodeRegistry.GENERAL_INVALID_ARG_NULL"), "site"));
    }

    Site updatedSite = null;

    try {
      String link =
          OnPremiseUrlRegistry.getUserPreferenceUrl(session, session.getPersonIdentifier());
      UrlBuilder url = new UrlBuilder(link);

      // prepare json data
      String[] sitePrefence = {"org", "alfresco", "share", "sites", "favourites"};

      JSONObject jroot = new JSONObject();
      JSONObject jt = null;
      JSONObject jp = jroot;
      for (int i = 0; i < sitePrefence.length; i++) {
        jt = new JSONObject();
        jp.put(sitePrefence[i], jt);
        jp = jt;
      }
      jt.put(site.getIdentifier(), addSite);

      final JsonDataWriter formDataM = new JsonDataWriter(jroot);

      // send
      post(
          url,
          formDataM.getContentType(),
          new HttpUtils.Output() {
            public void write(OutputStream out) throws IOException {
              formDataM.write(out);
            }
          },
          ErrorCodeRegistry.SITE_GENERIC);
      updateExtraPropertyCache(
          site.getIdentifier(), site.isPendingMember(), site.isMember(), addSite);
      updatedSite = new SiteImpl(site, site.isPendingMember(), site.isMember(), addSite);
      validateUpdateSite(updatedSite, ErrorCodeRegistry.SITE_GENERIC);
    } catch (Exception e) {
      convertException(e);
    }

    return updatedSite;
  }
  @Override
  public void addFavorite(Node node) {
    if (isObjectNull(node)) {
      throw new IllegalArgumentException(
          String.format(
              Messagesl18n.getString("ErrorCodeRegistry.GENERAL_INVALID_ARG_NULL"), "node"));
    }
    try {
      String link =
          PublicAPIUrlRegistry.getUserPreferenceUrl(session, session.getPersonIdentifier());
      UrlBuilder url = new UrlBuilder(link);

      // prepare json data
      String preferenceFilter = "target.file";
      if (node.isFolder()) {
        preferenceFilter = "target.folder";
      }

      String[] filter = preferenceFilter.split("\\.");

      JSONObject jroot = new JSONObject();
      JSONObject jt = null;
      JSONObject jp = jroot;
      for (int i = 0; i < filter.length; i++) {
        jt = new JSONObject();
        jp.put(filter[i], jt);
        jp = jt;
      }
      jt.put(PublicAPIConstant.GUID_VALUE, NodeRefUtils.getCleanIdentifier(node.getIdentifier()));

      final JsonDataWriter formDataM = new JsonDataWriter(jroot);

      // send
      post(
          url,
          formDataM.getContentType(),
          new Output() {
            public void write(OutputStream out) throws IOException {
              formDataM.write(out);
            }
          },
          ErrorCodeRegistry.DOCFOLDER_GENERIC);
    } catch (Exception e) {
      convertException(e);
    }
  }
  /** {@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;
  }