package com.twilio.base; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.twilio.exception.ApiConnectionException; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Page<T> { private final List<T> records; private final String firstPageUrl; private final String firstPageUri; private final String nextPageUrl; private final String nextPageUri; private final String previousPageUrl; private final String previousPageUri; private final String url; private final String uri; private final int pageSize; private Page(Builder<T> b) { this.records = b.records; this.firstPageUri = b.firstPageUri; this.firstPageUrl = b.firstPageUrl; this.nextPageUri = b.nextPageUri; this.nextPageUrl = b.nextPageUrl; this.previousPageUri = b.previousPageUri; this.previousPageUrl = b.previousPageUrl; this.uri = b.uri; this.url = b.url; this.pageSize = b.pageSize; } private String urlFromUri(String domain, String region, String uri) { return "https://" + Joiner.on(".").skipNulls().join(domain, region, "twilio", "com") + uri; } public List<T> getRecords() { return records; } /** * Generate first page url for a list result. * * @param domain domain to use * @param region region to use * @return the first page url */ public String getFirstPageUrl(String domain, String region) { if (firstPageUrl != null) { return firstPageUrl; } return urlFromUri(domain, region, firstPageUri); } /** * Generate next page url for a list result. * * @param domain domain to use * @param region region to use * @return the next page url */ public String getNextPageUrl(String domain, String region) { if (nextPageUrl != null) { return nextPageUrl; } return urlFromUri(domain, region, nextPageUri); } /** * Generate previous page url for a list result. * * @param domain domain to use * @param region region to use * @return the previous page url */ public String getPreviousPageUrl(String domain, String region) { if (previousPageUrl != null) { return previousPageUrl; } return urlFromUri(domain, region, previousPageUri); } public int getPageSize() { return pageSize; } /** * Generate page url for a list result. * * @param domain domain to use * @param region region to use * @return the page url */ public String getUrl(String domain, String region) { if (url != null) { return url; } return urlFromUri(domain, region, uri); } public boolean hasNextPage() { return !Strings.isNullOrEmpty(nextPageUri) || !Strings.isNullOrEmpty(nextPageUrl); } /** * Create a new page of data from a json blob. * * @param recordKey key which holds the records * @param json json blob * @param recordType resource type * @param mapper json parser * @param <T> record class type * @return a page of records of type T */ public static <T> Page<T> fromJson(String recordKey, String json, Class<T> recordType, ObjectMapper mapper) { try { List<T> results = new ArrayList<>(); JsonNode root = mapper.readTree(json); JsonNode records = root.get(recordKey); for (final JsonNode record : records) { results.add(mapper.readValue(record.toString(), recordType)); } JsonNode uriNode = root.get("uri"); if (uriNode != null) { return buildPage(root, results); } else { return buildNextGenPage(root, results); } } catch (final IOException e) { throw new ApiConnectionException( "Unable to deserialize response: " + e.getMessage() + "\nJSON: " + json, e ); } } private static <T> Page<T> buildPage(JsonNode root, List<T> results) { Builder<T> builder = new Builder<T>() .uri(root.get("uri").asText()); JsonNode nextPageNode = root.get("next_page_uri"); if (nextPageNode != null && !nextPageNode.isNull()) { builder.nextPageUri(nextPageNode.asText()); } JsonNode previousPageNode = root.get("previous_page_uri"); if (previousPageNode != null && !previousPageNode.isNull()) { builder.previousPageUri(previousPageNode.asText()); } JsonNode firstPageNode = root.get("first_page_uri"); if (firstPageNode != null && !firstPageNode.isNull()) { builder.firstPageUri(firstPageNode.asText()); } JsonNode pageSizeNode = root.get("page_size"); if (pageSizeNode != null && !pageSizeNode.isNull()) { builder.pageSize(pageSizeNode.asInt()); } else { builder.pageSize(results.size()); } return builder.records(results).build(); } private static <T> Page<T> buildNextGenPage(JsonNode root, List<T> results) { JsonNode meta = root.get("meta"); Builder<T> builder = new Builder<T>().url(meta.get("url").asText()); JsonNode nextPageNode = meta.get("next_page_url"); if (!nextPageNode.isNull()) { builder.nextPageUrl(nextPageNode.asText()); } JsonNode previousPageNode = meta.get("previous_page_url"); if (!previousPageNode.isNull()) { builder.previousPageUrl(previousPageNode.asText()); } JsonNode firstPageNode = meta.get("first_page_url"); if (!firstPageNode.isNull()) { builder.firstPageUrl(firstPageNode.asText()); } JsonNode pageSizeNode = meta.get("page_size"); if (!pageSizeNode.isNull()) { builder.pageSize(pageSizeNode.asInt()); } else { builder.pageSize(results.size()); } return builder.records(results).build(); } private static class Builder<T> { private List<T> records; private String firstPageUrl; private String firstPageUri; private String nextPageUrl; private String nextPageUri; private String previousPageUrl; private String previousPageUri; private String uri; private String url; private int pageSize; public Builder<T> records(List<T> records) { this.records = records; return this; } public Builder<T> firstPageUri(String firstPageUri) { this.firstPageUri = firstPageUri; return this; } public Builder<T> firstPageUrl(String firstPageUrl) { this.firstPageUrl = firstPageUrl; return this; } public Builder<T> nextPageUri(String nextPageUri) { this.nextPageUri = nextPageUri; return this; } public Builder<T> nextPageUrl(String nextPageUrl) { this.nextPageUrl = nextPageUrl; return this; } public Builder<T> previousPageUri(String previousPageUri) { this.previousPageUri = previousPageUri; return this; } public Builder<T> previousPageUrl(String previousPageUrl) { this.previousPageUrl = previousPageUrl; return this; } public Builder<T> uri(String uri) { this.uri = uri; return this; } public Builder<T> url(String url) { this.url = url; return this; } public Builder<T> pageSize(int pageSize) { this.pageSize = pageSize; return this; } public Page<T> build() { return new Page<>(this); } } }