001package org.nuxeo.ecm.automation.core.operations.services;
002
003import java.io.IOException;
004import java.io.Serializable;
005import java.util.ArrayList;
006import java.util.HashMap;
007import java.util.List;
008import java.util.Map;
009
010import org.apache.commons.lang.StringUtils;
011import org.nuxeo.ecm.automation.OperationContext;
012import org.nuxeo.ecm.automation.core.Constants;
013import org.nuxeo.ecm.automation.core.annotations.Context;
014import org.nuxeo.ecm.automation.core.annotations.Operation;
015import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
016import org.nuxeo.ecm.automation.core.annotations.Param;
017import org.nuxeo.ecm.automation.core.util.DocumentHelper;
018import org.nuxeo.ecm.automation.core.util.Paginable;
019import org.nuxeo.ecm.automation.core.util.Properties;
020import org.nuxeo.ecm.automation.core.util.StringList;
021import org.nuxeo.ecm.core.api.CoreSession;
022import org.nuxeo.ecm.core.api.DocumentModel;
023import org.nuxeo.ecm.core.api.SortInfo;
024import org.nuxeo.ecm.core.query.sql.NXQL;
025import org.nuxeo.ecm.platform.audit.api.AuditPageProvider;
026import org.nuxeo.ecm.platform.audit.api.LogEntry;
027import org.nuxeo.ecm.platform.audit.api.LogEntryList;
028import org.nuxeo.ecm.platform.query.api.PageProvider;
029import org.nuxeo.ecm.platform.query.api.PageProviderService;
030import org.nuxeo.ecm.platform.query.core.GenericPageProviderDescriptor;
031import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
032
033/**
034 * Operation to execute a query or a named provider against Audit with support for Pagination
035 *
036 * @author Tiry (tdelprat@nuxeo.com)
037 * @since 5.8
038 */
039@Operation(id = AuditPageProviderOperation.ID, category = Constants.CAT_FETCH, label = "Audit Query With Page Provider", description = "Perform "
040        + "a query or a named provider query against Audit logs. Result is "
041        + "paginated. The query result will become the input for the next "
042        + "operation. If no query or provider name is given, a query based on default Audit page provider will be executed.", addToStudio = false, aliases = { "Audit.PageProvider" })
043public class AuditPageProviderOperation {
044
045    public static final String ID = "Audit.QueryWithPageProvider";
046
047    public static final String CURRENT_USERID_PATTERN = "$currentUser";
048
049    public static final String CURRENT_REPO_PATTERN = "$currentRepository";
050
051    private static final String SORT_PARAMETER_SEPARATOR = " ";
052
053    public static final String DESC = "DESC";
054
055    public static final String ASC = "ASC";
056
057    @Context
058    protected OperationContext context;
059
060    @Context
061    protected CoreSession session;
062
063    @Context
064    protected PageProviderService ppService;
065
066    @Param(name = "providerName", required = false)
067    protected String providerName;
068
069    @Param(name = "query", required = false)
070    protected String query;
071
072    @Param(name = "language", required = false, widget = Constants.W_OPTION, values = { NXQL.NXQL })
073    protected String lang = NXQL.NXQL;
074
075    @Param(name = "page", required = false)
076    @Deprecated
077    protected Integer page;
078
079    @Param(name = "currentPageIndex", required = false)
080    protected Integer currentPageIndex;
081
082    @Param(name = "pageSize", required = false)
083    protected Integer pageSize;
084
085    /**
086     * @deprecated since 6.0 use instead {@link #sortBy and @link #sortOrder}.
087     */
088    @Deprecated
089    @Param(name = "sortInfo", required = false)
090    protected StringList sortInfoAsStringList;
091
092    @Param(name = "queryParams", required = false)
093    protected StringList strParameters;
094
095    @Param(name = "namedQueryParams", required = false)
096    protected Properties namedQueryParams;
097
098    /**
099     * @deprecated since 6.0, not used in operation.
100     */
101    @Deprecated
102    @Param(name = "maxResults", required = false)
103    protected Integer maxResults = 100;
104
105    /**
106     * @since 6.0
107     */
108    @Param(name = "sortBy", required = false, description = "Sort by " + "properties (separated by comma)")
109    protected String sortBy;
110
111    /**
112     * @since 6.0
113     */
114    @Param(name = "sortOrder", required = false, description = "Sort order, " + "ASC or DESC", widget = Constants.W_OPTION, values = {
115            ASC, DESC })
116    protected String sortOrder;
117
118    @SuppressWarnings("unchecked")
119    @OperationMethod
120    public Paginable<LogEntry> run() throws IOException {
121
122        List<SortInfo> sortInfos = null;
123        if (sortInfoAsStringList != null) {
124            sortInfos = new ArrayList<SortInfo>();
125            for (String sortInfoDesc : sortInfoAsStringList) {
126                SortInfo sortInfo;
127                if (sortInfoDesc.contains(SORT_PARAMETER_SEPARATOR)) {
128                    String[] parts = sortInfoDesc.split(SORT_PARAMETER_SEPARATOR);
129                    sortInfo = new SortInfo(parts[0], Boolean.parseBoolean(parts[1]));
130                } else {
131                    sortInfo = new SortInfo(sortInfoDesc, true);
132                }
133                sortInfos.add(sortInfo);
134            }
135        } else {
136            // Sort Info Management
137            if (!StringUtils.isBlank(sortBy)) {
138                sortInfos = new ArrayList<>();
139                String[] sorts = sortBy.split(",");
140                String[] orders = null;
141                if (!StringUtils.isBlank(sortOrder)) {
142                    orders = sortOrder.split(",");
143                }
144                for (int i = 0; i < sorts.length; i++) {
145                    String sort = sorts[i];
146                    boolean sortAscending = (orders != null && orders.length > i && "asc".equals(orders[i].toLowerCase()));
147                    sortInfos.add(new SortInfo(sort, sortAscending));
148                }
149            }
150        }
151
152        Object[] parameters = null;
153
154        if (strParameters != null && !strParameters.isEmpty()) {
155            parameters = strParameters.toArray(new String[strParameters.size()]);
156            // expand specific parameters
157            for (int idx = 0; idx < parameters.length; idx++) {
158                String value = (String) parameters[idx];
159                if (value.equals(CURRENT_USERID_PATTERN)) {
160                    parameters[idx] = session.getPrincipal().getName();
161                } else if (value.equals(CURRENT_REPO_PATTERN)) {
162                    parameters[idx] = session.getRepositoryName();
163                }
164            }
165        }
166        if (parameters == null) {
167            parameters = new Object[0];
168        }
169
170        Map<String, Serializable> props = new HashMap<String, Serializable>();
171        props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) session);
172
173        if (query == null && (providerName == null || providerName.length() == 0)) {
174            // provide a defaut provider
175            providerName = "AUDIT_BROWSER";
176        }
177
178        Long targetPage = null;
179        if (page != null) {
180            targetPage = page.longValue();
181        }
182        if (currentPageIndex != null) {
183            targetPage = currentPageIndex.longValue();
184        }
185        Long targetPageSize = null;
186        if (pageSize != null) {
187            targetPageSize = pageSize.longValue();
188        }
189
190        if (query != null) {
191
192            AuditPageProvider app = new AuditPageProvider();
193            app.setProperties(props);
194            GenericPageProviderDescriptor desc = new GenericPageProviderDescriptor();
195            desc.setPattern(query);
196            app.setParameters(parameters);
197            app.setDefinition(desc);
198            app.setSortInfos(sortInfos);
199            app.setPageSize(targetPageSize);
200            app.setCurrentPage(targetPage);
201            return new LogEntryList(app);
202        } else {
203
204            DocumentModel searchDoc = null;
205            if (namedQueryParams != null && namedQueryParams.size() > 0) {
206                String docType = ppService.getPageProviderDefinition(providerName).getWhereClause().getDocType();
207                searchDoc = session.createDocumentModel(docType);
208                DocumentHelper.setProperties(session, searchDoc, namedQueryParams);
209            }
210
211            PageProvider<LogEntry> pp = (PageProvider<LogEntry>) ppService.getPageProvider(providerName, searchDoc,
212                    sortInfos, targetPageSize, targetPage, props, parameters);
213            // return new PaginablePageProvider<LogEntry>(pp);
214            return new LogEntryList(pp);
215        }
216
217    }
218}