Clover Coverage Report - Google Sitemap Module 1.2.2
Coverage timestamp: Mon Jun 3 2013 12:21:05 CEST
../../../../../img/srcFileCovDistChart9.png 25% of files have more coverage
114   393   51   9.5
62   208   0.45   12
12     4.25  
1    
 
  SiteMapService       Line # 78 114 0% 51 24 87.2% 0.87234044
 
No Tests
 
1    /**
2    * This file Copyright (c) 2012 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.module.googlesitemap.service;
35   
36    import info.magnolia.cms.core.MetaData;
37    import info.magnolia.cms.core.MgnlNodeType;
38    import info.magnolia.cms.i18n.I18nContentSupport;
39    import info.magnolia.cms.i18n.I18nContentSupportFactory;
40    import info.magnolia.cms.util.ContentUtil;
41    import info.magnolia.context.MgnlContext;
42    import info.magnolia.jcr.util.MetaDataUtil;
43    import info.magnolia.link.LinkUtil;
44    import info.magnolia.module.googlesitemap.GoogleSiteMapConfiguration;
45    import info.magnolia.module.googlesitemap.bean.SiteMapEntry;
46    import info.magnolia.module.googlesitemap.service.query.QueryUtil;
47    import info.magnolia.module.templatingkit.sites.Site;
48    import info.magnolia.module.templatingkit.sites.SiteManager;
49    import info.magnolia.repository.RepositoryConstants;
50   
51    import java.util.ArrayList;
52    import java.util.Calendar;
53    import java.util.List;
54    import java.util.Locale;
55   
56    import javax.inject.Inject;
57    import javax.inject.Singleton;
58    import javax.jcr.Node;
59    import javax.jcr.NodeIterator;
60    import javax.jcr.RepositoryException;
61   
62    import org.apache.jackrabbit.commons.iterator.FilteringNodeIterator;
63    import org.apache.jackrabbit.commons.predicate.NodeTypePredicate;
64    import org.slf4j.Logger;
65    import org.slf4j.LoggerFactory;
66   
67   
68    /**
69    * Main SiteMapService.
70    * This service is responsible for:
71    * Searching the appropriate nodes (pages or VirtualUri) that should be displayed (for XML rendering or Editing).
72    * From the search nodes, create SiteMapEntrys (POJO containing preformated infos used for the rendering).
73    *
74    * @version $Id$
75    *
76    */
77    @Singleton
 
