001/* 002 * Copyright 2017 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.web.repository.page.actions; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.stream.Collectors; 023 024import org.apache.avalon.framework.parameters.Parameters; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.cocoon.acting.ServiceableAction; 028import org.apache.cocoon.environment.ObjectModelHelper; 029import org.apache.cocoon.environment.Redirector; 030import org.apache.cocoon.environment.Request; 031import org.apache.cocoon.environment.SourceResolver; 032import org.apache.commons.lang3.StringUtils; 033 034import org.ametys.cms.search.QueryBuilder; 035import org.ametys.cms.search.query.AndQuery; 036import org.ametys.cms.search.query.DocumentTypeQuery; 037import org.ametys.cms.search.query.Query; 038import org.ametys.cms.search.query.Query.Operator; 039import org.ametys.cms.search.query.StringQuery; 040import org.ametys.cms.search.solr.SearcherFactory; 041import org.ametys.core.cocoon.JSonReader; 042import org.ametys.plugins.repository.AmetysObjectIterable; 043import org.ametys.plugins.repository.AmetysObjectResolver; 044import org.ametys.plugins.repository.UnknownAmetysObjectException; 045import org.ametys.web.indexing.solr.SolrWebFieldNames; 046import org.ametys.web.repository.page.Page; 047import org.ametys.web.repository.site.SiteManager; 048import org.ametys.web.search.query.SiteQuery; 049import org.ametys.web.search.query.SitemapQuery; 050 051/** 052 * This action is used by the edition.select-page widget for searching pages from a query string 053 * 054 */ 055public class SearchPagesAction extends ServiceableAction 056{ 057 /** The Ametys object resolver */ 058 protected AmetysObjectResolver _resolver; 059 /** The searcher factory */ 060 protected SearcherFactory _searcherFactory; 061 /** The query builder */ 062 protected QueryBuilder _queryBuilder; 063 /** The site manager */ 064 protected SiteManager _siteManager; 065 066 @Override 067 public void service(ServiceManager smanager) throws ServiceException 068 { 069 super.service(smanager); 070 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 071 _searcherFactory = (SearcherFactory) smanager.lookup(SearcherFactory.ROLE); 072 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 073 } 074 075 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 076 { 077 Map<String, Object> result = new HashMap<>(); 078 List<Map<String, Object>> matchingPages; 079 List<String> unknownPages = new ArrayList<>(); 080 081 @SuppressWarnings("unchecked") 082 Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 083 084 if (jsParameters.get("ids") != null) 085 { 086 matchingPages = new ArrayList<>(); 087 088 @SuppressWarnings("unchecked") 089 List<String> pageIds = (List<String>) jsParameters.get("ids"); 090 for (String pageId : pageIds) 091 { 092 try 093 { 094 Page page = _resolver.resolveById(pageId); 095 matchingPages.add(page2json(page)); 096 } 097 catch (UnknownAmetysObjectException e) 098 { 099 getLogger().error("Unknown page of id '" + pageId + "'", e); 100 unknownPages.add(pageId); 101 } 102 } 103 } 104 else 105 { 106 String siteName = (String) jsParameters.get("siteName"); 107 String lang = (String) jsParameters.get("lang"); 108 String query = (String) jsParameters.get("query"); 109 int maxResult = Integer.MAX_VALUE; 110 if (jsParameters.containsKey("limit")) 111 { 112 maxResult = (Integer) jsParameters.get("limit"); 113 } 114 115 116 /// ------------------------------------------------------------- 117 List<Query> queries = new ArrayList<>(); 118 if (StringUtils.isNotEmpty(siteName)) 119 { 120 queries.add(new SiteQuery(siteName)); 121 } 122 if (StringUtils.isNotEmpty(lang)) 123 { 124 queries.add(new SitemapQuery(lang)); 125 } 126 if (StringUtils.isNotEmpty(query)) 127 { 128 queries.add(new StringQuery(SolrWebFieldNames.PAGE_TITLE, Operator.SEARCH, query, lang)); 129 } 130 131 Query finalQuery = new AndQuery(queries); 132 133 AmetysObjectIterable<Page> pages = _searcherFactory.create() 134 .withQuery(finalQuery) 135 .addFilterQuery(new DocumentTypeQuery(SolrWebFieldNames.TYPE_PAGE)) 136 .withLimits(0, maxResult).search(); 137 138 matchingPages = pages.stream().map(this::page2json).collect(Collectors.toList()); 139 } 140 141 result.put("pages", matchingPages); 142 143 if (unknownPages.size() > 0) 144 { 145 result.put("unknown-pages", unknownPages); 146 } 147 148 Request request = ObjectModelHelper.getRequest(objectModel); 149 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 150 151 return EMPTY_MAP; 152 } 153 154 /** 155 * Convert page to JSON object 156 * @param page The page 157 * @return The page as JSON object 158 */ 159 protected Map<String, Object> page2json(Page page) 160 { 161 Map<String, Object> object = new HashMap<>(); 162 object.put("id", page.getId()); 163 object.put("title", page.getTitle()); 164 object.put("lang", page.getSitemapName()); 165 object.put("siteName", page.getSiteName()); 166 return object; 167 } 168}