001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
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 *     Thomas Roger
016 */
017
018package org.nuxeo.ecm.platform.usermanager.providers;
019
020import java.io.Serializable;
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.commons.lang.StringUtils;
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.directory.SizeLimitExceededException;
031import org.nuxeo.ecm.platform.query.api.AbstractPageProvider;
032import org.nuxeo.ecm.platform.usermanager.UserManager;
033import org.nuxeo.runtime.api.Framework;
034
035/**
036 * Abstract Page provider listing groups.
037 * <p>
038 * This page provider requires one parameter: the first one to be filled with the search string.
039 * <p>
040 * This page provider requires the property {@link #GROUPS_LISTING_MODE_PROPERTY} to be filled with a the listing mode
041 * to use.
042 *
043 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
044 * @since 5.8
045 */
046public abstract class AbstractGroupsPageProvider<T> extends AbstractPageProvider<T> {
047
048    protected static final String GROUPS_LISTING_MODE_PROPERTY = "groupsListingMode";
049
050    protected static final String ALL_MODE = "all";
051
052    protected static final String SEARCH_ONLY_MODE = "search_only";
053
054    protected static final String SEARCH_OVERFLOW_ERROR_MESSAGE = "label.security.searchOverFlow";
055
056    private static final Log log = LogFactory.getLog(AbstractGroupsPageProvider.class);
057
058    private static final long serialVersionUID = 1L;
059
060    protected List<DocumentModel> pageGroups;
061
062    public List<DocumentModel> computeCurrentPage() {
063        if (pageGroups == null) {
064            error = null;
065            errorMessage = null;
066            pageGroups = new ArrayList<DocumentModel>();
067
068            List<DocumentModel> groups = new ArrayList<DocumentModel>();
069            try {
070                String groupListingMode = getGroupListingMode();
071                if (ALL_MODE.equals(groupListingMode)) {
072                    groups = searchAllGroups();
073                } else if (SEARCH_ONLY_MODE.equals(groupListingMode)) {
074                    groups = searchGroups();
075                }
076            } catch (SizeLimitExceededException slee) {
077                error = slee;
078                errorMessage = SEARCH_OVERFLOW_ERROR_MESSAGE;
079                log.warn(slee.getMessage(), slee);
080            }
081
082            if (!hasError()) {
083                long resultsCount = groups.size();
084                setResultsCount(resultsCount);
085                // post-filter the results "by hand" to handle pagination
086                long pageSize = getMinMaxPageSize();
087                if (pageSize == 0) {
088                    pageGroups.addAll(groups);
089                } else {
090                    // handle offset
091                    long offset = getCurrentPageOffset();
092                    if (offset <= resultsCount) {
093                        for (int i = Long.valueOf(offset).intValue(); i < resultsCount && i < offset + pageSize; i++) {
094                            pageGroups.add(groups.get(i));
095                        }
096                    }
097                }
098            }
099        }
100        return pageGroups;
101    }
102
103    protected List<DocumentModel> searchAllGroups() {
104        return Framework.getService(UserManager.class).searchGroups(Collections.<String, Serializable> emptyMap(), null);
105    }
106
107    protected List<DocumentModel> searchGroups() {
108        UserManager userManager = Framework.getService(UserManager.class);
109        List<DocumentModel> groups = new ArrayList<DocumentModel>();
110        String searchString = getFirstParameter();
111        if ("*".equals(searchString)) {
112            groups = searchAllGroups();
113        } else if (!StringUtils.isEmpty(searchString)) {
114            groups = userManager.searchGroups(searchString);
115        }
116        return groups;
117    }
118
119    protected String getGroupListingMode() {
120        Map<String, Serializable> props = getProperties();
121        if (props.containsKey(GROUPS_LISTING_MODE_PROPERTY)) {
122            return (String) props.get(GROUPS_LISTING_MODE_PROPERTY);
123        }
124        return SEARCH_ONLY_MODE;
125    }
126
127    protected String getFirstParameter() {
128        Object[] parameters = getParameters();
129        if (parameters.length > 0) {
130            String param = (String) parameters[0];
131            if (param != null) {
132                return param.trim();
133            }
134        }
135        return "";
136    }
137
138    /**
139     * This page provider does not support sort for now => override what may be contributed in the definition
140     */
141    @Override
142    public boolean isSortable() {
143        return false;
144    }
145
146    @Override
147    protected void pageChanged() {
148        pageGroups = null;
149        super.pageChanged();
150    }
151
152    @Override
153    public void refresh() {
154        pageGroups = null;
155        super.refresh();
156    }
157
158}