public CannedQuery<NodeWithChildrenEntity> getCannedQuery(
      NodeRef parentNodeRef,
      Date topicCreatedFrom,
      Date postCreatedFrom,
      boolean excludePrimaryPosts,
      CannedQuerySortDetails sortDetails,
      PagingRequest pagingReq) {
    ParameterCheck.mandatory("parentNodeRef", parentNodeRef);
    ParameterCheck.mandatory("pagingReq", pagingReq);

    int requestTotalCountMax = pagingReq.getRequestTotalCountMax();

    // FIXME Need tenant service like for GetChildren?
    GetDiscussionTopcisWithPostsCannedQueryParams paramBean =
        new GetDiscussionTopcisWithPostsCannedQueryParams(
            getNodeId(parentNodeRef),
            getQNameId(ContentModel.PROP_NAME),
            getQNameId(ForumModel.TYPE_TOPIC),
            getQNameId(ForumModel.TYPE_POST),
            topicCreatedFrom,
            postCreatedFrom,
            excludePrimaryPosts);

    CannedQueryPageDetails cqpd = createCQPageDetails(pagingReq);

    // create query params holder
    CannedQueryParameters params =
        new CannedQueryParameters(
            paramBean, cqpd, sortDetails, requestTotalCountMax, pagingReq.getQueryExecutionId());

    // return canned query instance
    return getCannedQuery(params);
  }
  public CannedQuery<AuthorityInfo> getCannedQuery(
      AuthorityType type,
      NodeRef containerRef,
      String displayNameFilter,
      boolean sortByDisplayName,
      boolean sortAscending,
      PagingRequest pagingRequest) {
    ParameterCheck.mandatory("containerRef", containerRef);
    ParameterCheck.mandatory("pagingRequest", pagingRequest);

    int requestTotalCountMax = pagingRequest.getRequestTotalCountMax();

    Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(tenantService.getName(containerRef));
    if (nodePair == null) {
      throw new InvalidNodeRefException(
          "Container ref does not exist: " + containerRef, containerRef);
    }

    Long containerNodeId = nodePair.getFirst();

    // specific query params
    GetAuthoritiesCannedQueryParams paramBean =
        new GetAuthoritiesCannedQueryParams(
            type,
            containerNodeId,
            getQNameId(ContentModel.PROP_AUTHORITY_DISPLAY_NAME),
            displayNameFilter);

    // page details
    CannedQueryPageDetails cqpd =
        new CannedQueryPageDetails(
            pagingRequest.getSkipCount(),
            pagingRequest.getMaxItems(),
            CannedQueryPageDetails.DEFAULT_PAGE_NUMBER,
            CannedQueryPageDetails.DEFAULT_PAGE_COUNT);

    // sort details
    CannedQuerySortDetails cqsd = null;
    if (sortByDisplayName) {
      List<Pair<? extends Object, SortOrder>> sortPairs =
          new ArrayList<Pair<? extends Object, SortOrder>>(1);
      sortPairs.add(
          new Pair<String, SortOrder>(
              "sortByName",
              (sortAscending
                  ? SortOrder.ASCENDING
                  : SortOrder.DESCENDING))); // note: sortByName is implied
      cqsd = new CannedQuerySortDetails(sortPairs);
    }

    // create query params holder
    CannedQueryParameters params =
        new CannedQueryParameters(
            paramBean, cqpd, cqsd, requestTotalCountMax, pagingRequest.getQueryExecutionId());

    // return canned query instance
    return getCannedQuery(params);
  }
  public PagingResults<Pair<String, Serializable>> getPagedPreferences(
      String userName, String preferenceFilter, PagingRequest pagingRequest) {
    final Map<String, Serializable> prefs = getPreferences(userName, preferenceFilter);

    int totalSize = prefs.size();
    int skipCount = pagingRequest.getSkipCount();
    int maxItems = pagingRequest.getMaxItems();
    int end =
        maxItems == CannedQueryPageDetails.DEFAULT_PAGE_SIZE ? totalSize : skipCount + maxItems;
    int pageSize =
        (maxItems == CannedQueryPageDetails.DEFAULT_PAGE_SIZE
            ? totalSize
            : Math.max(maxItems, totalSize - skipCount));
    final boolean hasMoreItems = end < totalSize;

    final List<Pair<String, Serializable>> page =
        new ArrayList<Pair<String, Serializable>>(pageSize);
    Iterator<Map.Entry<String, Serializable>> it = prefs.entrySet().iterator();
    for (int counter = 0; counter < end && it.hasNext(); counter++) {
      Map.Entry<String, Serializable> pref = it.next();

      if (counter < skipCount) {
        continue;
      }

      if (counter > end - 1) {
        break;
      }

      page.add(new Pair<String, Serializable>(pref.getKey(), pref.getValue()));
    }

    return new PagingResults<Pair<String, Serializable>>() {
      @Override
      public List<Pair<String, Serializable>> getPage() {
        return page;
      }

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

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

      @Override
      public String getQueryExecutionId() {
        return null;
      }
    };
  }