001/* 002 * Copyright 2012 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 */ 016 017package org.ametys.cms.transformation.xslt; 018 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.avalon.framework.context.Context; 025import org.apache.avalon.framework.context.ContextException; 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.cocoon.components.ContextHelper; 031import org.apache.cocoon.environment.Request; 032import org.apache.commons.lang.StringUtils; 033import org.w3c.dom.Element; 034import org.w3c.dom.Node; 035import org.w3c.dom.NodeList; 036 037import org.ametys.cms.contenttype.ContentType; 038import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 039import org.ametys.cms.repository.Content; 040import org.ametys.cms.tag.Tag; 041import org.ametys.cms.tag.TagProviderExtensionPoint; 042import org.ametys.cms.transformation.dom.TagElement; 043import org.ametys.core.util.dom.AmetysNodeList; 044import org.ametys.core.util.dom.EmptyElement; 045import org.ametys.core.util.dom.StringElement; 046import org.ametys.plugins.explorer.resources.Resource; 047import org.ametys.plugins.explorer.resources.ResourceCollection; 048import org.ametys.plugins.explorer.resources.dom.ResourceCollectionElement; 049import org.ametys.plugins.repository.AmetysObjectResolver; 050import org.ametys.plugins.repository.AmetysRepositoryException; 051import org.ametys.plugins.repository.UnknownAmetysObjectException; 052import org.ametys.plugins.repository.metadata.CompositeMetadata; 053import org.ametys.plugins.repository.metadata.UnknownMetadataException; 054 055/** 056 * Helper component to be used from XSL stylesheets. 057 */ 058public class AmetysXSLTHelper extends org.ametys.core.util.AmetysXSLTHelper implements LogEnabled 059{ 060 /** The Ametys object resolver */ 061 protected static AmetysObjectResolver _ametysObjectResolver; 062 /** The content types extension point */ 063 protected static ContentTypeExtensionPoint _cTypeExtensionPoint; 064 /** The tags provider */ 065 protected static TagProviderExtensionPoint _tagProviderExtPt; 066 /** The avalon context */ 067 protected static Context _context; 068 /** The logger */ 069 protected static Logger _logger; 070 071 @Override 072 public void contextualize(Context context) throws ContextException 073 { 074 super.contextualize(context); 075 _context = context; 076 } 077 078 @Override 079 public void enableLogging(Logger logger) 080 { 081 _logger = logger; 082 } 083 084 @Override 085 public void service(ServiceManager manager) throws ServiceException 086 { 087 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 088 _cTypeExtensionPoint = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 089 _tagProviderExtPt = (TagProviderExtensionPoint) manager.lookup(TagProviderExtensionPoint.ROLE); 090 } 091 092 /* ------------------------ */ 093 /* Content methods */ 094 /* ------------------------ */ 095 096 /** 097 * Get the content types of a content 098 * @param contentId The content id 099 * @return The content type or empty if the content does not exist 100 */ 101 public static NodeList contentTypes(String contentId) 102 { 103 ArrayList<StringElement> contentTypes = new ArrayList<>(); 104 105 try 106 { 107 Content content = _ametysObjectResolver.resolveById(contentId); 108 109 try 110 { 111 for (String id : content.getTypes()) 112 { 113 contentTypes.add(new StringElement("content-type", "id", id)); 114 } 115 } 116 catch (AmetysRepositoryException e) 117 { 118 _logger.error("Can not get type of content with id '" + contentId + "'", e); 119 } 120 } 121 catch (UnknownAmetysObjectException e) 122 { 123 _logger.error("Can not get type of content with id '" + contentId + "'", e); 124 } 125 126 return new AmetysNodeList(contentTypes); 127 } 128 129 /** 130 * Get the mixins of a content 131 * @param contentId The content id 132 * @return The content type or empty if the content does not exist 133 */ 134 public static NodeList contentMixinTypes(String contentId) 135 { 136 ArrayList<StringElement> contentTypes = new ArrayList<>(); 137 138 try 139 { 140 Content content = _ametysObjectResolver.resolveById(contentId); 141 142 try 143 { 144 for (String id : content.getMixinTypes()) 145 { 146 contentTypes.add(new StringElement("mixin", "id", id)); 147 } 148 } 149 catch (AmetysRepositoryException e) 150 { 151 _logger.error("Can not get type of content with id '" + contentId + "'", e); 152 } 153 } 154 catch (UnknownAmetysObjectException e) 155 { 156 _logger.error("Can not get type of content with id '" + contentId + "'", e); 157 } 158 159 return new AmetysNodeList(contentTypes); 160 } 161 162 163 /** 164 * Get the metadata of a content 165 * @param contentId The content id 166 * @param metadataName The metadata name (/ for composite) 167 * @return The name or empty if the metadata or the content does not exist 168 */ 169 public static String contentMetadata(String contentId, String metadataName) 170 { 171 try 172 { 173 Content content = _ametysObjectResolver.resolveById(contentId); 174 try 175 { 176 return _getMetadata(content.getMetadataHolder(), metadataName); 177 } 178 catch (UnknownMetadataException e) 179 { 180 _logger.error("Can not get metadata '" + metadataName + "' on content with id '" + contentId + "'", e); 181 return ""; 182 } 183 } 184 catch (UnknownAmetysObjectException e) 185 { 186 _logger.error("Can not get metadata '" + metadataName + "' on unknown content with id '" + contentId + "'", e); 187 return ""; 188 } 189 } 190 191 private static String _getMetadata(CompositeMetadata cm, String metadataName) 192 { 193 int i = metadataName.indexOf("/"); 194 if (i == -1) 195 { 196 return cm.getString(metadataName); 197 } 198 else 199 { 200 return _getMetadata(cm.getCompositeMetadata(metadataName.substring(0, i)), metadataName.substring(i + 1)); 201 } 202 } 203 204 /** 205 * Returns a DOM {@link Element} containing {@link Resource}s representing the attachments of the current content. 206 * @return an Element containing the attachments of the current content as {@link Resource}s. 207 */ 208 public static Node contentAttachments() 209 { 210 Request request = ContextHelper.getRequest(_context); 211 212 Content content = (Content) request.getAttribute(Content.class.getName()); 213 214 return contentAttachments(content); 215 } 216 217 /** 218 * Returns a DOM {@link Element} containing {@link Resource}s representing the attachments of a given content. 219 * @param contentId the content ID. 220 * @return an Element containing the attachments of the given content as {@link Resource}s. 221 */ 222 public static Node contentAttachments(String contentId) 223 { 224 Content content = _ametysObjectResolver.resolveById(contentId); 225 226 return contentAttachments(content); 227 } 228 229 /** 230 * Returns a DOM {@link Element} containing {@link Resource}s representing the attachments of a given content. 231 * @param content the content. 232 * @return an Element containing the attachments of the given content as {@link Resource}s. 233 */ 234 private static Node contentAttachments(Content content) 235 { 236 if (content == null) 237 { 238 return null; 239 } 240 241 ResourceCollection collection = content.getRootAttachments(); 242 243 return collection != null ? new ResourceCollectionElement(collection) : new EmptyElement("collection"); 244 } 245 246 //************************* 247 // Tag methods 248 //************************* 249 250 /** 251 * Returns all tags of the current content. 252 * @return a list of tags. 253 */ 254 public static NodeList contentTags() 255 { 256 Request request = ContextHelper.getRequest(_context); 257 258 Content content = (Content) request.getAttribute(Content.class.getName()); 259 260 if (content == null) 261 { 262 return null; 263 } 264 265 List<TagElement> list = new ArrayList<>(); 266 267 for (String tag : content.getTags()) 268 { 269 list.add(new TagElement(tag)); 270 } 271 272 return new AmetysNodeList(list); 273 } 274 275 /** 276 * Get the name of the parent of a tag. 277 * @param siteName the site name 278 * @param tagName the tag's name 279 * @return The id of parent or empty if not found 280 */ 281 public static String tagParent(String siteName, String tagName) 282 { 283 Map<String, Object> contextParameters = new HashMap<>(); 284 contextParameters.put("siteName", siteName); 285 286 Tag tag = _tagProviderExtPt.getTag(tagName, contextParameters); 287 if (tag == null) 288 { 289 return StringUtils.EMPTY; 290 } 291 292 String parentName = tag.getParentName(); 293 return parentName != null ? parentName : StringUtils.EMPTY; 294 } 295 296 /** 297 * Get the path of a tag. The path contains the tag's parents seprated by '/'. 298 * @param siteName The site name 299 * @param tagName The unique tag's name 300 * @return The tag's path or empty string if tag does not exist 301 */ 302 public static String tagPath (String siteName, String tagName) 303 { 304 Map<String, Object> contextParameters = new HashMap<>(); 305 contextParameters.put("siteName", siteName); 306 307 Tag tag = _tagProviderExtPt.getTag(tagName, contextParameters); 308 if (tag == null) 309 { 310 return StringUtils.EMPTY; 311 } 312 313 String path = tagName; 314 315 Tag parentTag = tag.getParent(); 316 while (parentTag != null) 317 { 318 path = parentTag.getName() + "/" + path; 319 parentTag = parentTag.getParent(); 320 } 321 322 return path; 323 } 324 325 /** 326 * Get the label of a tag 327 * @param siteName the current site 328 * @param tagName the name of the tag 329 * @param lang the lang (if i18n tag) 330 * @return the label of the tag or empty if it cannot be found 331 */ 332 public static String tagLabel(String siteName, String tagName, String lang) 333 { 334 Map<String, Object> contextParameters = new HashMap<>(); 335 contextParameters.put("siteName", siteName); 336 337 Tag tag = _tagProviderExtPt.getTag(tagName, contextParameters); 338 return tag == null ? "" : _i18nUtils.translate(tag.getTitle(), lang); 339 } 340 341 /** 342 * Get the description of a tag 343 * @param siteName the current site 344 * @param tagName the name of the tag 345 * @param lang the lang (if i18n tag) 346 * @return the label of the tag or empty if it cannot be found 347 */ 348 public static String tagDescription(String siteName, String tagName, String lang) 349 { 350 Map<String, Object> contextParameters = new HashMap<>(); 351 contextParameters.put("siteName", siteName); 352 353 Tag tag = _tagProviderExtPt.getTag(tagName, contextParameters); 354 return tag == null ? "" : _i18nUtils.translate(tag.getDescription(), lang); 355 } 356 357 /** 358 * Get the visibility of a tag 359 * @param siteName the current site 360 * @param tagName the name of the tag 361 * @return the lower-cased visibility of the tag ("public" or "private") 362 */ 363 public static String tagVisibility(String siteName, String tagName) 364 { 365 Map<String, Object> contextParameters = new HashMap<>(); 366 contextParameters.put("siteName", siteName); 367 368 Tag tag = _tagProviderExtPt.getTag(tagName, contextParameters); 369 return tag == null ? "" : tag.getVisibility().toString().toLowerCase(); 370 } 371 372 /* ----------------------------- */ 373 /* Content type methods */ 374 /* ----------------------------- */ 375 376 /** 377 * Returns all tags of a content type 378 * @param contentTypeId The id of the content type 379 * @return a list of tags. 380 */ 381 public static NodeList contentTypeTags(String contentTypeId) 382 { 383 ArrayList<TagElement> tags = new ArrayList<>(); 384 385 try 386 { 387 ContentType cType = _cTypeExtensionPoint.getExtension(contentTypeId); 388 if (cType != null) 389 { 390 for (String tag : cType.getTags()) 391 { 392 tags.add(new TagElement(tag)); 393 } 394 } 395 else 396 { 397 _logger.error("Can not get tags of unknown content type of id '" + contentTypeId + "'"); 398 } 399 400 } 401 catch (AmetysRepositoryException e) 402 { 403 _logger.error("Can not get tags of content type of id '" + contentTypeId + "'", e); 404 } 405 406 return new AmetysNodeList(tags); 407 } 408}