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