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.HashMap; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Map; 027 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.cocoon.ProcessingException; 031import org.apache.cocoon.xml.AttributesImpl; 032import org.apache.solr.client.solrj.SolrQuery; 033import org.apache.solr.client.solrj.response.QueryResponse; 034import org.xml.sax.SAXException; 035 036import org.ametys.cms.search.query.AndQuery; 037import org.ametys.cms.search.query.Query; 038import org.ametys.cms.search.query.TagQuery; 039import org.ametys.cms.tag.Tag; 040import org.ametys.cms.tag.TagProvider; 041import org.ametys.cms.tag.TagProviderExtensionPoint; 042import org.ametys.plugins.repository.metadata.CompositeMetadata; 043import org.ametys.runtime.i18n.I18nizableText; 044import org.ametys.web.search.query.PageContentQuery; 045import org.ametys.web.search.query.SiteQuery; 046import org.ametys.web.search.query.SitemapQuery; 047 048/** 049 * Generates a tag cloud based upon content tags 050 */ 051public class TagCloudOnTagsGenerator extends AbstractTagCloudGenerator 052{ 053 054 /** The {@link TagProviderExtensionPoint} */ 055 protected TagProviderExtensionPoint _tagExtPt; 056 057 @Override 058 public void service(ServiceManager serviceManager) throws ServiceException 059 { 060 super.service(serviceManager); 061 _tagExtPt = (TagProviderExtensionPoint) manager.lookup(TagProviderExtensionPoint.ROLE); 062 } 063 064 @Override 065 protected List<TagCloudItem> getTagCloudItems(String siteName, String lang, CompositeMetadata serviceParameters) throws IOException, ProcessingException 066 { 067 // Set of {@link TagCloud} sorted by occurrence 068 List<TagCloudItem> tagCloud = new ArrayList<>(); 069 070 // Content types 071 String[] cTypes = serviceParameters.getStringArray("content-types"); 072 073 // Pages 074 String[] pages = serviceParameters.getStringArray("search-by-pages"); 075 076 // Tags to search for 077 String[] tagArray = serviceParameters.getStringArray("search-by-tags"); 078 List<Tag> tags = _getTags(siteName, tagArray); 079 080 int pos = 0; 081 for (Tag tag : tags) 082 { 083 try 084 { 085 Query queryObject = getQuery(siteName, lang, tag.getName(), cTypes, pages); 086 087 SolrQuery query = build(queryObject); 088 089 if (getLogger().isInfoEnabled()) 090 { 091 getLogger().info("Solr query: " + URLDecoder.decode(query.toString(), "UTF-8")); 092 } 093 094 String collection = _solrClientProvider.getCollectionName(); 095 QueryResponse response = _solrClient.query(collection, query); 096 097 int count = (int) response.getResults().getNumFound(); 098 if (count > 0) 099 { 100 tagCloud.add(new TagTagCloudItem(count, tag, pos)); 101 pos++; 102 } 103 } 104 catch (Exception e) 105 { 106 getLogger().error("Query on tag " + tag.getName() + " failed. Unable to get number of occurrence", e); 107 throw new ProcessingException("Query on tag " + tag.getName() + " failed. Unable to get number of occurrence", e); 108 } 109 } 110 111 Collections.sort(tagCloud, OCCURRENCE_COMPARATOR); 112 113 return tagCloud; 114 } 115 116 @Override 117 protected void _saxAdditionalAttributes(TagCloudItem item, AttributesImpl attrs) throws SAXException 118 { 119 if (item instanceof TagTagCloudItem) 120 { 121 Tag tag = ((TagTagCloudItem) item).getTag(); 122 attrs.addCDATAAttribute("tag", tag.getName()); 123 } 124 } 125 126 /** 127 * Get the query 128 * @param siteName The site name. 129 * @param language The current language. 130 * @param tagName The tag name 131 * @param contentTypes The content types 132 * @param pages The pages 133 * @return the query 134 * @throws IllegalArgumentException If the search field is invalid 135 */ 136 protected Query getQuery(String siteName, String language, String tagName, String[] contentTypes, String[] pages) 137 { 138 List<Query> queries = new ArrayList<>(); 139 140 Query siteQuery = new SiteQuery(siteName); 141 Query langQuery = new SitemapQuery(language); 142 143 queries.add(siteQuery); 144 queries.add(langQuery); 145 146 _addContentTypeQuery(queries, contentTypes); 147 148 _addPagesQuery(queries, pages); 149 150 _addTagQuery(queries, tagName); 151 152 return new AndQuery(queries); 153 } 154 155 private void _addTagQuery(Collection<Query> queries, String tagName) 156 { 157 queries.add(new PageContentQuery(new TagQuery(tagName))); 158 } 159 160 private List<Tag> _getTags(String siteName, String[] tagArray) 161 { 162 Map<String, Object> contextParameters = new HashMap<>(); 163 contextParameters.put("siteName", siteName); 164 165 List<Tag> tags = new ArrayList<>(); 166 167 for (String tagName : tagArray) 168 { 169 boolean found = false; 170 Iterator<String> extensionsIds = _tagExtPt.getExtensionsIds().iterator(); 171 172 while (extensionsIds.hasNext() && !found) 173 { 174 String id = extensionsIds.next(); 175 176 TagProvider tagProvider = _tagExtPt.getExtension(id); 177 if (tagName.startsWith("provider_") && id.equals(tagName.substring("provider_".length()))) 178 { 179 found = true; 180 tags.addAll(tagProvider.getTags(contextParameters).values()); 181 } 182 else if (tagProvider.hasTag(tagName, contextParameters)) 183 { 184 found = true; 185 Tag tag = tagProvider.getTag(tagName, contextParameters); 186 tags.addAll(tag.getTags().values()); 187 } 188 } 189 } 190 191 return tags; 192 } 193 194 /** 195 * Class representing an item of tag cloud 196 */ 197 private class TagTagCloudItem implements TagCloudItem 198 { 199 private int _occurence; 200 private Tag _tag; 201 private int _position; 202 203 /** 204 * Constructor 205 * 206 * @param occurence the number of occurence 207 * @param tag the tag 208 * @param position the item original position. 209 */ 210 public TagTagCloudItem(int occurence, Tag tag, int position) 211 { 212 _occurence = occurence; 213 _tag = tag; 214 _position = position; 215 } 216 217 /** 218 * Returns the tag 219 * 220 * @return the tag 221 */ 222 public Tag getTag() 223 { 224 return _tag; 225 } 226 227 @Override 228 public I18nizableText getWord() 229 { 230 return _tag.getTitle(); 231 } 232 233 @Override 234 public int getOccurrenceCount() 235 { 236 return _occurence; 237 } 238 239 @Override 240 public int getPosition() 241 { 242 return _position; 243 } 244 } 245 246}