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.newsletter.category; 017 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.Collection; 021import java.util.List; 022 023import org.apache.avalon.framework.configuration.Configurable; 024import org.apache.avalon.framework.configuration.Configuration; 025import org.apache.avalon.framework.configuration.ConfigurationException; 026import org.apache.avalon.framework.logger.LogEnabled; 027import org.apache.avalon.framework.logger.Logger; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031 032import org.ametys.cms.repository.Content; 033import org.ametys.cms.repository.ContentTypeExpression; 034import org.ametys.plugins.repository.AmetysObjectIterable; 035import org.ametys.plugins.repository.AmetysObjectResolver; 036import org.ametys.plugins.repository.UnknownAmetysObjectException; 037import org.ametys.plugins.repository.query.expression.AndExpression; 038import org.ametys.plugins.repository.query.expression.Expression; 039import org.ametys.plugins.repository.query.expression.ExpressionContext; 040import org.ametys.plugins.repository.query.expression.Expression.Operator; 041import org.ametys.plugins.repository.query.expression.StringExpression; 042import org.ametys.runtime.i18n.I18nizableText; 043import org.ametys.runtime.plugin.component.PluginAware; 044import org.ametys.web.repository.page.ModifiablePage; 045import org.ametys.web.repository.page.Page; 046import org.ametys.web.repository.page.PageQueryHelper; 047import org.ametys.web.repository.page.jcr.DefaultPage; 048import org.ametys.web.tags.TagExpression; 049 050/** 051 * This class provides newsletter categories from the site map 052 * 053 */ 054public class SitemapCategoryProvider implements LogEnabled, CategoryProvider, Serviceable, Configurable, PluginAware 055{ 056 /** The root id */ 057 public static final String TAG_NAME = "NEWSLETTER_CATEGORY"; 058 /** The metadata name for newsletter template */ 059 public static final String METADATA_TEMPLATE = "newsletterTemplate"; 060 /** The metadata name for automatic newsletter ids. */ 061 public static final String METADATA_AUTOMATIC_IDS = "newsletterAutomaticIds"; 062 /** The metadata name for newsletter template */ 063 public static final String CATEGORY_PREFIX_ID = "category_"; 064 065 /** The id */ 066 protected String _id; 067 /** The label */ 068 protected I18nizableText _label; 069 /** The description */ 070 protected I18nizableText _description; 071 /** The plugin name */ 072 protected String _pluginName; 073 /** The feature name */ 074 protected String _featureName; 075 076 /** The Logger */ 077 protected Logger _logger; 078 079 private AmetysObjectResolver _resolver; 080 081 @Override 082 public void service(ServiceManager serviceManager) throws ServiceException 083 { 084 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 085 } 086 087 @Override 088 public void configure(Configuration configuration) throws ConfigurationException 089 { 090 _label = configureLabel(configuration); 091 _description = configureDescription(configuration); 092 } 093 094 public void enableLogging(Logger logger) 095 { 096 _logger = logger; 097 } 098 099 @Override 100 public boolean isWritable() 101 { 102 return false; 103 } 104 105 @Override 106 public List<Category> getCategories(String siteName, String lang) 107 { 108 TagExpression expr = new TagExpression(Operator.EQ, TAG_NAME); 109 String xpathQuery = PageQueryHelper.getPageXPathQuery(siteName, lang, "", expr, null); 110 111 List<Category> categories = new ArrayList<>(); 112 113 AmetysObjectIterable<DefaultPage> pages = _resolver.query(xpathQuery); 114 for (DefaultPage page : pages) 115 { 116 Category category = new Category(CATEGORY_PREFIX_ID + page.getId(), page.getName(), _id, new I18nizableText(page.getTitle()), null, page.getValue(METADATA_TEMPLATE), siteName, lang); 117 categories.add(category); 118 } 119 120 return categories; 121 } 122 123 @Override 124 public Collection<Category> getAllCategories(String siteName, String lang) 125 { 126 return getCategories(siteName, lang); 127 } 128 129 @Override 130 public List<Category> getCategories(String categoryID) 131 { 132 return new ArrayList<>(); 133 } 134 135 @Override 136 public boolean hasCategory(String categoryID) 137 { 138 if (categoryID.startsWith(CATEGORY_PREFIX_ID)) 139 { 140 String pageID = categoryID.substring(CATEGORY_PREFIX_ID.length()); 141 try 142 { 143 DefaultPage page = _resolver.resolveById(pageID); 144 if (page != null) 145 { 146 return page.getTags().contains(TAG_NAME); 147 } 148 } 149 catch (UnknownAmetysObjectException e) 150 { 151 // Page does not exist anymore 152 return false; 153 } 154 } 155 return false; 156 } 157 158 @Override 159 public Category getCategory(String categoryID) 160 { 161 if (categoryID.startsWith("category_")) 162 { 163 String pageID = categoryID.substring(CATEGORY_PREFIX_ID.length()); 164 DefaultPage page = _resolver.resolveById(pageID); 165 if (page != null && page.getTags().contains(TAG_NAME)) 166 { 167 return new Category(CATEGORY_PREFIX_ID + page.getId(), page.getName(), "provider_" + _id, new I18nizableText(page.getTitle()), new I18nizableText(""), page.getValue(METADATA_TEMPLATE), page.getSiteName(), page.getSitemapName()); 168 } 169 } 170 return null; 171 } 172 173 @Override 174 public void setTemplate(Category category, String templateName) 175 { 176 String categoryID = category.getId(); 177 if (categoryID.startsWith("category_")) 178 { 179 String pageID = categoryID.substring(CATEGORY_PREFIX_ID.length()); 180 ModifiablePage page = _resolver.resolveById(pageID); 181 if (page != null) 182 { 183 page.setValue(METADATA_TEMPLATE, templateName); 184 page.saveChanges(); 185 } 186 } 187 } 188 189 @Override 190 public Collection<String> getAutomaticIds(String categoryId) 191 { 192 if (categoryId.startsWith("category_")) 193 { 194 String pageID = categoryId.substring(CATEGORY_PREFIX_ID.length()); 195 Page page = _resolver.resolveById(pageID); 196 if (page != null) 197 { 198 String[] autoIds = page.getValue(METADATA_AUTOMATIC_IDS, new String[0]); 199 200 return Arrays.asList(autoIds); 201 } 202 } 203 204 // Either the category ID is not a page category, or the page doesn't exist. 205 throw new IllegalArgumentException("The provided category ID is invalid."); 206 } 207 208 @Override 209 public void setAutomatic(String categoryId, Collection<String> automaticNewsletterIds) 210 { 211 if (categoryId.startsWith("category_")) 212 { 213 String pageID = categoryId.substring(CATEGORY_PREFIX_ID.length()); 214 Page page = _resolver.resolveById(pageID); 215 if (page != null && page instanceof ModifiablePage) 216 { 217 ModifiablePage modifiablePage = (ModifiablePage) page; 218 219 // Convert to array. 220 String[] autoIdsArray = automaticNewsletterIds.toArray(new String[automaticNewsletterIds.size()]); 221 222 modifiablePage.setValue(METADATA_AUTOMATIC_IDS, autoIdsArray); 223 modifiablePage.saveChanges(); 224 225 return; 226 } 227 } 228 229 // Either the category ID is not a page category, or the page doesn't exist. 230 throw new IllegalArgumentException("The provided category ID is invalid."); 231 } 232 233 @Override 234 public AmetysObjectIterable<Content> getNewsletters(String categoryID, String siteName, String lang) 235 { 236 Expression cTypeExpr = new ContentTypeExpression(Operator.EQ, "org.ametys.plugins.newsletter.Content.newsletter"); 237 Expression siteExpr = new StringExpression("site", Operator.EQ, siteName); 238 Expression catExpr = new StringExpression("category", Operator.EQ, categoryID, ExpressionContext.newInstance().withInternal(true)); 239 Expression expr = new AndExpression(cTypeExpr, siteExpr, catExpr); 240 241 String xpathQuery = org.ametys.plugins.repository.query.QueryHelper.getXPathQuery(null, "ametys:content", expr); 242 return _resolver.query(xpathQuery); 243 } 244 245 @Override 246 public boolean hasChildren(String categoryID) 247 { 248 return false; 249 } 250 251 @Override 252 public boolean hasNewsletters(String categoryID, String siteName, String lang) 253 { 254 Expression expr = new ContentTypeExpression(Operator.EQ, "org.ametys.plugins.newsletter.Content.newsletter"); 255 Expression siteExpr = new StringExpression("site", Operator.EQ, siteName); 256 expr = new AndExpression(expr, siteExpr); 257 Expression catExpr = new StringExpression("category", Operator.EQ, categoryID, ExpressionContext.newInstance().withInternal(true)); 258 expr = new AndExpression(expr, catExpr); 259 260 String xpathQuery = org.ametys.plugins.repository.query.QueryHelper.getXPathQuery(null, "ametys:content", expr); 261 262 return _resolver.query(xpathQuery).iterator().hasNext(); 263 } 264 265 /** 266 * Configure label from the passed configuration 267 * @param configuration The configuration 268 * @return The label 269 * @throws ConfigurationException If an error occurred 270 */ 271 protected I18nizableText configureLabel (Configuration configuration) throws ConfigurationException 272 { 273 Configuration labelConfiguration = configuration.getChild("label"); 274 275 if (labelConfiguration.getAttributeAsBoolean("i18n", false)) 276 { 277 return new I18nizableText("plugin." + _pluginName, labelConfiguration.getValue("")); 278 } 279 else 280 { 281 return new I18nizableText(labelConfiguration.getValue("")); 282 } 283 } 284 285 /** 286 * Configure description from the passed configuration 287 * @param configuration The configuration 288 * @return The description 289 * @throws ConfigurationException If an error occurred 290 */ 291 protected I18nizableText configureDescription (Configuration configuration) throws ConfigurationException 292 { 293 Configuration descConfiguration = configuration.getChild("description"); 294 295 if (descConfiguration.getAttributeAsBoolean("i18n", false)) 296 { 297 return new I18nizableText("plugin." + _pluginName, descConfiguration.getValue("")); 298 } 299 else 300 { 301 return new I18nizableText(descConfiguration.getValue("")); 302 } 303 } 304 305 public void setPluginInfo(String pluginName, String featureName, String id) 306 { 307 _pluginName = pluginName; 308 _featureName = featureName; 309 _id = id; 310 } 311 312 /** 313 * Get the plugin name 314 * @return the plugin name 315 */ 316 public String getPluginName() 317 { 318 return _pluginName; 319 } 320 321 @Override 322 public I18nizableText getDescription() 323 { 324 return _description; 325 } 326 327 @Override 328 public String getId() 329 { 330 return _id; 331 } 332 333 @Override 334 public I18nizableText getLabel() 335 { 336 return _label; 337 } 338 339 @Override 340 public String getRootId(String siteName, String lang) 341 { 342 return _id; 343 } 344}