001/* 002 * Copyright 2016 Anyware Services 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 */ 016package org.ametys.cms.explorer; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.cocoon.ProcessingException; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.xml.XMLUtils; 029import org.apache.commons.lang.StringUtils; 030import org.apache.solr.client.solrj.util.ClientUtils; 031import org.xml.sax.SAXException; 032 033import org.ametys.cms.content.indexing.solr.SolrFieldNames; 034import org.ametys.cms.search.Sort; 035import org.ametys.cms.search.Sort.Order; 036import org.ametys.cms.search.filter.AccessSearchFilter; 037import org.ametys.cms.search.query.AndQuery; 038import org.ametys.cms.search.query.DocumentTypeQuery; 039import org.ametys.cms.search.query.DublinCoreQuery; 040import org.ametys.cms.search.query.FilenameQuery; 041import org.ametys.cms.search.query.FullTextQuery; 042import org.ametys.cms.search.query.OrQuery; 043import org.ametys.cms.search.query.Query; 044import org.ametys.cms.search.query.Query.Operator; 045import org.ametys.cms.search.query.QuerySyntaxException; 046import org.ametys.cms.search.query.ResourceLocationQuery; 047import org.ametys.cms.search.query.UsersQuery; 048import org.ametys.cms.search.solr.SearcherFactory; 049import org.ametys.core.user.UserIdentity; 050import org.ametys.core.util.JSONUtils; 051import org.ametys.plugins.core.user.UserHelper; 052import org.ametys.plugins.explorer.ExplorerNode; 053import org.ametys.plugins.explorer.resources.Resource; 054import org.ametys.plugins.explorer.resources.generators.SearchGenerator; 055import org.ametys.plugins.repository.AmetysObjectIterable; 056 057/** 058 * Search resources in a specific explorer node. 059 */ 060public class SearchResourcesGenerator extends SearchGenerator 061{ 062 /** The searcher factory. */ 063 protected SearcherFactory _searcherFactory; 064 065 /** The JSON utils */ 066 protected JSONUtils _jsonUtils; 067 068 /** The user helper */ 069 protected UserHelper _userHelper; 070 071 @Override 072 public void service(ServiceManager sManager) throws ServiceException 073 { 074 super.service(sManager); 075 _searcherFactory = (SearcherFactory) sManager.lookup(SearcherFactory.ROLE); 076 _jsonUtils = (JSONUtils) sManager.lookup(JSONUtils.ROLE); 077 _userHelper = (UserHelper) manager.lookup(UserHelper.ROLE); 078 } 079 080 @Override 081 public void generate() throws IOException, SAXException, ProcessingException 082 { 083 Request request = ObjectModelHelper.getRequest(objectModel); 084 085 String id = request.getParameter("id"); 086 String rootId = request.getParameter("rootId"); 087 ExplorerNode node = _resolver.resolveById(id); 088 089 Query query = getQuery(request, node, rootId); 090 091 contentHandler.startDocument(); 092 XMLUtils.startElement(contentHandler, "resources"); 093 094 try 095 { 096 Sort sort = new Sort(SolrFieldNames.TITLE_SORT, Order.ASC); 097 098 AmetysObjectIterable<Resource> resources = _searcherFactory.create() 099 .withQuery(query) 100 .withFilterQueries(new DocumentTypeQuery(SolrFieldNames.TYPE_RESOURCE)) 101 .withSort(sort) 102 .addContextElement(AccessSearchFilter.OBJECT_TYPE, "resource") 103 .search(); 104 105 for (Resource resource : resources) 106 { 107 saxResource(resource); 108 } 109 } 110 catch (Exception e) 111 { 112 getLogger().error("Error searching resources in the explorer node " + id, e); 113 throw new ProcessingException("Error searching resources in the explorer node " + id, e); 114 } 115 116 XMLUtils.endElement(contentHandler, "resources"); 117 contentHandler.endDocument(); 118 } 119 120 /** 121 * Build the query object corresponding to the user search. 122 * @param request The user request. 123 * @param explorerNode The explorer node to search into. 124 * @param rootId The root ID, can be null to search all resources. 125 * @return the query object. 126 */ 127 protected Query getQuery(Request request, ExplorerNode explorerNode, String rootId) 128 { 129 List<Query> queries = new ArrayList<>(); 130 131 if (explorerNode != null || StringUtils.isNotEmpty(rootId)) 132 { 133 String path = explorerNode == null ? "" : explorerNode.getExplorerPath(); 134 queries.add(new ResourceLocationQuery(rootId, path)); 135 } 136 137 // File name 138 String name = request.getParameter("name"); 139 if (StringUtils.isNotEmpty(name)) 140 { 141 queries.add(new FilenameQuery(name)); 142 } 143 144 // Full text 145 String fulltext = request.getParameter("fulltext"); 146 if (StringUtils.isNotEmpty(fulltext)) 147 { 148 queries.add(new FullTextQuery(fulltext, Operator.LIKE)); 149 } 150 151 String keywords = request.getParameter("keywords"); 152 if (StringUtils.isNotEmpty(keywords)) 153 { 154 Query subjectQuery = new DublinCoreQuery("subject", keywords); 155 Query descQuery = new DublinCoreQuery("description", keywords); 156 157 queries.add(new OrQuery(subjectQuery, descQuery)); 158 } 159 160 String authorAsStr = request.getParameter("author"); 161 Map<String, Object> json = _jsonUtils.convertJsonToMap(authorAsStr); 162 UserIdentity author = _userHelper.json2userIdentity(json); 163 if (null != author) 164 { 165 queries.add(new UsersQuery(SolrFieldNames.RESOURCE_CREATOR, author)); 166 } 167 168 return new AndQuery(queries); 169 } 170 171 172 173 /** 174 * Represents a {@link Query} testing the resource creator. 175 */ 176 class ResourceCreatorQuery implements Query 177 { 178 /** The operator. */ 179 private Operator _operator; 180 181 /** The value to test. */ 182 private String _value; 183 184 /** 185 * Build a string query. 186 * @param value the value. 187 */ 188 public ResourceCreatorQuery(String value) 189 { 190 this(Operator.EQ, value); 191 } 192 193 /** 194 * Build a string query. 195 * @param op the operator. 196 * @param value the value. 197 */ 198 public ResourceCreatorQuery(Operator op, String value) 199 { 200 _operator = op; 201 _value = value; 202 } 203 204 @Override 205 public String build() throws QuerySyntaxException 206 { 207 StringBuilder query = new StringBuilder(); 208 209 if (_operator == Operator.NE) 210 { 211 query.append('-'); 212 } 213 214 query.append(SolrFieldNames.RESOURCE_CREATOR).append(':') 215 .append(ClientUtils.escapeQueryChars(_value)); 216 217 return query.toString(); 218 } 219 } 220 221}