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