78    public class SiteMapService {
79   
80    private static final Logger log = LoggerFactory.getLogger(SiteMapService.class);
81    /**
82    * Injected service.
83    */
84    private SiteManager siteManager;
85    private I18nContentSupport i18nSupport;
86    private GoogleSiteMapConfiguration configuration;
87    private QueryUtil queryUtil;
88    /**
89    * Global variable.
90    */
91    private String lastMod = RepositoryConstants.NAMESPACE_PREFIX + ":" + MetaData.LAST_MODIFIED;
92    private String creation = RepositoryConstants.NAMESPACE_PREFIX + ":" + MetaData.CREATION_DATE;
93   
94   
95    /**
96    * Constructor for injection.
97    * @param siteManager: Injected.
98    */
 
99  24 toggle @Inject
100    public SiteMapService(SiteManager siteManager, GoogleSiteMapConfiguration configuration, QueryUtil queryUtil) {
101  24 this.siteManager = siteManager;
102  24 this.configuration = configuration;
103  24 this.queryUtil = queryUtil;
104  24 i18nSupport = I18nContentSupportFactory.getI18nSupport();
105    }
106   
107   
108    /**
109    * Create the SiteMapEntry List corresponding to the uriMapping.
110    */
 
111  8 toggle public List<SiteMapEntry> getSiteMapBeanForVirtualUri( boolean isForEdit) throws RepositoryException{
112    // Init
113  8 List<SiteMapEntry> res = new ArrayList<SiteMapEntry>();
114  8 NodeIterator nodeIterator = null;
115   
116  8 log.info("Requested virtualUri info's for EDIT ");
117    // Create a virtualUri info beans
118  8 nodeIterator = searchVirtualUriNodes();
119  8 feedVirtualUriMapBeans(res, nodeIterator, isForEdit);
120   
121  8 return res;
122    }
123   
124    /**
125    * Search the nodes related to the UriMappings.
126    */
 
127  8 toggle private NodeIterator searchVirtualUriNodes() {
128  8 NodeIterator nodes = null;
129   
130  8 String xpath = "//virtualURIMapping//element(*,"+MgnlNodeType.NT_CONTENTNODE+")";
131  8 nodes = queryUtil.query(RepositoryConstants.CONFIG, xpath, "xpath", MgnlNodeType.NT_CONTENTNODE);
132   
133  8 return nodes;
134    }
135   
136    /**
137    * Extract informations form the Node and create a Bean used in the display
138    * for Edit and XML rendering.
139    */
 
140  8 toggle private void feedVirtualUriMapBeans(List<SiteMapEntry> siteMapBeans, NodeIterator nodes, boolean isForEdit) throws RepositoryException {
141  24 while(nodes.hasNext()) {
142    // Init
143  16 Node child = nodes.nextNode();
144  16 if(hasToBePopulated(child, true, isForEdit, null)) {
145    //Populate the Bean used by the display
146  11 SiteMapEntry siteMapBean = populateBean(child, true, isForEdit , null, null);
147    //Add the bean to the result
148  11 siteMapBeans.add(siteMapBean);
149    }
150    }
151    }
152   
153   
154    /**
155    * Create the SiteMapEntry for all child's of the rootNode that are of type MgnlNodeType.NT_CONTENT.
156    */
 
157  24 toggle public List<SiteMapEntry> getSiteMapBeanForSite(Node rootNode, boolean isForEdit) throws RepositoryException{
158    // Init
159  24 List<SiteMapEntry> res = new ArrayList<SiteMapEntry>();
160  24 NodeIterator nodeIterator = null;
161   
162  24 log.info("Requested siteMap info's for EDIT based on the following root: "+rootNode.getPath());
163    // Create a site info beans
164  24 nodeIterator = searchSiteChildNodes(rootNode);
165  24 feedSiteMapBeans(res, nodeIterator, isForEdit, null);
166   
167  24 return res;
168    }
169   
170   
171    /**
172    * Search children of the root Node of type MgnlNodeType.NT_CONTENT and all inherited node types.
173    * @throws RepositoryException
174    */
 
175  53 toggle private NodeIterator searchSiteChildNodes(Node root) throws RepositoryException {
176  53 NodeIterator nodes = null;
177   
178  53 NodeTypePredicate predicate = new NodeTypePredicate(MgnlNodeType.NT_CONTENT, true);
179  53 nodes = new FilteringNodeIterator(root.getNodes(), predicate);
180   
181  53 return nodes;
182    }
183   
184   
185    /**
186    * Create a new SiteMapEntry POJO for all node from the NodeIterator if required.
187    */
 
188  31 toggle private void feedSiteMapBeans(List<SiteMapEntry> siteMapBeans, NodeIterator nodes, boolean isForEdit, Boolean inheritedParentDisplayColor) throws RepositoryException {
189   
190  71 while(nodes.hasNext()) {
191    // Init
192  40 Node child = nodes.nextNode();
193  40 Site site = siteManager.getAssignedSite(child);
194   
195  40 if(hasToBePopulated(child, false, isForEdit, site)) {
196    //Populate the Bean used by the display
197  29 SiteMapEntry siteMapBean = populateBean(child, false, isForEdit , site, inheritedParentDisplayColor);
198  29 NodeIterator childNodes = searchSiteChildNodes(child);
199  29 boolean hasChild = (childNodes!=null && childNodes.hasNext()) ? true:false;
200   
201  29 if(isForEdit) {
202    // Handle Edit Mode. Always all the bean.
203  9 siteMapBeans.add(siteMapBean);
204   
205  9 if(hasChild) {
206    // Handle the children if any
207  3 Boolean hideNodeChildInGoogleSitemapTmp = null;
208    // Handle the color of the child to be display.
209  3 if(inheritedParentDisplayColor != null) {
210  0 hideNodeChildInGoogleSitemapTmp = inheritedParentDisplayColor;
211  3 }else if(hideNodeChildInGoogleSitemap(child)) {
212  1 hideNodeChildInGoogleSitemapTmp = Boolean.TRUE;
213    }
214   
215  3 feedSiteMapBeans(siteMapBeans, childNodes, isForEdit, hideNodeChildInGoogleSitemapTmp);
216    }
217   
218    } else {
219    // Handle XML Display Mode
220    // If node has to be display.
221  20 if (!hideNodeInGoogleSitemap(child)){
222    // Check Multilang.
223  19 if(i18nSupport.isEnabled() && site.getI18n().isEnabled()) {
224  0 Locale currentLocale = i18nSupport.getLocale();
225  0 for(Locale locale:site.getI18n().getLocales() ){
226  0 i18nSupport.setLocale(locale);
227  0 SiteMapEntry siteMapBeanLocale = populateBean(child, false, isForEdit, site, null);
228  0 if(siteMapBeanLocale != null) {
229  0 siteMapBeans.add(siteMapBeanLocale);
230    }
231    }
232  0 i18nSupport.setLocale(currentLocale);
233    } else {
234  19 siteMapBeans.add(siteMapBean);
235    }
236    }
237    // Check if Child Node has to be included
238  20 if(hasChild && !hideNodeChildInGoogleSitemap(child)) {
239    // Call recursively
240  4 feedSiteMapBeans(siteMapBeans, childNodes, isForEdit, null);
241    }
242   
243    }
244   
245    }
246   
247    }
248    }
249   
250    /**
251    * Populate the Bean.
252    */
 
253  40 toggle private SiteMapEntry populateBean( Node child, boolean isForUriMapping, boolean isForEdit, Site site, Boolean inheritedParentDisplayColor ) throws RepositoryException {
254  40 SiteMapEntry res = null;
255    // Populate only if true
256  40 if(hasToBePopulated(child, isForUriMapping, isForEdit, site)) {
257  40 double priority = 0.5;
258  40 String changefreq = "weekly";
259  40 String lastmod = "";
260  40 int level = -1;
261  40 String loc = null;
262   
263    // Get Level
264  40 level = child.getDepth();
265   
266    // Get priority
267  40 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_PRIORITY_NODEDATA)) {
268  0 priority = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_PRIORITY_NODEDATA).getDouble();
269    }
270   
271    // Get changefreq
272  40 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_CHANGEFREQ_NODEDATA)) {
273  0 changefreq = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_CHANGEFREQ_NODEDATA).getString();
274    }
275   
276    // Get lastmod
277  40 Node metaData = child.getNode(MetaData.DEFAULT_META_NODE);
278  40 Calendar date = null;
279  40 if(metaData.hasProperty(lastMod)) {
280  40 date = metaData.getProperty(lastMod).getDate();
281    } else {
282  0 date = metaData.getProperty(creation).getDate();
283    }
284  40 lastmod = configuration.getFastDateFormat().format(date.getTime());
285   
286    // Get loc
287  40 if(isForUriMapping) {
288  11 loc = MgnlContext.getContextPath()+child.getProperty("fromURI").getString();
289    }else {
290  29 loc = LinkUtil.createExternalLink(ContentUtil.asContent(child));
291    }
292   
293    //Populate the bean:
294  40 res = new SiteMapEntry(loc, lastmod, changefreq, Double.toString(priority), level);
295  40 log.debug("Populate Basic info for Node: "+child.getPath()+ " with values "+res.toStringDisplay());
296   
297  40 if(isForEdit) {
298  14 res = populateBeanForEdit(child, isForUriMapping, res, inheritedParentDisplayColor);
299    }
300    }
301   
302  40 return res;
303    }
304   
305   
306    /**
307    * Add additional info's for Edit.
308    */
 
