Clover Coverage Report - Google Sitemap Module 2.0.3
Coverage timestamp: Fri Mar 14 2014 11:34:22 CET
../../../../../../img/srcFileCovDistChart9.png 2% of files have more coverage
67   239   24   7.44
28   137   0.36   9
9     2.67  
1    
 
  SiteMapDefinitionMigrationTask       Line # 74 67 0% 24 11 89.4% 0.8942308
 
No Tests
 
1    /**
2    * This file Copyright (c) 2013 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.setup.migration;
35   
36    import info.magnolia.cms.util.QueryUtil;
37    import info.magnolia.jcr.util.NodeTypes;
38    import info.magnolia.jcr.util.NodeUtil;
39    import info.magnolia.jcr.wrapper.JCRMgnlPropertiesFilteringNodeWrapper;
40    import info.magnolia.jcr.wrapper.JCRPropertiesFilteringNodeWrapper;
41    import info.magnolia.module.InstallContext;
42    import info.magnolia.module.delta.AbstractRepositoryTask;
43    import info.magnolia.module.delta.TaskExecutionException;
44    import info.magnolia.module.googlesitemap.GoogleSiteMapConfiguration;
45    import info.magnolia.module.googlesitemap.config.SiteMapType;
46    import info.magnolia.repository.RepositoryConstants;
47   
48    import java.util.ArrayList;
49    import java.util.Iterator;
50    import java.util.List;
51   
52    import javax.jcr.Node;
53    import javax.jcr.NodeIterator;
54    import javax.jcr.Property;
55    import javax.jcr.PropertyIterator;
56    import javax.jcr.RepositoryException;
57    import javax.jcr.Session;
58    import javax.jcr.query.Query;
59   
60    import org.apache.commons.lang.StringUtils;
61    import org.slf4j.Logger;
62    import org.slf4j.LoggerFactory;
63   
64   
65    /**
66    * Google site map dedicated migration task.<br>
67    * Implemented logic: <br>
68    * - Search all siteMaps definition from the specified workspace.<br>
69    * - For every siteMapDefinition <br>
70    * -- Create a folders representing the siteMap definition path (demo-project/about/siteMapDefinitoin --> demo-project/about) <br>
71    * -- Create a new M5 siteMap definition based on the M4.5 one.<br>
72    * -- Remove the M4.5 siteMap definition.<br>
73    */
 
