001/* 002 * Copyright 2010 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.plugins.tagcloud.generators; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.List; 023 024import org.apache.cocoon.ProcessingException; 025import org.apache.commons.lang3.StringUtils; 026import org.apache.solr.client.solrj.SolrQuery; 027import org.apache.solr.client.solrj.response.QueryResponse; 028 029import org.ametys.cms.search.query.AndQuery; 030import org.ametys.cms.search.query.FullTextQuery; 031import org.ametys.cms.search.query.OrQuery; 032import org.ametys.cms.search.query.Query; 033import org.ametys.cms.search.query.Query.Operator; 034import org.ametys.core.util.URIUtils; 035import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 036import org.ametys.runtime.i18n.I18nizableText; 037import org.ametys.web.search.query.PageContentQuery; 038import org.ametys.web.search.query.SiteQuery; 039import org.ametys.web.search.query.SitemapQuery; 040 041/** 042 * Generates a tag cloud based upon words 043 */ 044public class TagCloudOnWordsGenerator extends AbstractTagCloudGenerator 045{ 046 047 @Override 048 protected List<TagCloudItem> getTagCloudItems(String siteName, String lang, ModelAwareDataHolder serviceParameters) throws IOException, ProcessingException 049 { 050 // Content types 051 String[] cTypes = serviceParameters.getValue("content-types"); 052 053 // Pages 054 String[] pages = serviceParameters.getValue("search-by-pages"); 055 056 // Get key words to match. 057 // TODO If empty, use top ranking terms from the solr server. 058 String keywordsAsString = serviceParameters.getValue("keywords"); 059 String[] keywords = keywordsAsString.split("[,;\n]"); 060 061 // Set of {@link TagCloudItem} sorted by occurrence 062 List<TagCloudItem> tagCloud = new ArrayList<>(); 063 064 int pos = 0; 065 for (String keyword : keywords) 066 { 067 String trimKeyword = StringUtils.trimToNull(keyword); 068 if (trimKeyword != null) 069 { 070 try 071 { 072 Query queryObject = getQuery(siteName, lang, trimKeyword, cTypes, pages); 073 074 SolrQuery query = build(queryObject); 075 076 if (getLogger().isInfoEnabled()) 077 { 078 getLogger().info("Solr query: " + URIUtils.decode(query.toString())); 079 } 080 081 String collection = _solrClientProvider.getCollectionName(); 082 QueryResponse response = _solrClient.query(collection, query); 083 084 int count = (int) response.getResults().getNumFound(); 085 if (count > 0) 086 { 087 tagCloud.add(new WordTagCloudItem(count, trimKeyword, pos)); 088 pos++; 089 } 090 } 091 catch (Exception e) 092 { 093 getLogger().error("Query on keyword '" + trimKeyword + "' failed. Unable to get number of occurrence", e); 094 throw new ProcessingException("Query on keyword '" + trimKeyword + "' failed. Unable to get number of occurrence", e); 095 } 096 } 097 } 098 099 Collections.sort(tagCloud, OCCURRENCE_COMPARATOR); 100 101 return tagCloud; 102 } 103 104 /** 105 * Get the query 106 * @param siteName The site name. 107 * @param language The current language. 108 * @param keyword The key word 109 * @param contentTypes The content types 110 * @param pages The pages 111 * @return the query object. 112 * @throws IllegalArgumentException If the search field is invalid 113 */ 114 protected Query getQuery(String siteName, String language, String keyword, String[] contentTypes, String[] pages) throws IllegalArgumentException 115 { 116 List<Query> queries = new ArrayList<>(); 117 118 Query siteQuery = new SiteQuery(siteName); 119 Query langQuery = new SitemapQuery(language); 120 121 queries.add(siteQuery); 122 queries.add(langQuery); 123 124 _addContentTypeQuery(queries, contentTypes); 125 126 _addPagesQuery(queries, pages); 127 128 _addTextFieldQuery(queries, language, keyword); 129 130 return new AndQuery(queries); 131 } 132 133 // One or more of the words 134 private void _addTextFieldQuery(Collection<Query> queries, String language, String keyword) throws IllegalArgumentException 135 { 136 if (StringUtils.isNotBlank(keyword)) 137 { 138 Query query = new FullTextQuery(keyword, language, Operator.SEARCH); 139 Query contentQuery = new PageContentQuery(query); 140 141 queries.add(new OrQuery(query, contentQuery)); 142 } 143 } 144 145 private class WordTagCloudItem implements TagCloudItem 146 { 147 private int _occurrence; 148 private String _keyword; 149 private int _position; 150 151 /** 152 * Constructor 153 * 154 * @param occurrence the number of occurrence 155 * @param keyword the keyword 156 * @param position the original position 157 */ 158 public WordTagCloudItem(int occurrence, String keyword, int position) 159 { 160 _occurrence = occurrence; 161 _keyword = keyword; 162 _position = position; 163 } 164 165 @Override 166 public I18nizableText getWord() 167 { 168 return new I18nizableText(_keyword); 169 } 170 171 @Override 172 public int getOccurrenceCount() 173 { 174 return _occurrence; 175 } 176 177 @Override 178 public int getPosition() 179 { 180 return _position; 181 } 182 } 183 184} 185