309  14 toggle private SiteMapEntry populateBeanForEdit(Node child, boolean isForUriMapping, SiteMapEntry siteMapBean, Boolean inheritedParentDisplayColor) throws RepositoryException {
310    //Common fields
311  14 siteMapBean.setPath(child.getPath());
312   
313  14 if(isForUriMapping) {
314    //For VirtualUri
315  5 siteMapBean.setFrom(child.hasProperty("fromURI")?child.getProperty("fromURI").getString():"");
316  5 siteMapBean.setTo(child.hasProperty("toURI")?child.getProperty("toURI").getString():"");
317  5 siteMapBean.setStyleAlert(hideNodeInGoogleSitemap(child));
318  5 log.debug("Populate Edit VirtualUri info for Node: "+child.getPath()+ " with values "+siteMapBean.toStringVirtualUri());
319    } else {
320    //For Site
321  9 siteMapBean.setPageName(child.hasProperty("title")?child.getProperty("title").getString():"");
322  9 siteMapBean.setStyleAlert(inheritedParentDisplayColor!=null?inheritedParentDisplayColor.booleanValue():hideNodeInGoogleSitemap(child));
323  9 log.debug("Populate Edit Site info for Node: "+child.getPath()+ " with values "+siteMapBean.toStringSite());
324    }
325  14 return siteMapBean;
326    }
327   
328   
329    /**
330    * Check if the node has to be populated.
331    * True for UriMapping if:
332    * !hideInGoogleSitemap && node has a modification date
333    * True for Site if:
334    * !hideInGoogleSitemap && !hideInGoogleSitemapChildren && node has a creation date && site.isEnabled()
335    *
336    */
 
