| /* |
| * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // gonural - initial implementation |
| // 2014-09-01-2.6.0 Dmitry Kornilov |
| // - JPARS 2.0 related changes |
| package org.eclipse.persistence.jpa.rs.features.paging; |
| |
| import java.util.List; |
| import java.util.Map; |
| |
| import jakarta.ws.rs.core.UriBuilder; |
| import jakarta.ws.rs.core.UriInfo; |
| import jakarta.xml.bind.JAXBElement; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.ItemLinks; |
| import org.eclipse.persistence.internal.jpa.rs.weaving.PersistenceWeavedRest; |
| import org.eclipse.persistence.internal.queries.ReportItem; |
| import org.eclipse.persistence.jpa.rs.PersistenceContext; |
| import org.eclipse.persistence.jpa.rs.QueryParameters; |
| import org.eclipse.persistence.jpa.rs.features.FeatureResponseBuilderImpl; |
| import org.eclipse.persistence.jpa.rs.features.ItemLinksBuilder; |
| import org.eclipse.persistence.jpa.rs.util.HrefHelper; |
| import org.eclipse.persistence.jpa.rs.util.IdHelper; |
| import org.eclipse.persistence.jpa.rs.util.list.PageableCollection; |
| import org.eclipse.persistence.jpa.rs.util.list.ReadAllQueryResultCollection; |
| import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultCollection; |
| import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultListItem; |
| |
| /** |
| * FeatureResponseBuilder implementation used for pageable collections. Used in JPARS 2.0. |
| * |
| * @author gonural |
| * @since EclipseLink 2.6.0. |
| */ |
| public class PagingResponseBuilder extends FeatureResponseBuilderImpl { |
| |
| @Override |
| public Object buildReadAllQueryResponse(PersistenceContext context, Map<String, Object> queryParams, List<Object> items, UriInfo uriInfo) { |
| ReadAllQueryResultCollection response = new ReadAllQueryResultCollection(); |
| for (Object item : items) { |
| response.addItem(populatePagedReadAllQueryItemLinks(context, item)); |
| } |
| |
| return populatePagedCollectionLinks(queryParams, uriInfo, response); |
| } |
| |
| @Override |
| public Object buildReportQueryResponse(PersistenceContext context, Map<String, Object> queryParams, List<Object[]> results, List<ReportItem> items, UriInfo uriInfo) { |
| return populatePagedReportQueryCollectionLinks(queryParams, results, items, uriInfo); |
| } |
| |
| @Override |
| public Object buildAttributeResponse(PersistenceContext context, Map<String, Object> queryParams, String attribute, Object results, UriInfo uriInfo) { |
| if (results instanceof List) { |
| ReadAllQueryResultCollection response = new ReadAllQueryResultCollection(); |
| response.setItems((List<Object>) results); |
| return populatePagedCollectionLinks(queryParams, uriInfo, response); |
| } |
| return results; |
| } |
| |
| private Object populatePagedReadAllQueryItemLinks(PersistenceContext context, Object result) { |
| // populate links for the entity |
| ClassDescriptor descriptor = context.getJAXBDescriptorForClass(result.getClass()); |
| if ((result instanceof PersistenceWeavedRest) && (descriptor != null)) { |
| final PersistenceWeavedRest entity = (PersistenceWeavedRest) result; |
| final String href = HrefHelper.buildEntityHref(context, descriptor.getAlias(), IdHelper.stringifyId(result, descriptor.getAlias(), context)); |
| |
| final ItemLinks itemLinks = (new ItemLinksBuilder()) |
| .addSelf(href) |
| .addCanonical(href) |
| .build(); |
| |
| entity._persistence_setLinks(itemLinks); |
| return entity; |
| } |
| return result; |
| } |
| |
| private PageableCollection<?> populatePagedCollectionLinks(Map<String, Object> queryParams, UriInfo uriInfo, PageableCollection<?> resultCollection) { |
| // populate links for entire response |
| final ItemLinksBuilder itemLinksBuilder = new ItemLinksBuilder(); |
| |
| final int limit = Integer.parseInt((String) queryParams.get(QueryParameters.JPARS_PAGING_LIMIT)); |
| final int offset = Integer.parseInt((String) queryParams.get(QueryParameters.JPARS_PAGING_OFFSET)); |
| |
| final UriBuilder uriBuilder = UriBuilder.fromUri(uriInfo.getRequestUri()); |
| |
| if (resultCollection.getItems() != null) { |
| final int actualCount = resultCollection.getItems().size(); |
| if (actualCount > limit) { |
| // Remove the last item from collection. It was artificially added to indicate there are more records or not. |
| resultCollection.getItems().remove(actualCount - 1); |
| resultCollection.setCount(actualCount - 1); |
| |
| // next link |
| // The uri might have other query/matrix parameters, just replace the limit and offset |
| // for next and prev links and leave the rest untouched |
| uriBuilder.replaceQueryParam(QueryParameters.JPARS_PAGING_OFFSET, String.valueOf(limit + offset)); |
| itemLinksBuilder.addNext(uriBuilder.build().toString()); |
| resultCollection.setHasMore(true); |
| } else { |
| resultCollection.setHasMore(false); |
| resultCollection.setCount(actualCount); |
| } |
| } else { |
| resultCollection.setCount(0); |
| } |
| |
| if (offset != 0) { |
| if (offset > limit) { |
| uriBuilder.replaceQueryParam(QueryParameters.JPARS_PAGING_OFFSET, String.valueOf(offset - limit)); |
| } else { |
| uriBuilder.replaceQueryParam(QueryParameters.JPARS_PAGING_OFFSET, "0"); |
| } |
| |
| if (resultCollection.getItems() != null && !resultCollection.getItems().isEmpty()) { |
| itemLinksBuilder.addPrev(uriBuilder.build().toString()); |
| } |
| } |
| |
| itemLinksBuilder.addSelf(uriInfo.getRequestUri().toString()); |
| |
| resultCollection.setLinks(itemLinksBuilder.build().getLinks()); |
| resultCollection.setOffset(offset); |
| resultCollection.setLimit(limit); |
| |
| return resultCollection; |
| } |
| |
| /** |
| * Populate paged report query collection links. |
| * |
| * @param queryParams the query params |
| * @param results the results |
| * @param reportItems the report items |
| * @param uriInfo the uri info |
| * @return the pageable collection |
| */ |
| @SuppressWarnings({ "rawtypes" }) |
| private PageableCollection populatePagedReportQueryCollectionLinks(Map<String, Object> queryParams, List<Object[]> results, List<ReportItem> reportItems, UriInfo uriInfo) { |
| ReportQueryResultCollection response = new ReportQueryResultCollection(); |
| for (Object result : results) { |
| ReportQueryResultListItem queryResultListItem = new ReportQueryResultListItem(); |
| List<JAXBElement<?>> jaxbFields = createShellJAXBElementList(reportItems, result); |
| // We don't have a way of determining self links for the report query responses |
| // so, no links array will be inserted into individual items in the response |
| queryResultListItem.setFields(jaxbFields); |
| response.addItem(queryResultListItem); |
| } |
| |
| response.setCount(results.size()); |
| return populatePagedCollectionLinks(queryParams, uriInfo, response); |
| } |
| } |