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.templating.functions;
35
36 import info.magnolia.cms.beans.config.ServerConfiguration;
37 import info.magnolia.cms.core.AggregationState;
38 import info.magnolia.cms.core.MetaData;
39 import info.magnolia.cms.core.MgnlNodeType;
40 import info.magnolia.cms.core.NodeData;
41 import info.magnolia.cms.i18n.I18nContentSupportFactory;
42 import info.magnolia.cms.util.ContentUtil;
43 import info.magnolia.cms.util.SiblingsHelper;
44 import info.magnolia.jcr.inheritance.InheritanceNodeWrapper;
45 import info.magnolia.jcr.util.ContentMap;
46 import info.magnolia.jcr.util.NodeUtil;
47 import info.magnolia.jcr.util.PropertyUtil;
48 import info.magnolia.jcr.util.SessionUtil;
49 import info.magnolia.jcr.wrapper.HTMLEscapingNodeWrapper;
50 import info.magnolia.link.LinkUtil;
51 import info.magnolia.objectfactory.Components;
52 import info.magnolia.rendering.template.configured.ConfiguredInheritance;
53 import info.magnolia.repository.RepositoryConstants;
54 import info.magnolia.templating.inheritance.DefaultInheritanceContentDecorator;
55
56 import java.util.ArrayList;
57 import java.util.Collection;
58 import java.util.List;
59
60 import javax.inject.Inject;
61 import javax.inject.Provider;
62 import javax.jcr.Node;
63 import javax.jcr.PathNotFoundException;
64 import javax.jcr.Property;
65 import javax.jcr.PropertyType;
66 import javax.jcr.RepositoryException;
67
68 import org.apache.commons.lang.StringUtils;
69
70
71
72
73
74
75 public class TemplatingFunctions {
76
77 private final Provider<AggregationState> aggregationStateProvider;
78
79
80 @Inject
81 public TemplatingFunctions(Provider<AggregationState> aggregationStateProvider) {
82 this.aggregationStateProvider = aggregationStateProvider;
83 }
84
85
86 public Node asJCRNode(ContentMap contentMap) {
87 return contentMap == null ? null : contentMap.getJCRNode();
88 }
89
90 public ContentMap asContentMap(Node content) {
91 return content == null ? null : new ContentMap(content);
92 }
93
94 public List<Node> children(Node content) throws RepositoryException {
95 return content == null ? null : asNodeList(NodeUtil.getNodes(content, NodeUtil.EXCLUDE_META_DATA_FILTER));
96 }
97
98 public List<Node> children(Node content, String nodeTypeName) throws RepositoryException {
99 return content == null ? null : asNodeList(NodeUtil.getNodes(content, nodeTypeName));
100 }
101
102 public List<ContentMap> children(ContentMap content) throws RepositoryException {
103 return content == null ? null : asContentMapList(NodeUtil.getNodes(asJCRNode(content), NodeUtil.EXCLUDE_META_DATA_FILTER));
104 }
105
106 public List<ContentMap> children(ContentMap content, String nodeTypeName) throws RepositoryException {
107 return content == null ? null : asContentMapList(NodeUtil.getNodes(asJCRNode(content), nodeTypeName));
108 }
109
110 public ContentMap root(ContentMap contentMap) throws RepositoryException {
111 return contentMap == null ? null : asContentMap(this.root(contentMap.getJCRNode()));
112 }
113
114 public ContentMap root(ContentMap contentMap, String nodeTypeName) throws RepositoryException {
115 return contentMap == null ? null : asContentMap(this.root(contentMap.getJCRNode(), nodeTypeName));
116 }
117
118 public Node root(Node content) throws RepositoryException {
119 return this.root(content, null);
120 }
121
122 public Node root(Node content, String nodeTypeName) throws RepositoryException {
123 if (content == null) {
124 return null;
125 }
126 if (nodeTypeName == null) {
127 return (Node) content.getAncestor(0);
128 }
129 if (isRoot(content) && content.isNodeType(nodeTypeName)) {
130 return content;
131 }
132
133 Node parentNode = this.parent(content, nodeTypeName);
134 while (parent(parentNode, nodeTypeName) != null) {
135 parentNode = this.parent(parentNode, nodeTypeName);
136 }
137 return parentNode;
138 }
139
140 public ContentMap parent(ContentMap contentMap) throws RepositoryException {
141 return contentMap == null ? null : asContentMap(this.parent(contentMap.getJCRNode()));
142 }
143
144 public ContentMap parent(ContentMap contentMap, String nodeTypeName) throws RepositoryException {
145 return contentMap == null ? null : asContentMap(this.parent(contentMap.getJCRNode(), nodeTypeName));
146 }
147
148 public Node parent(Node content) throws RepositoryException {
149 return this.parent(content, null);
150 }
151
152 public Node parent(Node content, String nodeTypeName) throws RepositoryException {
153 if (content == null) {
154 return null;
155 }
156 if (isRoot(content)) {
157 return null;
158 }
159 if (nodeTypeName == null) {
160 return content.getParent();
161 }
162 Node parent = content.getParent();
163 while (!parent.isNodeType(nodeTypeName)) {
164 if (isRoot(parent)) {
165 return null;
166 }
167 parent = parent.getParent();
168 }
169 return parent;
170 }
171
172
173
174
175
176
177
178
179
180 public ContentMap page(ContentMap content) throws RepositoryException {
181 return content == null ? null : asContentMap(page(content.getJCRNode()));
182 }
183
184
185
186
187
188
189
190
191
192 public Node page(Node content) throws RepositoryException {
193 if (content == null) {
194 return null;
195 }
196 if (content.isNodeType(MgnlNodeType.NT_PAGE)) {
197 return content;
198 }
199 return parent(content, MgnlNodeType.NT_PAGE);
200 }
201
202 public List<ContentMap> ancestors(ContentMap contentMap) throws RepositoryException {
203 return ancestors(contentMap, null);
204 }
205
206 public List<ContentMap> ancestors(ContentMap contentMap, String nodeTypeName) throws RepositoryException {
207 List<Node> ancestorsAsNodes = this.ancestors(contentMap.getJCRNode(), nodeTypeName);
208 return asContentMapList(ancestorsAsNodes);
209 }
210
211 public List<Node> ancestors(Node content) throws RepositoryException {
212 return content == null ? null : this.ancestors(content, null);
213 }
214
215 public List<Node> ancestors(Node content, String nodeTypeName) throws RepositoryException {
216 if (content == null) {
217 return null;
218 }
219 List<Node> ancestors = new ArrayList<Node>();
220 int depth = content.getDepth();
221 for (int i = 1; i < depth; ++i) {
222 Node possibleAncestor = (Node) content.getAncestor(i);
223 if (nodeTypeName == null) {
224 ancestors.add(possibleAncestor);
225 } else {
226 if (possibleAncestor.isNodeType(nodeTypeName)) {
227 ancestors.add(possibleAncestor);
228 }
229 }
230 }
231 return ancestors;
232 }
233
234 public Node inherit(Node content) throws RepositoryException {
235 return inherit(content, null);
236 }
237
238 public Node inherit(Node content, String relPath) throws RepositoryException {
239 if (content == null) {
240 return null;
241 }
242 Node inheritedNode = wrapForInheritance(content);
243
244 if (StringUtils.isBlank(relPath)) {
245 return inheritedNode;
246 }
247
248 try {
249 Node subNode = inheritedNode.getNode(relPath);
250 return NodeUtil.unwrap(subNode);
251 } catch (PathNotFoundException e) {
252
253 }
254 return null;
255 }
256
257 public ContentMap inherit(ContentMap content) throws RepositoryException {
258 return inherit(content, null);
259 }
260
261 public ContentMap inherit(ContentMap content, String relPath) throws RepositoryException {
262 if (content == null) {
263 return null;
264 }
265 Node node = inherit(content.getJCRNode(), relPath);
266 return node == null ? null : new ContentMap(node);
267 }
268
269
270 public Property inheritProperty(Node content, String relPath) throws RepositoryException {
271 if (content == null) {
272 return null;
273 }
274 if (StringUtils.isBlank(relPath)) {
275 throw new IllegalArgumentException("relative path cannot be null or empty");
276 }
277 try {
278 Node inheritedNode = wrapForInheritance(content);
279 return inheritedNode.getProperty(relPath);
280
281 } catch (PathNotFoundException e) {
282
283 } catch (RepositoryException e) {
284
285 }
286
287 return null;
288 }
289
290 public Property inheritProperty(ContentMap content, String relPath) throws RepositoryException {
291 if (content == null) {
292 return null;
293 }
294 return inheritProperty(content.getJCRNode(), relPath);
295 }
296
297 public List<Node> inheritList(Node content, String relPath) throws RepositoryException {
298 if (content == null) {
299 return null;
300 }
301 if (StringUtils.isBlank(relPath)) {
302 throw new IllegalArgumentException("relative path cannot be null or empty");
303 }
304 Node inheritedNode = wrapForInheritance(content);
305 Node subNode = inheritedNode.getNode(relPath);
306 return children(subNode);
307 }
308
309 public List<ContentMap> inheritList(ContentMap content, String relPath) throws RepositoryException {
310 if (content == null) {
311 return null;
312 }
313 if (StringUtils.isBlank(relPath)) {
314 throw new IllegalArgumentException("relative path cannot be null or empty");
315 }
316 Node node = asJCRNode(content);
317 Node inheritedNode = wrapForInheritance(node);
318 Node subNode = inheritedNode.getNode(relPath);
319 return children(new ContentMap(subNode));
320 }
321
322 public boolean isInherited(Node content) {
323 if (content instanceof InheritanceNodeWrapper) {
324 return ((InheritanceNodeWrapper) content).isInherited();
325 }
326 return false;
327 }
328
329 public boolean isInherited(ContentMap content) {
330 return isInherited(asJCRNode(content));
331 }
332
333 public boolean isFromCurrentPage(Node content) {
334 return !isInherited(content);
335 }
336
337 public boolean isFromCurrentPage(ContentMap content) {
338 return isFromCurrentPage(asJCRNode(content));
339 }
340
341
342
343
344 public String link(String workspace, String nodeIdentifier) {
345 try {
346 return LinkUtil.createLink(workspace, nodeIdentifier);
347 } catch (RepositoryException e) {
348 return null;
349 }
350 }
351
352
353
354
355
356 public String link(Property property) {
357
358 try {
359 Node parentNode = null;
360 String propertyName = null;
361 if (property.getType() == PropertyType.BINARY) {
362 parentNode = property.getParent().getParent();
363 propertyName = property.getParent().getName();
364 } else {
365 parentNode = property.getParent();
366 propertyName = property.getName();
367 }
368 NodeData equivNodeData = ContentUtil.asContent(parentNode).getNodeData(propertyName);
369 return LinkUtil.createLink(equivNodeData);
370 } catch (Exception e) {
371 return null;
372 }
373 }
374
375
376
377 public String link(Node content) {
378 return content == null ? null : LinkUtil.createLink(ContentUtil.asContent(content));
379 }
380
381 public String link(ContentMap contentMap) throws RepositoryException {
382 return contentMap == null ? null : this.link(asJCRNode(contentMap));
383 }
384
385
386
387
388
389 public String language(){
390 return I18nContentSupportFactory.getI18nSupport().getLocale().toString();
391 }
392
393
394
395
396
397
398
399
400 public String externalLink(Node content, String linkPropertyName) {
401 String externalLink = PropertyUtil.getString(content, linkPropertyName);
402 if (StringUtils.isBlank(externalLink)) {
403 return StringUtils.EMPTY;
404 }
405 if (!hasProtocol(externalLink)) {
406 externalLink = "http://" + externalLink;
407 }
408 return externalLink;
409 }
410
411
412
413
414
415
416
417
418
419 public String externalLink(ContentMap content, String linkPropertyName) {
420 return externalLink(asJCRNode(content), linkPropertyName);
421 }
422
423
424
425
426
427
428
429
430
431
432 public String externalLinkTitle(Node content, String linkPropertyName, String linkTitlePropertyName) {
433 String linkTitle = PropertyUtil.getString(content, linkTitlePropertyName);
434 if (StringUtils.isNotEmpty(linkTitle)) {
435 return linkTitle;
436 }
437 return externalLink(content, linkPropertyName);
438 }
439
440
441
442
443
444
445
446
447
448
449 public String externalLinkTitle(ContentMap content, String linkPropertyName, String linkTitlePropertyName) {
450 return externalLinkTitle(asJCRNode(content), linkPropertyName, linkTitlePropertyName);
451 }
452
453 public boolean isEditMode() {
454
455 return isAuthorInstance() && !isPreviewMode();
456 }
457
458 public boolean isPreviewMode() {
459 return this.aggregationStateProvider.get().isPreviewMode();
460 }
461
462 public boolean isAuthorInstance() {
463 return Components.getComponent(ServerConfiguration.class).isAdmin();
464 }
465
466 public boolean isPublicInstance() {
467 return !isAuthorInstance();
468 }
469
470
471
472
473
474 public String createHtmlAttribute(String name, String value) {
475 value = StringUtils.trim(value);
476 if (StringUtils.isNotEmpty(value)) {
477 return new StringBuffer().append(name).append("=\"").append(value).append("\"").toString();
478 }
479 return StringUtils.EMPTY;
480 }
481
482
483
484
485 public SiblingsHelper siblings(Node node) throws RepositoryException {
486 return SiblingsHelper.of(ContentUtil.asContent(node));
487 }
488
489 public SiblingsHelper siblings(ContentMap node) throws RepositoryException {
490 return siblings(asJCRNode(node));
491 }
492
493
494
495
496
497 public Node content(String path){
498 return content(RepositoryConstants.WEBSITE, path);
499 }
500
501
502
503
504
505 public Node content(String repository, String path){
506 return SessionUtil.getNode(repository, path);
507 }
508
509 public List<ContentMap> asContentMapList(Collection<Node> nodeList) {
510 if (nodeList != null) {
511 List<ContentMap> contentMapList = new ArrayList<ContentMap>();
512 for (Node node : nodeList) {
513 contentMapList.add(asContentMap(node));
514 }
515 return contentMapList;
516 }
517 return null;
518 }
519
520 public List<Node> asNodeList(Collection<ContentMap> contentMapList) {
521 if (contentMapList != null) {
522 List<Node> nodeList = new ArrayList<Node>();
523 for (ContentMap node : contentMapList) {
524 nodeList.add(node.getJCRNode());
525 }
526 return nodeList;
527 }
528 return null;
529 }
530
531
532 protected List<Node> asNodeList(Iterable<Node> nodes) {
533 List<Node> childList = new ArrayList<Node>();
534 for (Node child : nodes) {
535 childList.add(child);
536 }
537 return childList;
538 }
539
540
541 protected List<ContentMap> asContentMapList(Iterable<Node> nodes) {
542 List<ContentMap> childList = new ArrayList<ContentMap>();
543 for (Node child : nodes) {
544 childList.add(new ContentMap(child));
545 }
546 return childList;
547 }
548
549
550
551
552
553
554
555 private boolean hasProtocol(String link) {
556 return link != null && link.contains("://");
557 }
558
559
560
561
562
563
564
565 private boolean isRoot(Node content) throws RepositoryException {
566 return content.getDepth() == 0;
567 }
568
569
570
571
572 public ContentMap decode(ContentMap content){
573 return asContentMap(decode(content.getJCRNode()));
574 }
575
576
577
578
579 public Node decode(Node content){
580 return NodeUtil.deepUnwrap(content, HTMLEscapingNodeWrapper.class);
581 }
582
583
584
585
586 public Node encode(Node content){
587 return content != null ? new HTMLEscapingNodeWrapper(content, true) : null;
588 }
589
590 private Node wrapForInheritance(Node destination) throws RepositoryException {
591 ConfiguredInheritance inheritanceConfiguration = new ConfiguredInheritance();
592 inheritanceConfiguration.setEnabled(true);
593 return new DefaultInheritanceContentDecorator(destination, inheritanceConfiguration).wrapNode(destination);
594 }
595
596
597
598
599 public String metaData(Node content, String property){
600 try {
601 if(content.hasNode(MetaData.DEFAULT_META_NODE)){
602 Node node = content.getNode(MetaData.DEFAULT_META_NODE);
603 if(node.hasProperty(property)) {
604 return PropertyUtil.getProperty(node, property).getString();
605 } else if(node.hasProperty(RepositoryConstants.NAMESPACE_PREFIX + ":" + property)) {
606 return PropertyUtil.getProperty(node, RepositoryConstants.NAMESPACE_PREFIX + ":" + property).getString();
607 }
608 }
609 } catch (RepositoryException e) {
610 throw new RuntimeException(e);
611 }
612 return null;
613 }
614
615
616
617
618 public String metaData(ContentMap content, String property){
619 return metaData(content.getJCRNode(), property);
620 }
621 }