001/*
002 * (C) Copyright 2013-2018 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.HashMap;
023import java.util.Map;
024
025import javax.servlet.http.HttpServletRequest;
026import javax.ws.rs.GET;
027
028import org.apache.commons.lang3.StringUtils;
029import org.nuxeo.ecm.automation.core.util.Paginable;
030import org.nuxeo.ecm.automation.core.util.PaginablePageProvider;
031import org.nuxeo.ecm.core.api.DocumentModel;
032import org.nuxeo.ecm.core.api.DocumentModelList;
033import org.nuxeo.ecm.core.api.NuxeoException;
034import org.nuxeo.ecm.platform.query.api.PageProvider;
035import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
036import org.nuxeo.ecm.platform.query.api.PageProviderService;
037import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
038import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter;
039import org.nuxeo.runtime.api.Framework;
040
041/**
042 * Abstract adapter to be used when one want to contribute an adapter base on PageProviders.
043 * <p>
044 * In order to use it, just override the {@link PaginableAdapter#getPageProviderDefinition()} and
045 * {@link PaginableAdapter#getParams()}
046 *
047 * @since 5.7.2
048 */
049public abstract class PaginableAdapter<T> extends DefaultAdapter {
050
051    protected Long currentPageIndex;
052
053    protected Long pageSize;
054
055    protected String maxResults;
056
057    /**
058     * Sort by parameters (can be a list of sorts, separated by commas).
059     * <p>
060     * Exp: dc:title,dc:modified.
061     *
062     * @since 5.9.4
063     */
064    protected String sortBy;
065
066    /**
067     * Sort order parameters (can be a list of sorts orders, separated by commas, matched by index to corresponding sort
068     * by parameters).
069     * <p>
070     * Exp: asc,desc, or ASC,DESC. When empty, defaults to 'desc'.
071     *
072     * @since 5.9.4
073     */
074    protected String sortOrder;
075
076    @Override
077    protected void initialize(Object... args) {
078        super.initialize(args);
079        final HttpServletRequest request = ctx.getRequest();
080
081        currentPageIndex = extractLongParam(request, "currentPageIndex", 0L);
082        pageSize = extractLongParam(request, "pageSize", 50L);
083        maxResults = request.getParameter("maxResults");
084        sortBy = request.getParameter("sortBy");
085        sortOrder = request.getParameter("sortOrder");
086    }
087
088    @Override
089    public <A> A getAdapter(Class<A> adapter) {
090        if (adapter.isAssignableFrom(DocumentModelList.class)) {
091            return adapter.cast(getPaginableEntries());
092        }
093        return super.getAdapter(adapter);
094    }
095
096    abstract protected PageProviderDefinition getPageProviderDefinition();
097
098    protected Object[] getParams() {
099        return new Object[] {};
100    }
101
102    protected DocumentModel getSearchDocument() {
103        return null;
104    }
105
106    @SuppressWarnings("unchecked")
107    @GET
108    public Paginable<T> getPaginableEntries() {
109        PageProviderDefinition ppDefinition = getPageProviderDefinition();
110        if (ppDefinition == null) {
111            throw new NuxeoException("Page provider given not found");
112        }
113
114        PageProviderService pps = Framework.getService(PageProviderService.class);
115        Map<String, Serializable> props = new HashMap<>();
116        props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) ctx.getCoreSession());
117        PageProvider<T> pp = (PageProvider<T>) pps.getPageProvider("", ppDefinition, getSearchDocument(), null,
118                pageSize, currentPageIndex, props, getParams());
119        if (!StringUtils.isBlank(sortBy)) {
120            String[] sorts = sortBy.split(",");
121            String[] orders = null;
122            if (!StringUtils.isBlank(sortOrder)) {
123                orders = sortOrder.split(",");
124            }
125            if (sorts != null) {
126                // clear potential default sort infos first
127                pp.setSortInfos(null);
128                for (int i = 0; i < sorts.length; i++) {
129                    String sort = sorts[i];
130                    boolean sortAscending = (orders != null && orders.length > i
131                            && "asc".equals(orders[i].toLowerCase())) ? true : false;
132                    pp.addSortInfo(sort, sortAscending);
133                }
134            }
135        }
136        return getPaginableEntries(pp);
137    }
138
139    protected Paginable<T> getPaginableEntries(PageProvider<T> pageProvider) {
140        return new PaginablePageProvider<>(pageProvider);
141    }
142
143    protected Long extractLongParam(HttpServletRequest request, String paramName, Long defaultValue) {
144        String strParam = request.getParameter(paramName);
145        return strParam == null ? defaultValue : Long.valueOf(strParam);
146    }
147
148}