001/*
002 * (C) Copyright 2013-2020 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     dmetzler
018 */
019package org.nuxeo.ecm.restapi.server.jaxrs.adapters;
020
021import java.io.Serializable;
022import java.util.ArrayList;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import javax.servlet.http.HttpServletRequest;
028import javax.ws.rs.GET;
029
030import org.apache.commons.lang3.StringUtils;
031import org.nuxeo.ecm.automation.core.util.Paginable;
032import org.nuxeo.ecm.automation.core.util.PaginablePageProvider;
033import org.nuxeo.ecm.core.api.DocumentModel;
034import org.nuxeo.ecm.core.api.DocumentModelList;
035import org.nuxeo.ecm.core.api.NuxeoException;
036import org.nuxeo.ecm.core.api.SortInfo;
037import org.nuxeo.ecm.platform.query.api.PageProvider;
038import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
039import org.nuxeo.ecm.platform.query.api.PageProviderService;
040import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
041import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter;
042import org.nuxeo.runtime.api.Framework;
043
044/**
045 * Abstract adapter to be used when one want to contribute an adapter base on PageProviders.
046 * <p>
047 * In order to use it, just override the {@link PaginableAdapter#getPageProviderDefinition()} and
048 * {@link PaginableAdapter#getParams()}
049 *
050 * @since 5.7.2
051 */
052public abstract class PaginableAdapter<T> extends DefaultAdapter {
053
054    protected Long currentPageIndex;
055
056    protected Long pageSize;
057
058    protected String maxResults;
059
060    /**
061     * Sort by parameters (can be a list of sorts, separated by commas).
062     * <p>
063     * Exp: dc:title,dc:modified.
064     *
065     * @since 5.9.4
066     */
067    protected String sortBy;
068
069    /**
070     * Sort order parameters (can be a list of sorts orders, separated by commas, matched by index to corresponding sort
071     * by parameters).
072     * <p>
073     * Exp: asc,desc, or ASC,DESC. When empty, defaults to 'desc'.
074     *
075     * @since 5.9.4
076     */
077    protected String sortOrder;
078
079    @Override
080    protected void initialize(Object... args) {
081        super.initialize(args);
082        final HttpServletRequest request = ctx.getRequest();
083
084        currentPageIndex = extractLongParam(request, "currentPageIndex", 0L);
085        pageSize = extractLongParam(request, "pageSize", 50L);
086        maxResults = request.getParameter("maxResults");
087        sortBy = request.getParameter("sortBy");
088        sortOrder = request.getParameter("sortOrder");
089    }
090
091    @Override
092    public <A> A getAdapter(Class<A> adapter) {
093        if (adapter.isAssignableFrom(DocumentModelList.class)) {
094            return adapter.cast(getPaginableEntries());
095        }
096        return super.getAdapter(adapter);
097    }
098
099    abstract protected PageProviderDefinition getPageProviderDefinition();
100
101    protected Object[] getParams() {
102        return new Object[] {};
103    }
104
105    protected DocumentModel getSearchDocument() {
106        return null;
107    }
108
109    @SuppressWarnings("unchecked")
110    @GET
111    public Paginable<T> getPaginableEntries() {
112        PageProviderDefinition ppDefinition = getPageProviderDefinition();
113        if (ppDefinition == null) {
114            throw new NuxeoException("Page provider given not found");
115        }
116
117        PageProviderService pps = Framework.getService(PageProviderService.class);
118        Map<String, Serializable> props = new HashMap<>();
119        props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) ctx.getCoreSession());
120        List<SortInfo> sortInfos = null;
121        if (!StringUtils.isBlank(sortBy)) {
122            String[] sorts = sortBy.split(",");
123            String[] orders = null;
124            if (!StringUtils.isBlank(sortOrder)) {
125                orders = sortOrder.split(",");
126            }
127
128            sortInfos = new ArrayList<>(sorts.length);
129            for (int i = 0; i < sorts.length; i++) {
130                String sort = sorts[i];
131                boolean sortAscending = orders != null && orders.length > i && "asc".equals(orders[i].toLowerCase());
132                sortInfos.add(new SortInfo(sort, sortAscending));
133            }
134        }
135        PageProvider<T> pp = (PageProvider<T>) pps.getPageProvider("", ppDefinition, getSearchDocument(), sortInfos,
136                pageSize, currentPageIndex, props, getParams());
137
138        return getPaginableEntries(pp);
139    }
140
141    protected Paginable<T> getPaginableEntries(PageProvider<T> pageProvider) {
142        return new PaginablePageProvider<>(pageProvider);
143    }
144
145    protected Long extractLongParam(HttpServletRequest request, String paramName, Long defaultValue) {
146        String strParam = request.getParameter(paramName);
147        return strParam == null ? defaultValue : Long.valueOf(strParam);
148    }
149
150}