Skip to content

Commit

Permalink
Fix #23870 : Add pagination info to the API response. (#24287)
Browse files Browse the repository at this point in the history
* #23870 : Add pagination info to the API response.

* As per Freddy Montes' feedback, removing the unnecessary value for the `x-pagination-link-pages` header.

* Implementing SonarQube feedback.
  • Loading branch information
jcastro-dotcms committed Mar 10, 2023
1 parent 4d158c9 commit 124ec30
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 79 deletions.
28 changes: 7 additions & 21 deletions dotCMS/src/curl-test/UserResource.postman_collection.json
@@ -1,6 +1,6 @@
{
"info": {
"_postman_id": "baa5cd8a-ee19-4f3e-9398-f28dcc176d02",
"_postman_id": "a9eac856-e8ee-47da-96a9-f2e68e81fd72",
"name": "UserResource",
"description": "Verifies that commonly-used routines for interacting with User data are working as expected. Most of these are related to filtering operations and for back-end use only.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
Expand All @@ -20,14 +20,6 @@
"",
"var jsonData = pm.response.json().entity;",
"",
"/*pm.test(\"Contains anonymous\", function () {",
" pm.expect(containsAttrAndValue(jsonData, \"userId\" ,\"anonymous\")).to.be.true;",
"});",
"",
"pm.test(\"Contains default\", function () {",
" pm.expect(containsAttrAndValue(jsonData, \"userId\" ,\"dotcms.org.default\")).to.be.true;",
"});*/",
"",
"pm.test(\"Contains anonymous\", function () {",
" containsAttrAndValue = eval(pm.collectionVariables.get(\"containsAttrAndValue\", containsAttrAndValue.toString()));",
" pm.expect(containsAttrAndValue(jsonData, \"userId\" ,\"anonymous\")).to.be.true;",
Expand All @@ -38,19 +30,13 @@
" pm.expect(containsAttrAndValue(jsonData, \"userId\" ,\"dotcms.org.default\")).to.be.true;",
"});",
"",
"",
"/*",
"function _isContains(json, keyname, value) {",
" return Object.keys(json).some(key => {",
" return typeof json[key] === 'object' ? ",
" _isContains(json[key], keyname, value) : key === keyname && json[key] === value;",
" });",
"}",
"",
"pm.test(\"Contains default\", function () {",
" pm.expect(containsUserId(jsonData, \"userId\" ,\"dotcms.org.default\")).to.be.true;",
"pm.test(\"Check pagination data\", function () {",
" var paginationData = pm.response.json().pagination;",
" pm.expect(paginationData.currentPage).to.equal(1);",
" pm.expect(paginationData.perPage).to.equal(100);",
" pm.expect(paginationData.totalEntries).to.equal(2);",
"});",
"*/"
""
],
"type": "text/javascript"
}
Expand Down
18 changes: 13 additions & 5 deletions dotCMS/src/main/java/com/dotcms/rest/EntityView.java
Expand Up @@ -9,13 +9,21 @@
*/
public interface EntityView <T> {

public List<ErrorEntity> getErrors();
List<ErrorEntity> getErrors();

public T getEntity();
T getEntity();

public List<MessageEntity> getMessages() ;
List<MessageEntity> getMessages() ;

public Map<String, String> getI18nMessagesMap();
Map<String, String> getI18nMessagesMap();

List<String> getPermissions();

/**
* Returns the pagination parameters associated to the current data request.
*
* @return The {@link Pagination} instance.
*/
Pagination getPagination();

public List<String> getPermissions();
}
111 changes: 111 additions & 0 deletions dotCMS/src/main/java/com/dotcms/rest/Pagination.java
@@ -0,0 +1,111 @@
package com.dotcms.rest;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.io.Serializable;

/**
* Provides pagination data associated to the entity returned by any dotCMS REST Endpoint. This way, developers can
* still access pagination data even when accessing our APIs through proxies that may remove the already existing
* pagination headers.
*
* @author Jose Castro
* @since Mar 3rd, 2023
*/
@JsonDeserialize(builder = Pagination.Builder.class)
public class Pagination implements Serializable {

private final int currentPage;
private final int perPage;
private final long totalEntries;

/**
* Private constructor used to create an instance of this class.
*
* @param builder The {@link Builder} class for the pagination object.
*/
private Pagination(final Builder builder) {
this.currentPage = builder.currentPage;
this.perPage = builder.perPage;
this.totalEntries = builder.totalEntries;
}

public int getCurrentPage() {
return this.currentPage;
}

public int getPerPage() {
return this.perPage;
}

public long getTotalEntries() {
return this.totalEntries;
}

@Override
public String toString() {
return "Pagination{" + "currentPage=" + this.currentPage + ", perPage=" + this.perPage + ", totalEntries=" + this.totalEntries + '}';
}

/**
* This builder allows you to create an instance of the {@link Pagination} class.
*/
public static class Builder {

@JsonProperty
private int currentPage;
@JsonProperty
private int perPage;
@JsonProperty
private long totalEntries;

/**
* Returns the currently selected results page, or the first one if not specified.
*
* @param currentPage The current results page.
*
* @return The current {@link Builder} instance.
*/
public Builder currentPage(int currentPage) {
this.currentPage = currentPage;
return this;
}

/**
* The maximum number of items that are included in a results page.
*
* @param perPage The maximum number of returned items.
*
* @return The current {@link Builder} instance.
*/
public Builder perPage(int perPage) {
this.perPage = perPage;
return this;
}

/**
* The total number of results for a given data query. That is, the total list of <b>unfiltered items</b> for a
* given query.
*
* @param totalEntries The total number of results.
*
* @return The current {@link Builder} instance.
*/
public Builder totalEntries(long totalEntries) {
this.totalEntries = totalEntries;
return this;
}

/**
* Creates an instance of the {@link Pagination} class.
*
* @return A new instance of the {@link Pagination} class.
*/
public Pagination build() {
return new Pagination(this);
}

}

}

0 comments on commit 124ec30

Please sign in to comment.