001/* 002 * Copyright 2015 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.blog.posts; 017 018import java.io.IOException; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Set; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.cocoon.ProcessingException; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.generation.ServiceableGenerator; 029import org.apache.cocoon.xml.AttributesImpl; 030import org.apache.cocoon.xml.XMLUtils; 031import org.apache.commons.lang.StringUtils; 032import org.xml.sax.SAXException; 033 034import org.ametys.cms.tag.CMSTag; 035import org.ametys.cms.tag.CMSTag.TagVisibility; 036import org.ametys.cms.tag.Tag; 037import org.ametys.cms.tag.TagHelper; 038import org.ametys.cms.tag.TagProviderExtensionPoint; 039import org.ametys.plugins.blog.BlogCacheManager; 040import org.ametys.plugins.blog.BlogCacheManager.Post; 041import org.ametys.plugins.blog.BlogPageHandler; 042import org.ametys.plugins.blog.repository.VirtualMonthPage; 043import org.ametys.plugins.blog.repository.VirtualPostPage; 044import org.ametys.plugins.blog.repository.VirtualTagPage; 045import org.ametys.plugins.blog.repository.VirtualTagsPage; 046import org.ametys.plugins.blog.repository.VirtualYearPage; 047import org.ametys.plugins.repository.UnknownAmetysObjectException; 048import org.ametys.web.repository.page.Page; 049import org.ametys.web.repository.page.PagesContainer; 050 051/** 052 * Blog pages generator. 053 */ 054public class BlogPagesGenerator extends ServiceableGenerator 055{ 056 /** The blog cache manager. */ 057 private BlogPageHandler _blogRootPageHandler; 058 059 /** The blog cache manager */ 060 private BlogCacheManager _blogCacheManager; 061 062 /** The extension point for tag providers. */ 063 private TagProviderExtensionPoint _tagProviderExtensionPoint; 064 065 @Override 066 public void service(ServiceManager serviceManager) throws ServiceException 067 { 068 super.service(serviceManager); 069 _blogRootPageHandler = (BlogPageHandler) serviceManager.lookup(BlogPageHandler.ROLE); 070 _blogCacheManager = (BlogCacheManager) serviceManager.lookup(BlogCacheManager.ROLE); 071 _tagProviderExtensionPoint = (TagProviderExtensionPoint) serviceManager.lookup(TagProviderExtensionPoint.ROLE); 072 } 073 074 @Override 075 public void generate() throws IOException, SAXException, ProcessingException 076 { 077 Request request = ObjectModelHelper.getRequest(objectModel); 078 Page currentPage = (Page) request.getAttribute(Page.class.getName()); 079 080 String site = parameters.getParameter("site", currentPage.getSiteName()); 081 String language = parameters.getParameter("lang", currentPage.getSitemapName()); 082 String pagePath = parameters.getParameter("page-path", ""); 083 int depth = parameters.getParameterAsInteger("depth", -1); 084 085 // Service parameters 086 String excludePrivateAsString = parameters.getParameter("excludePrivateTags", request.getParameter("excludePrivateTags")); 087 boolean excludePrivate = Boolean.parseBoolean(excludePrivateAsString); 088 089 String rootTagName = parameters.getParameter("tag", request.getParameter("tag")); 090 091 PagesContainer container = null; 092 if (StringUtils.isEmpty(pagePath)) 093 { 094 // SAX all pages 095 container = _blogRootPageHandler.getBlogRootPage(site, language); 096 } 097 else 098 { 099 container = _blogRootPageHandler.getBlogPage(site, language, pagePath); 100 101 if (StringUtils.isNotEmpty(rootTagName) && container instanceof VirtualTagsPage) 102 { 103 // SAX from the specified tag virtual page => find the corresponding container 104 Map<String, Object> params = new HashMap<>(); 105 params.put("siteName", site); 106 Tag tag = _tagProviderExtensionPoint.getTag(rootTagName, params); 107 108 if (tag != null) 109 { 110 Set<String> ancestorNames = TagHelper.getAncestorNames(tag, true); 111 try 112 { 113 container = container.getChild(StringUtils.join(ancestorNames, "/")); 114 } 115 catch (UnknownAmetysObjectException e) 116 { 117 // There is no virtual tag page for this tag (= no post) 118 container = null; 119 } 120 } 121 else 122 { 123 // Tag does not exist anymore 124 getLogger().error("Navigation by tags can not be displayed with the unexisting tag '" + rootTagName + "'."); 125 container = null; 126 } 127 } 128 } 129 130 contentHandler.startDocument(); 131 132 XMLUtils.startElement(contentHandler, "pages"); 133 134 if (container != null) 135 { 136 _saxPagesContainer(container, depth, site, excludePrivate); 137 } 138 139 XMLUtils.endElement(contentHandler, "pages"); 140 141 contentHandler.endDocument(); 142 } 143 144 /** 145 * SAX the pages 146 * @param pagesContainer the page or sitemap from which we start to SAX 147 * @param depth the remaining levels of pages to SAX 148 * @param siteName the site's name 149 * @param excludePrivate true to exclude private pages, false otherwise 150 * @throws SAXException if an error occurs while SAXing the pages' information 151 */ 152 private void _saxPagesContainer(PagesContainer pagesContainer, int depth, String siteName, boolean excludePrivate) throws SAXException 153 { 154 if (depth != 0) 155 { 156 for (Page page : pagesContainer.getChildrenPages()) 157 { 158 AttributesImpl attrs = new AttributesImpl (); 159 attrs.addCDATAAttribute("name", page.getName()); 160 attrs.addCDATAAttribute("title", page.getTitle()); 161 attrs.addCDATAAttribute("long-title", page.getLongTitle()); 162 attrs.addCDATAAttribute("path", page.getPathInSitemap()); 163 attrs.addCDATAAttribute("id", page.getId()); 164 165 if (page instanceof VirtualPostPage) 166 { 167 attrs.addCDATAAttribute("type", "post"); 168 } 169 else if (page instanceof VirtualTagPage) 170 { 171 VirtualTagPage tagPage = (VirtualTagPage) page; 172 String tagName = tagPage.getTagName(); 173 174 Map<String, Object> contextualParams = new HashMap<>(); 175 contextualParams.put("siteName", siteName); 176 177 CMSTag tag = _tagProviderExtensionPoint.getTag(tagName, contextualParams); 178 179 if (!excludePrivate || !tag.getVisibility().equals(TagVisibility.PRIVATE)) 180 { 181 // no test on tag visibility 182 attrs.addCDATAAttribute("type", "tag"); 183 184 String language = tagPage.getSitemapName(); 185 Map<String, Post> postsByTag = _blogCacheManager.getPostsByTag(siteName, language, tagName); 186 187 attrs.addCDATAAttribute("entries", String.valueOf(postsByTag.keySet().size())); 188 } 189 } 190 else if (page instanceof VirtualYearPage) 191 { 192 attrs.addCDATAAttribute("type", "year"); 193 } 194 else if (page instanceof VirtualMonthPage) 195 { 196 attrs.addCDATAAttribute("type", "month"); 197 198 VirtualMonthPage monthPage = (VirtualMonthPage) page; 199 String language = monthPage.getSitemapName(); 200 int year = monthPage.getYear(); 201 int month = monthPage.getMonth(); 202 203 Map<String, Post> postsByMonth = _blogCacheManager.getPostsByMonth(siteName, language, year, month); 204 205 attrs.addCDATAAttribute("entries", String.valueOf(postsByMonth.keySet().size())); 206 } 207 208 for (String tag : page.getTags()) 209 { 210 attrs.addCDATAAttribute("PLUGIN_TAGS_" + tag, "empty"); 211 } 212 213 XMLUtils.startElement(contentHandler, "page", attrs); 214 215 _saxPagesContainer(page, depth - 1, siteName, excludePrivate); 216 217 XMLUtils.endElement(contentHandler, "page"); 218 } 219 } 220 } 221} 222