001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     dmetzler
016 */
017package org.nuxeo.ecm.restapi.server.jaxrs.adapters;
018
019import java.io.Serializable;
020import java.util.HashMap;
021import java.util.Map;
022
023import javax.servlet.http.HttpServletRequest;
024import javax.ws.rs.GET;
025
026import org.apache.commons.lang.StringUtils;
027import org.nuxeo.ecm.automation.core.util.Paginable;
028import org.nuxeo.ecm.automation.core.util.PaginablePageProvider;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.DocumentModelList;
031import org.nuxeo.ecm.core.api.NuxeoException;
032import org.nuxeo.ecm.platform.query.api.PageProvider;
033import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
034import org.nuxeo.ecm.platform.query.api.PageProviderService;
035import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
036import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter;
037import org.nuxeo.runtime.api.Framework;
038
039/**
040 * Abstract adapter to be used when one want to contribute
041 * an adapter base on PageProviders. In order to use it,
042 * just override the {@link PaginableAdapter#getPageProviderDefinition()}
043 * and {@link PaginableAdapter#getParams()}
044 *
045 * @since 5.7.2
046 */
047/**
048 * Abstract adapter to be used when one want to contribute an adapter base on PageProviders.
049 * <p>
050 * In order to use it, just override the {@link PaginableAdapter#getPageProviderDefinition()} and
051 * {@link PaginableAdapter#getParams()}
052 *
053 * @since 5.7.2
054 */
055public abstract class PaginableAdapter<T> extends DefaultAdapter {
056
057    protected Long currentPageIndex;
058
059    protected Long pageSize;
060
061    protected String maxResults;
062
063    /**
064     * Sort by parameters (can be a list of sorts, separated by commas).
065     * <p>
066     * Exp: dc:title,dc:modified.
067     *
068     * @since 5.9.4
069     */
070    protected String sortBy;
071
072    /**
073     * Sort order parameters (can be a list of sorts orders, separated by commas, matched by index to corresponding sort
074     * by parameters).
075     * <p>
076     * Exp: asc,desc, or ASC,DESC. When empty, defaults to 'desc'.
077     *
078     * @since 5.9.4
079     */
080    protected String sortOrder;
081
082    @Override
083    protected void initialize(Object... args) {
084        super.initialize(args);
085        final HttpServletRequest request = ctx.getRequest();
086
087        currentPageIndex = extractLongParam(request, "currentPageIndex", 0L);
088        pageSize = extractLongParam(request, "pageSize", 50L);
089        maxResults = request.getParameter("maxResults");
090        sortBy = request.getParameter("sortBy");
091        sortOrder = request.getParameter("sortOrder");
092    }
093
094    @Override
095    public <A> A getAdapter(Class<A> adapter) {
096        if (adapter.isAssignableFrom(DocumentModelList.class)) {
097            return adapter.cast(getPaginableEntries());
098        }
099        return super.getAdapter(adapter);
100    }
101
102    abstract protected PageProviderDefinition getPageProviderDefinition();
103
104    protected Object[] getParams() {
105        return new Object[] {};
106    }
107
108    protected DocumentModel getSearchDocument() {
109        return null;
110    }
111
112    @SuppressWarnings("unchecked")
113    @GET
114    public Paginable<T> getPaginableEntries() {
115        PageProviderDefinition ppDefinition = getPageProviderDefinition();
116        if (ppDefinition == null) {
117            throw new NuxeoException("Page provider given not found");
118        }
119
120        PageProviderService pps = Framework.getLocalService(PageProviderService.class);
121        Map<String, Serializable> props = new HashMap<String, Serializable>();
122        props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) ctx.getCoreSession());
123        PageProvider<T> pp = (PageProvider<T>) pps.getPageProvider("", ppDefinition, getSearchDocument(), null,
124                pageSize, currentPageIndex, props, getParams());
125        if (!StringUtils.isBlank(sortBy)) {
126            String[] sorts = sortBy.split(",");
127            String[] orders = null;
128            if (!StringUtils.isBlank(sortOrder)) {
129                orders = sortOrder.split(",");
130            }
131            if (sorts != null) {
132                // clear potential default sort infos first
133                pp.setSortInfos(null);
134                for (int i = 0; i < sorts.length; i++) {
135                    String sort = sorts[i];
136                    boolean sortAscending = (orders != null && orders.length > i && "asc".equals(orders[i].toLowerCase())) ? true
137                            : false;
138                    pp.addSortInfo(sort, sortAscending);
139                }
140            }
141        }
142        return getPaginableEntries(pp);
143    }
144
145    protected Paginable<T> getPaginableEntries(PageProvider<T> pageProvider) {
146        return new PaginablePageProvider<>(pageProvider);
147    }
148
149    protected Long extractLongParam(HttpServletRequest request, String paramName, Long defaultValue) {
150        String strParam = request.getParameter(paramName);
151        return strParam == null ? defaultValue : Long.parseLong(strParam);
152    }
153
154}