001/*
002 * (C) Copyright 2014 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 *     Anahide Tchertchian
016 *     Benoit Delbosc
017 */
018package org.nuxeo.ecm.platform.query.core;
019
020import java.util.ArrayList;
021import java.util.Arrays;
022import java.util.Collections;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.nuxeo.common.xmap.annotation.XNode;
028import org.nuxeo.common.xmap.annotation.XNodeList;
029import org.nuxeo.common.xmap.annotation.XNodeMap;
030import org.nuxeo.ecm.core.api.SortInfo;
031import org.nuxeo.ecm.platform.query.api.AggregateDefinition;
032import org.nuxeo.ecm.platform.query.api.WhereClauseDefinition;
033
034/**
035 * Base class for page provider descriptors.
036 *
037 * @since 6.0
038 */
039public abstract class BasePageProviderDescriptor {
040
041    @XNode("@name")
042    protected String name;
043
044    @XNode("@enabled")
045    protected boolean enabled = true;
046
047    @XNodeMap(value = "property", key = "@name", type = HashMap.class, componentType = String.class)
048    protected Map<String, String> properties = new HashMap<String, String>();
049
050    @XNodeList(value = "parameter", type = String[].class, componentType = String.class)
051    protected String[] queryParameters;
052
053    @XNode("pageSize")
054    protected long pageSize = 0;
055
056    @XNode("pageSizeBinding")
057    protected String pageSizeBinding;
058
059    @XNode("maxPageSize")
060    protected Long maxPageSize;
061
062    /**
063     * @since 7.3
064     */
065    @XNodeList(value = "pageSizeOptions/option", type = ArrayList.class, componentType = Long.class)
066    protected List<Long> pageSizeOptions;
067
068    @XNode("sortable")
069    protected boolean sortable = true;
070
071    @XNodeList(value = "sort", type = ArrayList.class, componentType = SortInfoDescriptor.class)
072    protected List<SortInfoDescriptor> sortInfos;
073
074    @XNode("sortInfosBinding")
075    protected String sortInfosBinding;
076
077    protected String pattern;
078
079    @XNode("pattern@quoteParameters")
080    protected boolean quotePatternParameters = true;
081
082    @XNode("pattern@escapeParameters")
083    protected boolean escapePatternParameters = true;
084
085    @XNode("whereClause")
086    protected WhereClauseDescriptor whereClause;
087
088    /**
089     * @since 6.0
090     */
091    @XNode("searchDocumentType")
092    protected String searchDocumentType;
093
094    @XNode("pattern")
095    public void setPattern(String pattern) {
096        // remove new lines and following spaces
097        if (pattern != null) {
098            this.pattern = pattern.replaceAll("\r?\n\\s*", " ");
099        }
100    }
101
102    /**
103     * @since 6.0
104     */
105    @XNodeList(value = "aggregates/aggregate", type = ArrayList.class, componentType = AggregateDescriptor.class)
106    protected List<AggregateDescriptor> aggregates;
107
108    /**
109     * @since 7.4
110     */
111    @XNode("trackUsage")
112    protected boolean trackUsage = false;
113
114    /**
115     * @since 7.4
116     */
117    public boolean isUsageTrackingEnabled() {
118        return trackUsage;
119    }
120
121    public boolean getQuotePatternParameters() {
122        return quotePatternParameters;
123    }
124
125    public boolean getEscapePatternParameters() {
126        return escapePatternParameters;
127    }
128
129    public Map<String, String> getProperties() {
130        return properties;
131    }
132
133    public String[] getQueryParameters() {
134        return queryParameters;
135    }
136
137    public String getPattern() {
138        return pattern;
139    }
140
141    public WhereClauseDefinition getWhereClause() {
142        return whereClause;
143    }
144
145    public boolean isSortable() {
146        return sortable;
147    }
148
149    public List<SortInfo> getSortInfos() {
150        List<SortInfo> res = new ArrayList<SortInfo>();
151        if (sortInfos != null) {
152            for (SortInfoDescriptor sortInfo : sortInfos) {
153                res.add(sortInfo.getSortInfo());
154            }
155        }
156        return res;
157    }
158
159    public long getPageSize() {
160        return pageSize;
161    }
162
163    public List<Long> getPageSizeOptions() {
164        List<Long> res = new ArrayList<Long>();
165        if (pageSizeOptions == null || pageSizeOptions.isEmpty()) {
166            res.addAll(Arrays.asList(5L, 10L, 20L, 30L, 40L, 50L));
167        } else {
168            res.addAll(pageSizeOptions);
169        }
170        long defaultPageSize = getPageSize();
171        if (!res.contains(defaultPageSize)) {
172            res.add(defaultPageSize);
173        }
174        Collections.sort(res);
175        return res;
176    }
177
178    public boolean isEnabled() {
179        return enabled;
180    }
181
182    public void setEnabled(boolean enabled) {
183        this.enabled = enabled;
184    }
185
186    public String getPageSizeBinding() {
187        return pageSizeBinding;
188    }
189
190    public String getSortInfosBinding() {
191        return sortInfosBinding;
192    }
193
194    public String getName() {
195        return name;
196    }
197
198    public void setName(String name) {
199        this.name = name;
200    }
201
202    public Long getMaxPageSize() {
203        return maxPageSize;
204    }
205
206    /**
207     * @since 6.0
208     */
209    @SuppressWarnings("unchecked")
210    public List<AggregateDefinition> getAggregates() {
211        return (List<AggregateDefinition>) (List<?>) aggregates;
212    }
213
214    /**
215     * Returns the search document type used for wher clause, aggregates and named parameters.
216     *
217     * @since 6.0
218     */
219    public String getSearchDocumentType() {
220        if (searchDocumentType == null) {
221            // BBB
222            WhereClauseDefinition wc = getWhereClause();
223            if (wc != null) {
224                return wc.getDocType();
225            }
226        }
227        return searchDocumentType;
228    }
229
230    protected BasePageProviderDescriptor cloneDescriptor() {
231        BasePageProviderDescriptor clone = newInstance();
232        clone.name = getName();
233        clone.enabled = isEnabled();
234        Map<String, String> props = getProperties();
235        if (props != null) {
236            clone.properties = new HashMap<String, String>();
237            clone.properties.putAll(props);
238        }
239        String[] params = getQueryParameters();
240        if (params != null) {
241            clone.queryParameters = params.clone();
242        }
243        clone.pageSize = getPageSize();
244        clone.pageSizeBinding = getPageSizeBinding();
245        clone.maxPageSize = getMaxPageSize();
246        clone.pageSizeOptions = getPageSizeOptions();
247        clone.sortable = isSortable();
248        if (sortInfos != null) {
249            clone.sortInfos = new ArrayList<SortInfoDescriptor>();
250            for (SortInfoDescriptor item : sortInfos) {
251                clone.sortInfos.add(item.clone());
252            }
253        }
254        clone.sortInfosBinding = getSortInfosBinding();
255        clone.pattern = getPattern();
256        clone.quotePatternParameters = getQuotePatternParameters();
257        clone.escapePatternParameters = getEscapePatternParameters();
258        if (whereClause != null) {
259            clone.whereClause = whereClause.clone();
260        }
261        if (aggregates != null) {
262            clone.aggregates = new ArrayList<AggregateDescriptor>();
263            for (AggregateDescriptor agg : aggregates) {
264                clone.aggregates.add(agg.clone());
265            }
266        }
267        clone.searchDocumentType = searchDocumentType;
268        clone.trackUsage=trackUsage;
269        return clone;
270    }
271
272    protected abstract BasePageProviderDescriptor newInstance();
273
274
275}