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.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
70
71
72
73
74
75
76
77 @Singleton
78 public class SiteMapService {
79
80 private static final Logger log = LoggerFactory.getLogger(SiteMapService.class);
81
82
83
84 private SiteManager siteManager;
85 private I18nContentSupport i18nSupport;
86 private GoogleSiteMapConfiguration configuration;
87 private QueryUtil queryUtil;
88
89
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
97
98
99 @Inject
100 public SiteMapService(SiteManager siteManager, GoogleSiteMapConfiguration configuration, QueryUtil queryUtil) {
101 this.siteManager = siteManager;
102 this.configuration = configuration;
103 this.queryUtil = queryUtil;
104 i18nSupport = I18nContentSupportFactory.getI18nSupport();
105 }
106
107
108
109
110
111 public List<SiteMapEntry> getSiteMapBeanForVirtualUri( boolean isForEdit) throws RepositoryException{
112
113 List<SiteMapEntry> res = new ArrayList<SiteMapEntry>();
114 NodeIterator nodeIterator = null;
115
116 log.info("Requested virtualUri info's for EDIT ");
117
118 nodeIterator = searchVirtualUriNodes();
119 feedVirtualUriMapBeans(res, nodeIterator, isForEdit);
120
121 return res;
122 }
123
124
125
126
127 private NodeIterator searchVirtualUriNodes() {
128 NodeIterator nodes = null;
129
130 String xpath = "//virtualURIMapping//element(*,"+MgnlNodeType.NT_CONTENTNODE+")";
131 nodes = queryUtil.query(RepositoryConstants.CONFIG, xpath, "xpath", MgnlNodeType.NT_CONTENTNODE);
132
133 return nodes;
134 }
135
136
137
138
139
140 private void feedVirtualUriMapBeans(List<SiteMapEntry> siteMapBeans, NodeIterator nodes, boolean isForEdit) throws RepositoryException {
141 while(nodes.hasNext()) {
142
143 Node child = nodes.nextNode();
144 if(hasToBePopulated(child, true, isForEdit, null)) {
145
146 SiteMapEntry siteMapBean = populateBean(child, true, isForEdit , null, null);
147
148 siteMapBeans.add(siteMapBean);
149 }
150 }
151 }
152
153
154
155
156
157 public List<SiteMapEntry> getSiteMapBeanForSite(Node rootNode, boolean isForEdit) throws RepositoryException{
158
159 List<SiteMapEntry> res = new ArrayList<SiteMapEntry>();
160 NodeIterator nodeIterator = null;
161
162 log.info("Requested siteMap info's for EDIT based on the following root: "+rootNode.getPath());
163
164 nodeIterator = searchSiteChildNodes(rootNode);
165 feedSiteMapBeans(res, nodeIterator, isForEdit, null);
166
167 return res;
168 }
169
170
171
172
173
174
175 private NodeIterator searchSiteChildNodes(Node root) throws RepositoryException {
176 NodeIterator nodes = null;
177
178 NodeTypePredicate predicate = new NodeTypePredicate(MgnlNodeType.NT_CONTENT, true);
179 nodes = new FilteringNodeIterator(root.getNodes(), predicate);
180
181 return nodes;
182 }
183
184
185
186
187
188 private void feedSiteMapBeans(List<SiteMapEntry> siteMapBeans, NodeIterator nodes, boolean isForEdit, Boolean inheritedParentDisplayColor) throws RepositoryException {
189
190 while(nodes.hasNext()) {
191
192 Node child = nodes.nextNode();
193 Site site = siteManager.getAssignedSite(child);
194
195 if(hasToBePopulated(child, false, isForEdit, site)) {
196
197 SiteMapEntry siteMapBean = populateBean(child, false, isForEdit , site, inheritedParentDisplayColor);
198 NodeIterator childNodes = searchSiteChildNodes(child);
199 boolean hasChild = (childNodes!=null && childNodes.hasNext()) ? true:false;
200
201 if(isForEdit) {
202
203 siteMapBeans.add(siteMapBean);
204
205 if(hasChild) {
206
207 Boolean hideNodeChildInGoogleSitemapTmp = null;
208
209 if(inheritedParentDisplayColor != null) {
210 hideNodeChildInGoogleSitemapTmp = inheritedParentDisplayColor;
211 }else if(hideNodeChildInGoogleSitemap(child)) {
212 hideNodeChildInGoogleSitemapTmp = Boolean.TRUE;
213 }
214
215 feedSiteMapBeans(siteMapBeans, childNodes, isForEdit, hideNodeChildInGoogleSitemapTmp);
216 }
217
218 } else {
219
220
221 if (!hideNodeInGoogleSitemap(child)){
222
223 if(i18nSupport.isEnabled() && site.getI18n().isEnabled()) {
224 Locale currentLocale = i18nSupport.getLocale();
225 for(Locale locale:site.getI18n().getLocales() ){
226 i18nSupport.setLocale(locale);
227 SiteMapEntry siteMapBeanLocale = populateBean(child, false, isForEdit, site, null);
228 if(siteMapBeanLocale != null) {
229 siteMapBeans.add(siteMapBeanLocale);
230 }
231 }
232 i18nSupport.setLocale(currentLocale);
233 } else {
234 siteMapBeans.add(siteMapBean);
235 }
236 }
237
238 if(hasChild && !hideNodeChildInGoogleSitemap(child)) {
239
240 feedSiteMapBeans(siteMapBeans, childNodes, isForEdit, null);
241 }
242
243 }
244
245 }
246
247 }
248 }
249
250
251
252
253 private SiteMapEntry populateBean( Node child, boolean isForUriMapping, boolean isForEdit, Site site, Boolean inheritedParentDisplayColor ) throws RepositoryException {
254 SiteMapEntry res = null;
255
256 if(hasToBePopulated(child, isForUriMapping, isForEdit, site)) {
257 double priority = 0.5;
258 String changefreq = "weekly";
259 String lastmod = "";
260 int level = -1;
261 String loc = null;
262
263
264 level = child.getDepth();
265
266
267 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_PRIORITY_NODEDATA)) {
268 priority = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_PRIORITY_NODEDATA).getDouble();
269 }
270
271
272 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_CHANGEFREQ_NODEDATA)) {
273 changefreq = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_CHANGEFREQ_NODEDATA).getString();
274 }
275
276
277 Node metaData = child.getNode(MetaData.DEFAULT_META_NODE);
278 Calendar date = null;
279 if(metaData.hasProperty(lastMod)) {
280 date = metaData.getProperty(lastMod).getDate();
281 } else {
282 date = metaData.getProperty(creation).getDate();
283 }
284 lastmod = configuration.getFastDateFormat().format(date.getTime());
285
286
287 if(isForUriMapping) {
288 loc = MgnlContext.getContextPath()+child.getProperty("fromURI").getString();
289 }else {
290 loc = LinkUtil.createExternalLink(ContentUtil.asContent(child));
291 }
292
293
294 res = new SiteMapEntry(loc, lastmod, changefreq, Double.toString(priority), level);
295 log.debug("Populate Basic info for Node: "+child.getPath()+ " with values "+res.toStringDisplay());
296
297 if(isForEdit) {
298 res = populateBeanForEdit(child, isForUriMapping, res, inheritedParentDisplayColor);
299 }
300 }
301
302 return res;
303 }
304
305
306
307
308
309 private SiteMapEntry populateBeanForEdit(Node child, boolean isForUriMapping, SiteMapEntry siteMapBean, Boolean inheritedParentDisplayColor) throws RepositoryException {
310
311 siteMapBean.setPath(child.getPath());
312
313 if(isForUriMapping) {
314
315 siteMapBean.setFrom(child.hasProperty("fromURI")?child.getProperty("fromURI").getString():"");
316 siteMapBean.setTo(child.hasProperty("toURI")?child.getProperty("toURI").getString():"");
317 siteMapBean.setStyleAlert(hideNodeInGoogleSitemap(child));
318 log.debug("Populate Edit VirtualUri info for Node: "+child.getPath()+ " with values "+siteMapBean.toStringVirtualUri());
319 } else {
320
321 siteMapBean.setPageName(child.hasProperty("title")?child.getProperty("title").getString():"");
322 siteMapBean.setStyleAlert(inheritedParentDisplayColor!=null?inheritedParentDisplayColor.booleanValue():hideNodeInGoogleSitemap(child));
323 log.debug("Populate Edit Site info for Node: "+child.getPath()+ " with values "+siteMapBean.toStringSite());
324 }
325 return siteMapBean;
326 }
327
328
329
330
331
332
333
334
335
336
337 private boolean hasToBePopulated( Node child, boolean isForUriMapping, boolean isForEdit, Site site ) throws RepositoryException {
338 boolean hasCreationDate = child.hasNode(MetaData.DEFAULT_META_NODE) && child.getNode(MetaData.DEFAULT_META_NODE).hasProperty(creation);
339 boolean hasModificationDate = child.hasNode(MetaData.DEFAULT_META_NODE) && child.getNode(MetaData.DEFAULT_META_NODE).hasProperty(lastMod);
340
341
342 if(MetaDataUtil.getTemplate(child).endsWith(GoogleSiteMapConfiguration.SITE_MAP_TEMPLATE_NAME)) {
343 return false;
344 }
345
346
347 if(isForEdit) {
348 return hasCreationDate;
349 }
350
351
352 if(hideNodeInGoogleSitemap(child) && (isForUriMapping || hideNodeChildInGoogleSitemap(child))) {
353 return false;
354 }
355
356 if(isForUriMapping && hasModificationDate) {
357 return true;
358 }
359
360 if(!isForUriMapping && site.isEnabled() && hasCreationDate ) {
361 return true;
362 }
363
364 return false;
365 }
366
367
368
369
370 private boolean hideNodeInGoogleSitemap(Node child) throws RepositoryException {
371 boolean res = false;
372
373 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAP_NODEDATA)) {
374 res = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAP_NODEDATA).getBoolean();
375 }
376
377 return res;
378 }
379
380
381
382
383 private boolean hideNodeChildInGoogleSitemap(Node child) throws RepositoryException {
384 boolean res = false;
385
386 if(child.hasProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAPCHILDREN_NODEDATA)) {
387 res = child.getProperty(GoogleSiteMapConfiguration.DEFAULT_HIDEINGOOGLESITEMAPCHILDREN_NODEDATA).getBoolean();
388 }
389
390 return res;
391 }
392
393 }