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