74    public class SiteMapDefinitionMigrationTask extends AbstractRepositoryTask {
75   
76    private final Logger log = LoggerFactory.getLogger(SiteMapDefinitionMigrationTask.class);
77   
78    private final String sourceWorkspace;
79    private final String searchRootPath;
80    private final String templateName = "google-sitemap:pages/siteMapsConfiguration";
81    private final String siteDefinitionTemplateName = "google-sitemap:components/content/siteComponent";
82    private final String virtualUriTemplateName = "google-sitemap:components/content/virtualUriComponent";
83    private Session siteMapSession;
84   
85   
 
86  4 toggle public SiteMapDefinitionMigrationTask(String name, String description, String sourceWorkspace, String searchRootPath) {
87  4 super(name, description);
88  4 this.sourceWorkspace = (StringUtils.isNotBlank(sourceWorkspace)) ? sourceWorkspace : RepositoryConstants.WEBSITE;
89  4 this.searchRootPath = (StringUtils.isNotBlank(searchRootPath)) ? searchRootPath : "/";
90    }
91   
 
92  3 toggle @Override
93    protected void doExecute(InstallContext installContext) throws RepositoryException, TaskExecutionException {
94    // Init
95  3 siteMapSession = installContext.getJCRSession(GoogleSiteMapConfiguration.WORKSPACE);
96  3 try {
97    // Perform the query
98  3 NodeIterator nodeIterator = getQueryResult();
99    // Handle result
100  8 while (nodeIterator.hasNext()) {
101  5 handleSimeMapDefinitionMigration(nodeIterator.nextNode());
102    }
103   
104    } catch (RepositoryException re) {
105  0 installContext.error("Unable to perform Migration task " + getName(), re);
106  0 throw new TaskExecutionException(re.getMessage());
107    }
108    }
109   
 
110  5 toggle private void handleSimeMapDefinitionMigration(Node siteMapNodeDefinition) throws RepositoryException {
111    // Create path in the siteMap workspace
112  5 Node targetRootSiteMapFolder = getOrCreateRootSiteMapDefinitionNode(siteMapNodeDefinition);
113   
114    // Create an equivalent M5 siteMap definition
115  5 Node targetSiteMapDefinition = migrateSiteMapDefinition(siteMapNodeDefinition, targetRootSiteMapFolder);
116  5 log.info("New M5 siteMapDefinition created {} based on the previous definition {} ", targetSiteMapDefinition.getPath(), siteMapNodeDefinition.getPath());
117   
118    // Remove the original siteMapDefinition
119  5 siteMapNodeDefinition.remove();
120    }
121   
122    /**
123    * Create a M5 siteMapDefinition based on a M4.5 definition.<br>
124    * Steps: <br>
125    * - Create a folder tree to the sitMapDefinition node if required<br>
126    * - Create a new siteMapDefinition nodeTye <br>
127    * - Create a new sites contentNode child
128    * - Copy all site definition from M4.5 into the newly created child node.
129    */
 
130  5 toggle private Node migrateSiteMapDefinition(Node siteMapNodeDefinition, Node targetRootSiteMapFolder) throws RepositoryException {
131    // Create the new M5 definition
132  5 Node targetSiteMapDefinition = targetRootSiteMapFolder.addNode(siteMapNodeDefinition.getName(), GoogleSiteMapConfiguration.NODE_TYPE);
133    // Copy all root properties
134  5 copyOrUpdateProperty(siteMapNodeDefinition, targetSiteMapDefinition);
135   
136    // Copy all properties from M4.5 definition into 5.2 format
137  5 populateSiteMapDefinition(targetSiteMapDefinition, siteMapNodeDefinition);
138   
139  5 return targetSiteMapDefinition;
140    }
141   
 
142  5 toggle private void populateSiteMapDefinition(Node targetSiteMapDefinition, Node sourceSiteMapNodeDefinition) throws RepositoryException {
143  5 List<String> siteMapDefinitionList = new ArrayList<String>();
144  5 boolean insertVirtualUri = false;
145  5 Iterable<Node> children = NodeUtil.collectAllChildren(sourceSiteMapNodeDefinition);
146  5 Iterator<Node> childrenIterator = children.iterator();
147    // Iterate the child nodes and extract the configuration
148  27 while (childrenIterator.hasNext()) {
149  22 Node child = childrenIterator.next();
150  22 if (StringUtils.isNotBlank(NodeTypes.Renderable.getTemplate(child))) {
151  10 String templateName = NodeTypes.Renderable.getTemplate(child);
152  10 if (virtualUriTemplateName.equals(templateName)) {
153  3 insertVirtualUri = true;
154  7 } else if (siteDefinitionTemplateName.equals(templateName)) {
155  7 siteMapDefinitionList.addAll(extractSiteMapDefinition(child));
156    }
157    }
158    }
159   
160    // Set includeVirtualURIMappings property
161  5 targetSiteMapDefinition.setProperty(GoogleSiteMapConfiguration.INCLUDE_VIRTUAL_URI_MAPPINGS_PROPERTIES, insertVirtualUri);
162    // Set siteMaps definition
163  5 if (!siteMapDefinitionList.isEmpty()) {
164  5 Node sites = targetSiteMapDefinition.addNode("sites", NodeTypes.ContentNode.NAME);
165  5 int pos = 0;
166  5 for (String definition : siteMapDefinitionList) {
167  12 sites.setProperty("" + pos, definition);
168  12 pos += 1;
169    }
170    }
171    }
172   
 
173  7 toggle private List<String> extractSiteMapDefinition(Node parent) throws RepositoryException {
174  7 List<String> siteDefinitions = new ArrayList<String>();
175  7 if (parent.hasNode(GoogleSiteMapConfiguration.SITE_DIALOG_CONFIGURATION_NAME)) {
176  7 Node filteredNode = new JCRMgnlPropertiesFilteringNodeWrapper(parent.getNode(GoogleSiteMapConfiguration.SITE_DIALOG_CONFIGURATION_NAME));
177  7 PropertyIterator iterator = filteredNode.getProperties();
178  19 while (iterator.hasNext()) {
179  12 Property property = iterator.nextProperty();
180  12 siteDefinitions.add(property.getString());
181    }
182    } else {
183  0 log.info("Node '{}' do not have a 'sites' child node.", parent.getPath());
184    }
185  7 return siteDefinitions;
186    }
187   
188   
189    /**
190    * Copy all non jcr: properties from the source to the target node.
191    */
 
192  5 toggle private void copyOrUpdateProperty(Node source, Node target) throws RepositoryException {
193  5 Node filteredSource = new JCRPropertiesFilteringNodeWrapper(source);
194  5 PropertyIterator iterator = filteredSource.getProperties();
195  40 while (iterator.hasNext()) {
196  35 Property property = iterator.nextProperty();
197  35 if (target.hasProperty(property.getName())) {
198  0 target.getProperty(property.getName()).setValue(property.getValue());
199    } else {
200  35 target.setProperty(property.getName(), property.getValue());
201    }
202    }
203    // Set Url
204  5 target.setProperty(GoogleSiteMapConfiguration.SITE_MAP_URL_PROPERTY_NAME, source.getPath());
205    // Set default type
206  5 target.setProperty(GoogleSiteMapConfiguration.SITE_MAP_TYPE_PROPERTY_NAME, SiteMapType.Standard.name());
207    // Set display name
208  5 target.setProperty(GoogleSiteMapConfiguration.SITE_MAP_DISPLAY_NAME_PROPERTY_NAME, source.getName());
209    }
210   
211    /**
212    * Create the site map definition parent folder.
213    */
 
214  5 toggle Node getOrCreateRootSiteMapDefinitionNode(Node siteMapNodeDefinition) throws RepositoryException {
215    // If the definition is at the root level, return the root node.
216  5 if (siteMapNodeDefinition.getDepth() <= 1) {
217  2 return siteMapSession.getRootNode();
218    }
219    // If the path already exist return the referenced node..
220  3 String targetPath = siteMapNodeDefinition.getParent().getPath();
221  3 if (siteMapSession.nodeExists(targetPath)) {
222  0 return siteMapSession.getNode(targetPath);
223    }
224    // If the path do not already exist, create it.
225  3 return NodeUtil.createPath(siteMapSession.getRootNode(), targetPath, NodeTypes.Folder.NAME, false);
226    }
227   
228    /**
229    * Search all node within 'sourceWorkspace' that are under the 'searchRootPath' containing a template definition equal to 'templateName'.
230    */
 
231  3 toggle private NodeIterator getQueryResult() throws RepositoryException {
232  3 NodeIterator nodeIterator = null;
233  3 String query = "SELECT * FROM [nt:base] AS t WHERE (ISSAMENODE(t, '" + searchRootPath + "') OR ISDESCENDANTNODE(t, '" + searchRootPath + "')) " +
234    "AND t.[mgnl:template] is not null AND contains(t.[" + NodeTypes.Renderable.TEMPLATE + "],'" + templateName + "')";
235  3 nodeIterator = QueryUtil.search(sourceWorkspace, query, Query.JCR_SQL2);
236  3 log.info("{} google site map definitions will be handled", nodeIterator.getSize());
237  3 return nodeIterator;
238    }
239    }