1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.googlesitemap.service;
35
36 import info.magnolia.cms.i18n.I18nContentSupport;
37 import info.magnolia.context.MgnlContext;
38 import info.magnolia.jcr.util.NodeTypes;
39 import info.magnolia.jcr.util.NodeUtil;
40 import info.magnolia.link.LinkUtil;
41 import info.magnolia.module.googlesitemap.GoogleSiteMapConfiguration;
42 import info.magnolia.module.googlesitemap.SiteMapNodeTypes;
43 import info.magnolia.module.googlesitemap.bean.SiteMapEntry;
44 import info.magnolia.module.googlesitemap.service.query.QueryUtil;
45 import info.magnolia.module.site.Site;
46 import info.magnolia.module.site.SiteManager;
47 import info.magnolia.objectfactory.Components;
48 import info.magnolia.repository.RepositoryConstants;
49
50 import java.util.ArrayList;
51 import java.util.HashSet;
52 import java.util.Iterator;
53 import java.util.List;
54 import java.util.Locale;
55 import java.util.Set;
56
57 import javax.inject.Inject;
58 import javax.inject.Singleton;
59 import javax.jcr.Node;
60 import javax.jcr.NodeIterator;
61 import javax.jcr.RepositoryException;
62 import javax.jcr.Session;
63
64 import org.apache.jackrabbit.commons.iterator.FilteringNodeIterator;
65 import org.apache.jackrabbit.commons.predicate.NodeTypePredicate;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69
70
71
72
73
74
75 @Singleton
76 public class SiteMapService {
77
78 private static final Logger log = LoggerFactory.getLogger(SiteMapService.class);
79
80
81
82
83 private SiteManager siteManager;
84 private I18nContentSupport i18nSupport;
85 private GoogleSiteMapConfiguration configuration;
86 private QueryUtil queryUtil;
87
88
89
90
91
92
93 @Inject
94 public SiteMapService(SiteManager siteManager, GoogleSiteMapConfiguration configuration, QueryUtil queryUtil) {
95 this.siteManager = siteManager;
96 this.configuration = configuration;
97 this.queryUtil = queryUtil;
98 i18nSupport = Components.getComponent(I18nContentSupport.class);
99 }
100
101
102
103
104
105
106 public List<SiteMapEntry> getSiteMapBeans(Node siteMapNode, boolean isForVirtualUri, boolean isForEdit) throws RepositoryException {
107
108 List<SiteMapEntry> res = new ArrayList<SiteMapEntry>();
109 final String changefreq = SiteMapNodeTypes.SiteMap.getDefaultChangeFreq(siteMapNode) != null ? SiteMapNodeTypes.SiteMap.getDefaultChangeFreq(siteMapNode) : configuration.getChangeFrequency();
110 final Double priority = SiteMapNodeTypes.SiteMap.getDefaultPriority(siteMapNode) != null ? SiteMapNodeTypes.SiteMap.getDefaultPriority(siteMapNode) : configuration.getPriority();
111 Session webSiteSession = MgnlContext.getJCRSession(RepositoryConstants.WEBSITE);
112
113 NodeIterator nodeIterator = null;
114 if (isForVirtualUri) {
115 log.info("Requested virtualUri info's for EDIT='{}", isForEdit);
116
117 nodeIterator = searchVirtualUriNodes();
118 feedVirtualUriMapBeans(res, nodeIterator, isForEdit, changefreq, priority);
119 } else {
120 log.info("Requested siteMap info's for EDIT='{}' based on the following root {} ", isForEdit, siteMapNode.getPath());
121
122
123 List<String> pages = SiteMapNodeTypes.SiteMap.getPages(siteMapNode);
124 for (String id : pages) {
125
126 if (!webSiteSession.nodeExists(id)) {
127 log.debug("Page '{}' is not visible. This page will not be added to the result list", id);
128 continue;
129 }
130 Node page = webSiteSession.getNode(id);
131 nodeIterator = searchSiteChildNodes(page);
132 feedSiteMapBeans(res, nodeIterator, isForEdit, null, changefreq, priority, page.getDepth());
133 }
134 }
135
136 return res;
137 }
138
139
140
141
142 private NodeIterator searchVirtualUriNodes() {
143 NodeIterator nodes = null;
144
145 String xpath = "//virtualURIMapping//element(*," + NodeTypes.ContentNode.NAME + ")";
146 nodes = queryUtil.query(RepositoryConstants.CONFIG, xpath, "xpath", NodeTypes.ContentNode.NAME);
147
148 return nodes;
149 }
150
151
152
153
154
155 private void feedVirtualUriMapBeans(List<SiteMapEntry> siteMapBeans, NodeIterator nodes, boolean isForEdit, String changefreq, Double priority) throws RepositoryException {
156
157 while (nodes.hasNext()) {
158
159 Node child = nodes.nextNode();
160 if (hasToBePopulated(child, true, isForEdit, null)) {
161
162 SiteMapEntry siteMapBean = populateBean(child, true, isForEdit, null, null, changefreq, priority, 0);
163
164 siteMapBeans.add(siteMapBean);
165 }
166 }
167 }
168
169
170
171
172
173
174 private NodeIterator searchSiteChildNodes(Node root) throws RepositoryException {
175 NodeIterator nodes = null;
176
177 NodeTypePredicate predicate = new NodeTypePredicate(NodeTypes.Content.NAME, true);
178 nodes = new FilteringNodeIterator(root.getNodes(), predicate);
179
180 return nodes;
181 }
182
183
184
185
186 private void feedSiteMapBeans(List<SiteMapEntry> siteMapBeans, NodeIterator nodes, boolean isForEdit, Boolean inheritedParentDisplayColor, String changefreq, Double priority, int rootLevel) throws RepositoryException {
187
188 while (nodes.hasNext()) {
189
190 Node page = nodes.nextNode();
191 Site site = siteManager.getAssignedSite(page);
192 if (!hasToBePopulated(page, false, isForEdit, site)) {
193 log.debug("Page '' is not part of the site map.", NodeUtil.getNodePathIfPossible(page));
194 continue;
195 }
196
197
198 SiteMapEntry siteMapBean = populateBean(page, false, isForEdit, site, inheritedParentDisplayColor, changefreq, priority, rootLevel);
199 NodeIterator childNodes = searchSiteChildNodes(page);
200 boolean hasChild = (childNodes != null && childNodes.hasNext());
201
202 if (isForEdit) {
203
204 siteMapBeans.add(siteMapBean);
205
206 if (hasChild) {
207
208 Boolean hideNodeChildInGoogleSitemapTmp = null;
209
210 if (inheritedParentDisplayColor != null) {
211 hideNodeChildInGoogleSitemapTmp = inheritedParentDisplayColor;
212 } else if (SiteMapNodeTypes.GoogleSiteMap.isHideChildren(page)) {
213 hideNodeChildInGoogleSitemapTmp = Boolean.TRUE;
214 }
215
216 feedSiteMapBeans(siteMapBeans, childNodes, isForEdit, hideNodeChildInGoogleSitemapTmp, changefreq, priority, rootLevel);
217 }
218
219 } else {
220
221
222 if (!SiteMapNodeTypes.GoogleSiteMap.isHide(page)) {
223
224 if (i18nSupport.isEnabled() && site.getI18n().isEnabled()) {
225 Locale currentLocale = i18nSupport.getLocale();
226 for (Locale locale : site.getI18n().getLocales()) {
227 i18nSupport.setLocale(locale);
228 SiteMapEntry siteMapBeanLocale = populateBean(page, false, isForEdit, site, null, changefreq, priority, rootLevel);
229 if (siteMapBeanLocale != null) {
230 siteMapBeans.add(siteMapBeanLocale);
231 }
232 }
233 i18nSupport.setLocale(currentLocale);
234 } else {
235 siteMapBeans.add(siteMapBean);
236 }
237 }
238
239 if (hasChild && !SiteMapNodeTypes.GoogleSiteMap.isHideChildren(page)) {
240
241 feedSiteMapBeans(siteMapBeans, childNodes, isForEdit, null, changefreq, priority, rootLevel);
242 }
243 }
244 }
245 }
246
247
248
249
250 private SiteMapEntry populateBean(Node child, boolean isForUriMapping, boolean isForEdit, Site site, Boolean inheritedParentDisplayColor, String changefreq, Double priority, int rootLevel) throws RepositoryException {
251 SiteMapEntry res = null;
252
253 if (hasToBePopulated(child, isForUriMapping, isForEdit, site)) {
254
255 String loc = null;
256
257
258 if (isForUriMapping) {
259 loc = child.hasProperty("fromURI") ? MgnlContext.getContextPath() + child.getProperty("fromURI").getString() : "";
260 } else {
261 loc = LinkUtil.createExternalLink(child);
262 }
263
264
265 res = new SiteMapEntry(configuration, loc, child, rootLevel, changefreq, priority);
266 log.debug("Populate Basic info for Node: " + child.getPath() + " with values " + res.toStringDisplay());
267
268 if (isForEdit) {
269 res = populateBeanForEdit(child, isForUriMapping, res, inheritedParentDisplayColor);
270 }
271 }
272
273 return res;
274 }
275
276
277
278
279 private SiteMapEntry populateBeanForEdit(Node child, boolean isForUriMapping, SiteMapEntry siteMapBean, Boolean inheritedParentDisplayColor) throws RepositoryException {
280
281 if (isForUriMapping) {
282
283 siteMapBean.setFrom(child.hasProperty("fromURI") ? child.getProperty("fromURI").getString() : "");
284 siteMapBean.setTo(child.hasProperty("toURI") ? child.getProperty("toURI").getString() : "");
285 siteMapBean.setStyleAlert(SiteMapNodeTypes.GoogleSiteMap.isHide(child));
286 log.debug("Populate Edit VirtualUri info for Node: " + child.getPath() + " with values " + siteMapBean.toStringVirtualUri());
287 } else {
288
289 siteMapBean.setPageName(child.hasProperty("title") ? child.getProperty("title").getString() : "");
290 siteMapBean.setStyleAlert(inheritedParentDisplayColor != null ? inheritedParentDisplayColor.booleanValue() : SiteMapNodeTypes.GoogleSiteMap.isHide(child));
291 log.debug("Populate Edit Site info for Node: " + child.getPath() + " with values " + siteMapBean.toStringSite());
292 }
293 return siteMapBean;
294 }
295
296
297
298
299
300
301
302
303 private boolean hasToBePopulated(Node child, boolean isForUriMapping, boolean isForEdit, Site site) throws RepositoryException {
304 boolean hasCreationDate = NodeTypes.Created.getCreated(child) != null;
305 boolean hasModificationDate = NodeTypes.LastModified.getLastModified(child) != null;
306
307
308 if (isForEdit) {
309 return hasCreationDate;
310 }
311
312
313 if (SiteMapNodeTypes.GoogleSiteMap.isHide(child) && (isForUriMapping || SiteMapNodeTypes.GoogleSiteMap.isHideChildren(child))) {
314 return false;
315 }
316
317 if (isForUriMapping && hasModificationDate) {
318 return true;
319 }
320
321 if (!isForUriMapping && site.isEnabled() && hasCreationDate) {
322 return true;
323 }
324 return false;
325 }
326
327
328
329
330
331 public Iterator<SiteMapEntry> getSiteMapBeans(Node siteMapNode) throws RepositoryException {
332 Set<SiteMapEntry> res = new HashSet<SiteMapEntry>();
333
334 if (!NodeUtil.isNodeType(siteMapNode, SiteMapNodeTypes.SiteMap.NAME)) {
335 return res.iterator();
336 }
337
338 res.addAll(getSiteMapBeans(siteMapNode, false, false));
339 if (SiteMapNodeTypes.SiteMap.isVirtualUriMappingIncluded(siteMapNode)) {
340 res.addAll(getSiteMapBeans(siteMapNode, true, false));
341 }
342 return res.iterator();
343 }
344
345
346
347
348
349
350 public Node updatePageNode(SiteMapEntry entry) throws RepositoryException {
351 Node pageNode = MgnlContext.getJCRSession(RepositoryConstants.WEBSITE).getNode(entry.getPath());
352 return updateNode(entry, pageNode);
353 }
354
355 public Node updateVirtualUriNode(SiteMapEntry entry) throws RepositoryException {
356 Node virtualUriNode = MgnlContext.getJCRSession(RepositoryConstants.CONFIG).getNode(entry.getPath());
357 return updateNode(entry, virtualUriNode);
358 }
359
360 private Node updateNode(SiteMapEntry entry, Node node) throws RepositoryException {
361 SiteMapNodeTypes.GoogleSiteMap.update(node, entry.getChangefreq(), entry.getPriority(), entry.isHide(), entry.isHideChildren());
362 NodeTypes.LastModified.update(node);
363 return node;
364 }
365 }