public static PagingContext getPagingContext( final ResourceContext context, final PagingContext defaultContext) { String startString = ArgumentUtils.argumentAsString( context.getParameter(RestConstants.START_PARAM), RestConstants.START_PARAM); String countString = ArgumentUtils.argumentAsString( context.getParameter(RestConstants.COUNT_PARAM), RestConstants.COUNT_PARAM); try { int defaultStart = defaultContext == null ? RestConstants.DEFAULT_START : defaultContext.getStart(); int defaultCount = defaultContext == null ? RestConstants.DEFAULT_COUNT : defaultContext.getCount(); int start = startString == null || StringUtils.isEmpty(startString.trim()) ? defaultStart : Integer.parseInt(startString); int count = countString == null || StringUtils.isEmpty(countString.trim()) ? defaultCount : Integer.parseInt(countString); if (count < 0 || start < 0) { throw new RoutingException("start/count parameters must be non-negative", 400); } return new PagingContext(start, count, startString != null, countString != null); } catch (NumberFormatException e) { throw new RoutingException("Invalid (non-integer) start/count parameters", 400); } }
@Finder("searchWithPostFilter") public CollectionResult<Greeting, Empty> searchWithPostFilter( @PagingContextParam PagingContext ctx) { List<Greeting> greetings = new ArrayList<Greeting>(); int idx = 0; int start = ctx.getStart(); int stop = start + ctx.getCount(); for (Greeting g : _db.values()) { if (idx++ >= ctx.getStart()) { greetings.add(g); if (idx == stop) { break; } } } if (greetings.size() > 0) greetings.remove(0); // for testing, using a post-filter that just removes the first element int total = _db.values().size(); // but we keep the numElements returned as the full count despite the fact that with the filter // removed 1 // this is to keep paging consistent even in the presence of a post filter. return new CollectionResult<Greeting, Empty>(greetings, total, null, PageIncrement.FIXED); }
private static Integer getNextPageStart( int elementsOnCurrentPage, final Integer totalResults, PagingContext pagingContext, final PageIncrement pageIncrement) { if (pageIncrement == PageIncrement.RELATIVE) { if ((totalResults != null && (pagingContext.getStart() + elementsOnCurrentPage < totalResults)) || (elementsOnCurrentPage == pagingContext.getCount())) { return pagingContext.getStart() + elementsOnCurrentPage; } else { return null; // no next page } } else if (pageIncrement == PageIncrement.FIXED) { if (totalResults == null) throw new IllegalStateException( "'total' must be non-null when PageIncrement is FIXED"); // this is also checked by the // CollectionResult constructor if (pagingContext.getStart() + pagingContext.getCount() < totalResults) { return pagingContext.getStart() + pagingContext.getCount(); } else { return null; // no next page } } else { throw new IllegalStateException("Unrecognized enumeration value: " + pageIncrement); } }
@Finder("search") public List<Greeting> search( @PagingContextParam PagingContext ctx, @QueryParam("tone") @Optional Tone tone) { List<Greeting> greetings = new ArrayList<Greeting>(); int idx = 0; int start = ctx.getStart(); int stop = start + ctx.getCount(); for (Greeting g : _db.values()) { if (idx++ >= ctx.getStart()) { if (tone == null || g.getTone().equals(tone)) { greetings.add(g); } if (idx == stop) { break; } } } return greetings; }
@Finder("searchWithTones") public List<Greeting> searchWithTones( @PagingContextParam PagingContext ctx, @QueryParam("tones") @Optional Tone[] tones) { Set<Tone> toneSet = new HashSet<Tone>(Arrays.asList(tones)); List<Greeting> greetings = new ArrayList<Greeting>(); int idx = 0; int start = ctx.getStart(); int stop = start + ctx.getCount(); for (Greeting g : _db.values()) { if (idx++ >= ctx.getStart()) { if (tones == null || toneSet.contains(g.getTone())) { greetings.add(g); } if (idx == stop) { break; } } } return greetings; }
public static CollectionMetadata buildMetadata( final URI requestUri, final ResourceContext resourceContext, final ResourceMethodDescriptor methodDescriptor, final List<?> resultElements, final PageIncrement pageIncrement, final Integer totalResults) { CollectionMetadata metadata = new CollectionMetadata(); List<Parameter<?>> pagingContextParams = methodDescriptor.getParametersWithType(Parameter.ParamType.PAGING_CONTEXT_PARAM); PagingContext defaultPagingContext = pagingContextParams.isEmpty() ? null : (PagingContext) pagingContextParams.get(0).getDefaultValue(); PagingContext pagingContext = getPagingContext(resourceContext, defaultPagingContext); metadata.setCount(pagingContext.getCount()); metadata.setStart(pagingContext.getStart()); if (totalResults != null) { metadata.setTotal(totalResults); } else { metadata.removeTotal(); } LinkArray links = new LinkArray(); String bestEncoding = RestConstants.HEADER_VALUE_APPLICATION_JSON; if (resourceContext.getRawRequest() != null) { bestEncoding = pickBestEncoding(resourceContext.getRequestHeaders().get(RestConstants.HEADER_ACCEPT)); } // links use count as the step interval, so links don't make sense with count==0 if (pagingContext.getCount() > 0) { // prev link if (pagingContext.getStart() > 0) { int prevStart = Math.max(0, pagingContext.getStart() - pagingContext.getCount()); String prevUri = buildPaginatedUri(requestUri, prevStart, pagingContext.getCount()); Link prevLink = new Link(); prevLink.setRel("prev"); prevLink.setHref(prevUri); prevLink.setType(bestEncoding); links.add(prevLink); } // next link if there are more results, or we returned a full page Integer nextStart = getNextPageStart(resultElements.size(), totalResults, pagingContext, pageIncrement); if (nextStart != null) { // R2 doesn't expose host/port => can't build absolute URI (this is ok, as // relative URIs internally String nextUri = buildPaginatedUri(requestUri, nextStart, pagingContext.getCount()); Link nextLink = new Link(); nextLink.setRel("next"); nextLink.setHref(nextUri); nextLink.setType(bestEncoding); links.add(nextLink); } metadata.setLinks(links); } return metadata; }