337  96 toggle private boolean hasToBePopulated( Node child, boolean isForUriMapping, boolean isForEdit, Site site ) throws RepositoryException {
338  96 boolean hasCreationDate = child.hasNode(MetaData.DEFAULT_META_NODE) && child.getNode(MetaData.DEFAULT_META_NODE).hasProperty(creation);
339  96 boolean hasModificationDate = child.hasNode(MetaData.DEFAULT_META_NODE) && child.getNode(MetaData.DEFAULT_META_NODE).hasProperty(lastMod);
340   
341    // Exclude SiteMap pages
342  96 if(MetaDataUtil.getTemplate(child).endsWith(GoogleSiteMapConfiguration.SITE_MAP_TEMPLATE_NAME)) {
343  0 return false;
344    }
345   
346    // For edit and if has creation date --> true.
347  96 if(isForEdit) {
348  32 return hasCreationDate;
349    }
350   
351    // Node has a property set to hide node to be display --> false.
352  64 if(hideNodeInGoogleSitemap(child) && (isForUriMapping || hideNodeChildInGoogleSitemap(child))) {
353  1 return false;
354    }
355    // For uriMapping.
356  63 if(isForUriMapping && hasModificationDate) {
357  12 return true;
358    }
359    // For site.
360  51 if(!isForUriMapping && site.isEnabled() && hasCreationDate ) {
361  40 return true;
362    }
363   
364  11 return false;
365    }
366   
367    /**
368    * Check if we have to display in SiteMap.
369    */
 
370  97 toggle private boolean hideNodeInGoogleSitemap(Node child) throws RepositoryException {
371  97 boolean res = false;
372   
373  97 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAP_NODEDATA)) {
374  6 res = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAP_NODEDATA).getBoolean();
375    }
376   
377  97 return res;
378    }
379   
380    /**
381    * Check if we have to display in SiteMap.
382    */
 
383  10 toggle private boolean hideNodeChildInGoogleSitemap(Node child) throws RepositoryException {
384  10 boolean res = false;
385   
386  10 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAPCHILDREN_NODEDATA)) {
387  2 res = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAPCHILDREN_NODEDATA).getBoolean();
388    }
389   
390  10 return res;
391    }
392   
393    }