/**
  * Helper to encapsulate the test for whether the currently authenticated user can write to the
  * preferences objects for the given username and person node reference.
  *
  * @param userName Username owner of the preferences object for modification test
  * @param personNodeRef Non-null person representing the given username
  * @return true if they are allowed to write to the user preferences, false otherwise
  */
 private boolean userCanWritePreferences(final String userName, final NodeRef personNodeRef) {
   final String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser();
   return (userName.equals(currentUserName)
       || personService
           .getUserIdentifier(userName)
           .equals(personService.getUserIdentifier(currentUserName))
       || authenticationContext.isSystemUserName(currentUserName)
       || permissionService.hasPermission(personNodeRef, PermissionService.WRITE)
           == AccessStatus.ALLOWED);
 }
  private JSONObject getPreferencesObject(String userName) throws JSONException {
    JSONObject jsonPrefs = null;

    // Get the user node reference
    NodeRef personNodeRef = this.personService.getPerson(userName);
    if (personNodeRef == null) {
      throw new AlfrescoRuntimeException(
          "Cannot get preferences for " + userName + " because he/she does not exist.");
    }

    String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser();
    boolean isSystem =
        AuthenticationUtil.isRunAsUserTheSystemUser()
            || authenticationContext.isSystemUserName(currentUserName);
    if (isSystem
        || userName.equals(currentUserName)
        || personService
            .getUserIdentifier(userName)
            .equals(personService.getUserIdentifier(currentUserName))
        || authorityService.isAdminAuthority(currentUserName)) {
      // Check for preferences aspect
      if (this.nodeService.hasAspect(personNodeRef, ContentModel.ASPECT_PREFERENCES) == true) {
        // Get the preferences for this user
        ContentReader reader =
            this.contentService.getReader(personNodeRef, ContentModel.PROP_PREFERENCE_VALUES);
        if (reader != null) {
          jsonPrefs = new JSONObject(reader.getContentString());
        }
      }
    } else {
      // The current user does not have sufficient permissions to get
      // the preferences for this user
      throw new AccessDeniedException(
          "The current user "
              + currentUserName
              + " does not have sufficient permissions to get the preferences of the user "
              + userName);
    }

    return jsonPrefs;
  }
  @Override
  public PagingResults<PersonFavourite> getPagedFavourites(
      String userName,
      Set<Type> types,
      List<Pair<FavouritesService.SortFields, Boolean>> sortProps,
      PagingRequest pagingRequest) {
    // Get the user node reference
    final NodeRef personNodeRef = personService.getPerson(userName);
    if (personNodeRef == null) {
      throw new AlfrescoRuntimeException(
          "Can not get preferences for " + userName + " because he/she does not exist.");
    }

    boolean includeFiles = types.contains(Type.FILE);
    boolean includeFolders = types.contains(Type.FOLDER);
    boolean includeSites = types.contains(Type.SITE);

    String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser();
    if (authenticationContext.isSystemUserName(currentUserName) == true
        || permissionService.hasPermission(personNodeRef, PermissionService.WRITE)
            == AccessStatus.ALLOWED
        || userName.equals(currentUserName) == true) {
      // we may have more than one favourite that is considered the same w.r.t. the PersonFavourite
      // comparator
      final Map<PersonFavouriteKey, PersonFavourite> sortedFavouriteNodes =
          new TreeMap<PersonFavouriteKey, PersonFavourite>(getComparator(sortProps));

      PrefKeys sitePrefKeys = getPrefKeys(Type.SITE);
      PrefKeys documentsPrefKeys = getPrefKeys(Type.FILE);
      PrefKeys foldersPrefKeys = getPrefKeys(Type.FOLDER);

      Map<String, Serializable> preferences = preferenceService.getPreferences(userName);
      for (String key : preferences.keySet()) {
        if (includeFiles && key.startsWith(documentsPrefKeys.sharePrefKey)) {
          String nodes = (String) preferences.get(key);
          if (nodes != null) {
            sortedFavouriteNodes.putAll(extractFavouriteNodes(userName, Type.FILE, nodes));
          }
        } else if (includeFolders && key.startsWith(foldersPrefKeys.sharePrefKey)) {
          String nodes = (String) preferences.get(key);
          if (nodes != null) {
            sortedFavouriteNodes.putAll(extractFavouriteNodes(userName, Type.FOLDER, nodes));
          }
        } else if (includeSites
            && key.startsWith(sitePrefKeys.getSharePrefKey())
            && !key.endsWith(".createdAt")) {
          // key is either of the form org.alfresco.share.sites.favourites.<siteId>.favourited or
          // org.alfresco.share.sites.favourites.<siteId>
          extractFavouriteSite(userName, Type.SITE, sortedFavouriteNodes, preferences, key);
        }
      }

      int totalSize = sortedFavouriteNodes.size();
      final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize);

      final List<PersonFavourite> page = new ArrayList<PersonFavourite>(pageDetails.getPageSize());
      Iterator<PersonFavourite> it = sortedFavouriteNodes.values().iterator();
      for (int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) {
        PersonFavourite favouriteNode = it.next();

        if (counter < pageDetails.getSkipCount()) {
          continue;
        }

        if (counter > pageDetails.getEnd() - 1) {
          break;
        }

        page.add(favouriteNode);
      }

      return new PagingResults<PersonFavourite>() {
        @Override
        public List<PersonFavourite> getPage() {
          return page;
        }

        @Override
        public boolean hasMoreItems() {
          return pageDetails.hasMoreItems();
        }

        @Override
        public Pair<Integer, Integer> getTotalResultCount() {
          Integer total = Integer.valueOf(sortedFavouriteNodes.size());
          return new Pair<Integer, Integer>(total, total);
        }

        @Override
        public String getQueryExecutionId() {
          return null;
        }
      };
    } else {
      // The current user does not have sufficient permissions to update the preferences for this
      // user
      throw new AccessDeniedException(
          "The current user "
              + currentUserName
              + " does not have sufficient permissions to get the favourites of the user "
              + userName);
    }
  }