Clover icon

Google Sitemap Module 2.4.3

  1. Project Clover database Thu May 11 2017 16:52:32 CEST
  2. Package info.magnolia.module.googlesitemap.setup.migration

File SiteMapDefinitionMigrationTask.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart2.png
66% of files have more coverage

Code metrics

28
67
9
1
241
139
24
0.36
7.44
9
2.67

Classes

Class Line # Actions
SiteMapDefinitionMigrationTask 75 67 0% 24 86
0.1730769317.3%
 

Contributing tests

This file is covered by 12 tests. .

Source view

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