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.beans.config.URI2RepositoryManager;
38 import info.magnolia.cms.core.AggregationState;
39 import info.magnolia.cms.core.NodeData;
40 import info.magnolia.cms.i18n.I18nContentSupport;
41 import info.magnolia.cms.util.ContentUtil;
42 import info.magnolia.cms.util.PathUtil;
43 import info.magnolia.cms.util.QueryUtil;
44 import info.magnolia.cms.util.SelectorUtil;
45 import info.magnolia.cms.util.SiblingsHelper;
46 import info.magnolia.context.MgnlContext;
47 import info.magnolia.context.WebContext;
48 import info.magnolia.context.HTMLEscapingWebContextWrapper;
49 import info.magnolia.jcr.inheritance.InheritanceNodeWrapper;
50 import info.magnolia.jcr.util.ContentMap;
51 import info.magnolia.jcr.util.MetaDataUtil;
52 import info.magnolia.jcr.util.NodeTypes;
53 import info.magnolia.jcr.util.NodeUtil;
54 import info.magnolia.jcr.util.PropertyUtil;
55 import info.magnolia.jcr.util.SessionUtil;
56 import info.magnolia.jcr.wrapper.HTMLEscapingContentDecorator;
57 import info.magnolia.jcr.wrapper.HTMLEscapingNodeWrapper;
58 import info.magnolia.jcr.wrapper.I18nNodeWrapper;
59 import info.magnolia.link.LinkUtil;
60 import info.magnolia.objectfactory.Components;
61 import info.magnolia.rendering.engine.RenderingEngine;
62 import info.magnolia.rendering.template.configured.ConfiguredInheritance;
63 import info.magnolia.rendering.template.type.DefaultTemplateTypes;
64 import info.magnolia.rendering.template.type.TemplateTypeHelper;
65 import info.magnolia.repository.RepositoryConstants;
66 import info.magnolia.templating.inheritance.DefaultInheritanceContentDecorator;
67 import info.magnolia.templating.inspector.Inspector;
68 import info.magnolia.util.EscapeUtil;
69
70 import java.net.URI;
71 import java.net.URISyntaxException;
72 import java.util.ArrayList;
73 import java.util.Arrays;
74 import java.util.Calendar;
75 import java.util.Collection;
76 import java.util.Collections;
77 import java.util.LinkedHashMap;
78 import java.util.List;
79 import java.util.Locale;
80 import java.util.Map;
81 import java.util.Set;
82
83 import javax.inject.Inject;
84 import javax.inject.Provider;
85 import javax.jcr.Node;
86 import javax.jcr.PathNotFoundException;
87 import javax.jcr.Property;
88 import javax.jcr.PropertyType;
89 import javax.jcr.RepositoryException;
90
91 import org.apache.commons.io.FileUtils;
92 import org.apache.commons.lang3.StringUtils;
93 import org.apache.jackrabbit.util.ISO8601;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
96
97
98
99
100 public class TemplatingFunctions {
101
102 private static final Logger log = LoggerFactory.getLogger(TemplatingFunctions.class);
103
104 private final Provider<WebContext> webContextProvider;
105 private final TemplateTypeHelper templateTypeHelper;
106 private final Provider<I18nContentSupport> i18nContentSupport;
107
108 @Inject
109 public TemplatingFunctions(TemplateTypeHelper templateTypeFunctions, Provider<I18nContentSupport> i18nContentSupport, Provider<WebContext> webContextProvider) {
110 this.webContextProvider = webContextProvider;
111 this.templateTypeHelper = templateTypeFunctions;
112 this.i18nContentSupport = i18nContentSupport;
113 }
114
115
116
117
118 @Deprecated
119 public TemplatingFunctions(Provider<AggregationState> aggregationStateProvider, TemplateTypeHelper templateTypeFunctions, Provider<I18nContentSupport> i18nContentSupport) {
120 this(templateTypeFunctions, i18nContentSupport, new Provider<WebContext>() {
121 @Override
122 public WebContext get() {
123 return Components.getComponent(WebContext.class);
124 }
125 });
126 }
127
128
129
130
131 @Deprecated
132 public TemplatingFunctions(Provider<AggregationState> aggregationStateProvider, TemplateTypeHelper templateTypeFunctions) {
133 this(templateTypeFunctions, new Provider<I18nContentSupport>() {
134 @Override
135 public I18nContentSupport get() {
136 return Components.getComponent(I18nContentSupport.class);
137 }
138 }, new Provider<WebContext>() {
139 @Override
140 public WebContext get() {
141 return Components.getComponent(WebContext.class);
142 }
143 });
144 }
145
146
147
148
149 @Deprecated
150 public TemplatingFunctions(Provider<AggregationState> aggregationStateProvider) {
151 this(Components.getComponent(TemplateTypeHelper.class), new Provider<I18nContentSupport>() {
152 @Override
153 public I18nContentSupport get() {
154 return Components.getComponent(I18nContentSupport.class);
155 }
156 }, new Provider<WebContext>() {
157 @Override
158 public WebContext get() {
159 return Components.getComponent(WebContext.class);
160 }
161 });
162 }
163
164
165
166
167
168 public Node asJCRNode(ContentMap contentMap) {
169 return contentMap == null ? null : contentMap.getJCRNode();
170 }
171
172
173
174
175
176 public ContentMap asContentMap(Node content) {
177 return content == null ? null : new ContentMap(content);
178 }
179
180
181
182
183 public List<Node> children(Node content) throws RepositoryException {
184 return content == null ? null : asNodeList(NodeUtil.getNodes(content, NodeUtil.EXCLUDE_META_DATA_FILTER));
185 }
186
187
188
189
190 public List<Node> children(Node content, String nodeTypeName) throws RepositoryException {
191 return content == null ? null : asNodeList(NodeUtil.getNodes(content, nodeTypeName));
192 }
193
194
195
196
197 public List<ContentMap> children(ContentMap content) throws RepositoryException {
198 return content == null ? null : asContentMapList(NodeUtil.getNodes(asJCRNode(content), NodeUtil.EXCLUDE_META_DATA_FILTER));
199 }
200
201
202
203
204 public List<ContentMap> children(ContentMap content, String nodeTypeName) throws RepositoryException {
205 return content == null ? null : asContentMapList(NodeUtil.getNodes(asJCRNode(content), nodeTypeName));
206 }
207
208
209
210
211 public ContentMap root(ContentMap contentMap) throws RepositoryException {
212 return contentMap == null ? null : asContentMap(this.root(contentMap.getJCRNode()));
213 }
214
215
216
217
218 public ContentMap root(ContentMap contentMap, String nodeTypeName) throws RepositoryException {
219 return contentMap == null ? null : asContentMap(this.root(contentMap.getJCRNode(), nodeTypeName));
220 }
221
222
223
224
225 public Node root(Node content) throws RepositoryException {
226 return this.root(content, null);
227 }
228
229
230
231
232 public Node root(Node content, String nodeTypeName) throws RepositoryException {
233 if (content == null) {
234 return null;
235 }
236 if (nodeTypeName == null) {
237 return (Node) content.getAncestor(0);
238 }
239 if (isRoot(content) && content.isNodeType(nodeTypeName)) {
240 return content;
241 }
242
243 Node parentNode = this.parent(content, nodeTypeName);
244 while (parent(parentNode, nodeTypeName) != null) {
245 parentNode = this.parent(parentNode, nodeTypeName);
246 }
247 return parentNode;
248 }
249
250
251
252
253 public ContentMap parent(ContentMap contentMap) throws RepositoryException {
254 return contentMap == null ? null : asContentMap(this.parent(contentMap.getJCRNode()));
255 }
256
257
258
259
260 public ContentMap parent(ContentMap contentMap, String nodeTypeName) throws RepositoryException {
261 return contentMap == null ? null : asContentMap(this.parent(contentMap.getJCRNode(), nodeTypeName));
262 }
263
264
265
266
267 public Node parent(Node content) throws RepositoryException {
268 return this.parent(content, null);
269 }
270
271
272
273
274
275 public Node parent(Node content, String nodeTypeName) throws RepositoryException {
276 if (content == null) {
277 return null;
278 }
279 if (isRoot(content)) {
280 return null;
281 }
282 if (nodeTypeName == null) {
283 return content.getParent();
284 }
285 Node parent = content.getParent();
286 while (!parent.isNodeType(nodeTypeName)) {
287 if (isRoot(parent)) {
288 return null;
289 }
290 parent = parent.getParent();
291 }
292 return parent;
293 }
294
295
296
297
298
299
300
301
302 public ContentMap page(ContentMap content) throws RepositoryException {
303 return content == null ? null : asContentMap(page(content.getJCRNode()));
304 }
305
306
307
308
309
310
311
312
313 public Node page(Node content) throws RepositoryException {
314 if (content == null) {
315 return null;
316 }
317 if (content.isNodeType(NodeTypes.Page.NAME)) {
318 return content;
319 }
320 return parent(content, NodeTypes.Page.NAME);
321 }
322
323
324
325
326 public List<ContentMap> ancestors(ContentMap contentMap) throws RepositoryException {
327 return ancestors(contentMap, null);
328 }
329
330
331
332
333 public List<ContentMap> ancestors(ContentMap contentMap, String nodeTypeName) throws RepositoryException {
334 List<Node> ancestorsAsNodes = this.ancestors(contentMap.getJCRNode(), nodeTypeName);
335 return asContentMapList(ancestorsAsNodes);
336 }
337
338
339
340
341
342 public List<Node> ancestors(Node content) throws RepositoryException {
343 return content == null ? null : this.ancestors(content, null);
344 }
345
346
347
348
349
350 public List<Node> ancestors(Node content, String nodeTypeName) throws RepositoryException {
351 if (content == null) {
352 return null;
353 }
354 List<Node> ancestors = new ArrayList<Node>();
355 int depth = content.getDepth();
356 for (int i = 1; i < depth; ++i) {
357 Node possibleAncestor = (Node) content.getAncestor(i);
358 if (nodeTypeName == null) {
359 ancestors.add(possibleAncestor);
360 } else {
361 if (possibleAncestor.isNodeType(nodeTypeName)) {
362 ancestors.add(possibleAncestor);
363 }
364 }
365 }
366 return ancestors;
367 }
368
369
370
371
372
373
374
375
376
377 public Node inherit(Node content) throws RepositoryException {
378 return inherit(content, null);
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392 public Node inherit(Node content, String relPath) throws RepositoryException {
393 return inherit(content, relPath, StringUtils.EMPTY, ConfiguredInheritance.COMPONENTS_FILTERED, ConfiguredInheritance.PROPERTIES_ALL);
394 }
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427 public Node inherit(Node content, String relPath, String nodeTypes, String nodeInheritance, String propertyInheritance) throws RepositoryException {
428 if (content == null) {
429 return null;
430 }
431
432 ConfiguredInheritance configuredInheritance = new ConfiguredInheritance();
433 if (StringUtils.isNotEmpty(nodeTypes)) {
434 configuredInheritance.setNodeTypes(Arrays.asList(StringUtils.split(nodeTypes, ",")));
435 }
436 if (StringUtils.isNotEmpty(nodeInheritance)) {
437 configuredInheritance.setComponents(nodeInheritance);
438 }
439 if (StringUtils.isNotEmpty(propertyInheritance)) {
440 configuredInheritance.setProperties(propertyInheritance);
441 }
442
443 Node inheritedNode = wrapForInheritance(content, configuredInheritance);
444
445 if (StringUtils.isBlank(relPath)) {
446 return inheritedNode;
447 }
448
449 try {
450 Node subNode = inheritedNode.getNode(relPath);
451 return NodeUtil.unwrap(subNode);
452 } catch (PathNotFoundException e) {
453
454 }
455 return null;
456 }
457
458
459
460
461 public ContentMap inherit(ContentMap content) throws RepositoryException {
462 return inherit(content, null);
463 }
464
465
466
467
468 public ContentMap inherit(ContentMap content, String relPath) throws RepositoryException {
469 if (content == null) {
470 return null;
471 }
472 Node node = inherit(content.getJCRNode(), relPath);
473 return node == null ? null : new ContentMap(node);
474 }
475
476
477
478
479 public ContentMap inherit(ContentMap content, String relPath, String nodeTypes, String nodeInheritance, String propertyInheritance) throws RepositoryException {
480 if (content == null) {
481 return null;
482 }
483 Node node = inherit(content.getJCRNode(), relPath, nodeTypes, nodeInheritance, propertyInheritance);
484 return node == null ? null : new ContentMap(node);
485 }
486
487
488
489
490
491
492
493
494 public Property inheritProperty(Node content, String relPath) throws RepositoryException {
495 if (content == null) {
496 return null;
497 }
498 if (StringUtils.isBlank(relPath)) {
499 throw new IllegalArgumentException("relative path cannot be null or empty");
500 }
501 try {
502 Node inheritedNode = wrapForInheritance(content, new ConfiguredInheritance());
503 return inheritedNode.getProperty(relPath);
504
505 } catch (PathNotFoundException e) {
506
507 } catch (RepositoryException e) {
508
509 }
510
511 return null;
512 }
513
514
515
516
517 public Property inheritProperty(ContentMap content, String relPath) throws RepositoryException {
518 if (content == null) {
519 return null;
520 }
521 return inheritProperty(content.getJCRNode(), relPath);
522 }
523
524
525
526
527 public List<Node> inheritList(Node content, String relPath) throws RepositoryException {
528 if (content == null) {
529 return null;
530 }
531 if (StringUtils.isBlank(relPath)) {
532 throw new IllegalArgumentException("Relative path cannot be null or empty");
533 }
534 Node inheritedNode = wrapForInheritance(content, new ConfiguredInheritance());
535 Node subNode = inheritedNode.getNode(relPath);
536 return children(subNode);
537 }
538
539
540
541
542 public List<ContentMap> inheritList(ContentMap content, String relPath) throws RepositoryException {
543 if (content == null) {
544 return null;
545 }
546 if (StringUtils.isBlank(relPath)) {
547 throw new IllegalArgumentException("Relative path cannot be null or empty");
548 }
549 Node node = asJCRNode(content);
550 Node inheritedNode = wrapForInheritance(node, new ConfiguredInheritance());
551 Node subNode = inheritedNode.getNode(relPath);
552 return children(new ContentMap(subNode));
553 }
554
555
556
557
558 public boolean isInherited(Node content) {
559 if (content instanceof InheritanceNodeWrapper) {
560 return ((InheritanceNodeWrapper) content).isInherited();
561 }
562 return false;
563 }
564
565
566
567
568 public boolean isInherited(ContentMap content) {
569 return isInherited(asJCRNode(content));
570 }
571
572
573
574
575
576 public boolean isFromCurrentPage(Node content) {
577 return !isInherited(content);
578 }
579
580
581
582
583 public boolean isFromCurrentPage(ContentMap content) {
584 return isFromCurrentPage(asJCRNode(content));
585 }
586
587
588
589
590
591 public String link(String workspace, String nodeIdentifier) {
592 try {
593 return LinkUtil.createLink(workspace, nodeIdentifier);
594 } catch (RepositoryException e) {
595 handleRepositoryException(e, workspace);
596 return null;
597 }
598 }
599
600
601
602
603
604
605
606
607 @Deprecated
608 public String link(Property property) {
609 try {
610 Node parentNode = null;
611 String propertyName = null;
612 if (property.getType() == PropertyType.BINARY) {
613 parentNode = property.getParent().getParent();
614 propertyName = property.getParent().getName();
615 } else {
616 parentNode = property.getParent();
617 propertyName = property.getName();
618 }
619 NodeData equivNodeData = ContentUtil.asContent(parentNode).getNodeData(propertyName);
620 return LinkUtil.createLink(equivNodeData);
621 } catch (Exception e) {
622 return null;
623 }
624 }
625
626
627
628
629
630 public String link(Node content) {
631 return content == null ? null : LinkUtil.createLink(content);
632 }
633
634
635
636
637 public String link(ContentMap contentMap) throws RepositoryException {
638 return contentMap == null ? null : this.link(asJCRNode(contentMap));
639 }
640
641 public String linkPrefix(Node content) {
642 if (!MgnlContext.isWebContext()) {
643 return MgnlContext.getContextPath();
644 }
645 String fullLinkToPage = link(content);
646 String pagePath = Components.getComponent(URI2RepositoryManager.class).getURI(LinkUtil.createLinkInstance(content));
647 int ndx = fullLinkToPage.length();
648 for (int cnt = StringUtils.countMatches(pagePath, "/"); cnt > 0; cnt--) {
649 ndx = fullLinkToPage.lastIndexOf('/', ndx - 1);
650 }
651 String linkPrefix = fullLinkToPage.substring(0, ndx);
652 return linkPrefix;
653 }
654
655
656
657
658 public String linkPrefix(ContentMap content) {
659 return linkPrefix(asJCRNode(content));
660 }
661
662
663
664
665
666
667 @Deprecated
668 public String getQueryStringAndFragment(String url) {
669 return queryStringAndFragment(url);
670 }
671
672
673
674
675 public String queryStringAndFragment(String url) {
676 String result = StringUtils.EMPTY;
677 try {
678 URI uri = new URI(url);
679 String query = uri.getQuery();
680 String fragment = uri.getFragment();
681
682 if (StringUtils.isNotEmpty(query)) {
683 result += "?" + query;
684 }
685 if (StringUtils.isNotEmpty(fragment)) {
686 result += "#" + fragment;
687 }
688 } catch (URISyntaxException e) {
689 log.warn("URL cannot be parsed. {0}, {1}", url, e.getMessage());
690 return StringUtils.EMPTY;
691 }
692 return result;
693 }
694
695
696
697
698
699
700 public String language() {
701 return i18nContentSupport.get().getLocale().toString();
702 }
703
704
705
706
707
708
709
710
711
712 public String externalLink(Node content, String linkPropertyName) {
713 String externalLink = PropertyUtil.getString(content, linkPropertyName);
714 if (StringUtils.isBlank(externalLink)) {
715 return StringUtils.EMPTY;
716 }
717
718 if (!hasProtocol(externalLink) && !externalLink.startsWith("#")) {
719 externalLink = "http://" + externalLink;
720 }
721 return EscapeUtil.escapeXss(externalLink);
722 }
723
724
725
726
727
728
729
730
731
732 public String externalLink(ContentMap content, String linkPropertyName) {
733 return externalLink(asJCRNode(content), linkPropertyName);
734 }
735
736
737
738
739
740
741
742
743
744
745 public String externalLinkTitle(Node content, String linkPropertyName, String linkTitlePropertyName) {
746 String linkTitle = PropertyUtil.getString(content, linkTitlePropertyName);
747 if (StringUtils.isNotEmpty(linkTitle)) {
748 return linkTitle;
749 }
750 return externalLink(content, linkPropertyName);
751 }
752
753
754
755
756
757
758
759
760
761
762 public String externalLinkTitle(ContentMap content, String linkPropertyName, String linkTitlePropertyName) {
763 return externalLinkTitle(asJCRNode(content), linkPropertyName, linkTitlePropertyName);
764 }
765
766
767
768
769
770
771 public boolean isEditMode() {
772
773 return isAuthorInstance() && !isPreviewMode();
774 }
775
776
777
778
779 public boolean isPreviewMode() {
780 return this.webContextProvider.get().getAggregationState().isPreviewMode();
781 }
782
783
784
785
786 public boolean isAuthorInstance() {
787 return Components.getComponent(ServerConfiguration.class).isAdmin();
788 }
789
790
791
792
793 public boolean isPublicInstance() {
794 return !isAuthorInstance();
795 }
796
797
798
799
800
801 public String createHtmlAttribute(String name, String value) {
802 value = StringUtils.trim(value);
803 if (StringUtils.isNotEmpty(value)) {
804 return new StringBuffer().append(name).append("=\"").append(value).append("\"").toString();
805 }
806 return StringUtils.EMPTY;
807 }
808
809
810
811
812 public SiblingsHelper siblings(Node node) throws RepositoryException {
813 return SiblingsHelper.of(ContentUtil.asContent(node));
814 }
815
816 public SiblingsHelper siblings(ContentMap node) throws RepositoryException {
817 return siblings(asJCRNode(node));
818 }
819
820
821
822
823
824
825 @Deprecated
826 public Node content(String path) {
827 return content(RepositoryConstants.WEBSITE, path);
828 }
829
830
831
832
833
834
835 @Deprecated
836 public Node content(String repository, String path) {
837 return SessionUtil.getNode(repository, path);
838 }
839
840
841
842
843
844
845 @Deprecated
846 public Node contentByIdentifier(String id) {
847 return contentByIdentifier(RepositoryConstants.WEBSITE, id);
848 }
849
850
851
852
853
854
855 @Deprecated
856 public Node contentByIdentifier(String repository, String id) {
857 return SessionUtil.getNodeByIdentifier(repository, id);
858 }
859
860
861
862
863 public ContentMap contentByPath(String path) {
864 return contentByPath(path, RepositoryConstants.WEBSITE);
865 }
866
867
868
869
870 public ContentMap contentByPath(String path, String workspace) {
871 return asContentMap(nodeByPath(path, workspace));
872 }
873
874
875
876
877 public ContentMap contentById(String id) {
878 return contentById(id, RepositoryConstants.WEBSITE);
879 }
880
881
882
883
884 public ContentMap contentById(String id, String workspace) {
885 return asContentMap(nodeById(id, workspace));
886 }
887
888
889
890
891 public Node nodeByPath(String path) {
892 return nodeByPath(path, RepositoryConstants.WEBSITE);
893 }
894
895
896
897
898 public Node nodeByPath(String path, String workspace) {
899 try {
900 String pathToNode = new URI(path).getPath();
901 return webContextProvider.get().getJCRSession(workspace).getNode(pathToNode);
902 } catch (URISyntaxException e) {
903 log.warn("Path cannot be parsed. {0}, {1}", path, e.getMessage());
904 return null;
905 } catch (RepositoryException e) {
906 handleRepositoryException(e, workspace);
907 return null;
908 }
909 }
910
911
912
913
914 public Node nodeById(String id) {
915 return nodeById(id, RepositoryConstants.WEBSITE);
916 }
917
918
919
920
921 public Node nodeById(String id, String workspace) {
922 try {
923 return webContextProvider.get().getJCRSession(workspace).getNodeByIdentifier(id);
924 } catch (RepositoryException e) {
925 handleRepositoryException(e, workspace);
926 return null;
927 }
928 }
929
930 private void handleRepositoryException(RepositoryException e, String workspace) {
931 final AggregationState aggregationState = webContextProvider.get().getAggregationState();
932 String template;
933 try {
934 template = NodeTypes.Renderable.getTemplate(aggregationState.getCurrentContentNode());
935 } catch (RepositoryException e1) {
936 template = "unknown";
937 }
938 log.debug("Exception in '{}' workspace when rendering template '{}' for URI '{}': {}", workspace, template, aggregationState.getOriginalBrowserURI(), e);
939
940 }
941
942
943
944
945
946
947
948
949
950
951 public Node contentByReference(Node content, String idPropertyName, String referencedWorkspace) throws RepositoryException {
952 if (content.hasProperty(idPropertyName)) {
953 final String identifier = PropertyUtil.getString(content, idPropertyName);
954 final Node node = NodeUtil.getNodeByIdentifier(referencedWorkspace, identifier);
955 return encode(wrapForI18n(node));
956 }
957 return null;
958 }
959
960
961
962
963 public ContentMap contentByReference(ContentMap content, String idPropertyName, String referencedWorkspace) throws RepositoryException {
964 Node node = asJCRNode(content);
965 return asContentMap(contentByReference(node, idPropertyName, referencedWorkspace));
966 }
967
968
969
970
971
972 public List<ContentMap> asContentMapList(Collection<Node> nodeList) {
973 if (nodeList != null) {
974 List<ContentMap> contentMapList = new ArrayList<ContentMap>();
975 for (Node node : nodeList) {
976 contentMapList.add(asContentMap(node));
977 }
978 return contentMapList;
979 }
980 return null;
981 }
982
983
984
985
986
987 public List<Node> asNodeList(Collection<ContentMap> contentMapList) {
988 if (contentMapList != null) {
989 List<Node> nodeList = new ArrayList<Node>();
990 for (ContentMap node : contentMapList) {
991 nodeList.add(node.getJCRNode());
992 }
993 return nodeList;
994 }
995 return null;
996 }
997
998
999 protected List<Node> asNodeList(Iterable<Node> nodes) {
1000 List<Node> childList = new ArrayList<Node>();
1001 for (Node child : nodes) {
1002 childList.add(child);
1003 }
1004 return childList;
1005 }
1006
1007
1008 protected List<ContentMap> asContentMapList(Iterable<Node> nodes) {
1009 List<ContentMap> childList = new ArrayList<ContentMap>();
1010 for (Node child : nodes) {
1011 childList.add(new ContentMap(child));
1012 }
1013 return childList;
1014 }
1015
1016
1017
1018
1019
1020
1021
1022 private boolean hasProtocol(String link) {
1023 return link != null && link.contains("://");
1024 }
1025
1026
1027
1028
1029
1030
1031
1032 private boolean isRoot(Node content) throws RepositoryException {
1033 return content.getDepth() == 0;
1034 }
1035
1036
1037
1038
1039 public ContentMap decode(ContentMap content) {
1040 return asContentMap(decode(content.getJCRNode()));
1041 }
1042
1043
1044
1045
1046 public Node decode(Node content) {
1047 return NodeUtil.deepUnwrap(content, HTMLEscapingNodeWrapper.class);
1048 }
1049
1050
1051
1052
1053 public ContentMap encode(ContentMap content) {
1054 return content != null ? new ContentMap(new HTMLEscapingNodeWrapper(content.getJCRNode(), true)) : null;
1055 }
1056
1057
1058
1059
1060 public Node encode(Node content) {
1061 return content != null ? new HTMLEscapingNodeWrapper(content, true) : null;
1062 }
1063
1064
1065
1066
1067 public String encode(String text) {
1068 return new HTMLEscapingContentDecorator(true).decorate(text);
1069 }
1070
1071
1072
1073
1074 public Node wrapForI18n(Node content) {
1075 return content != null ? new I18nNodeWrapper(content) : null;
1076 }
1077
1078
1079
1080
1081 public ContentMap wrapForI18n(ContentMap content) {
1082 return content != null ? new ContentMap(wrapForI18n(content.getJCRNode())) : null;
1083 }
1084
1085
1086
1087
1088
1089 private Node wrapForInheritance(Node destination, ConfiguredInheritance configuredInheritance) throws RepositoryException {
1090 configuredInheritance.setEnabled(true);
1091 return new DefaultInheritanceContentDecorator(destination, configuredInheritance).wrapNode(destination);
1092 }
1093
1094
1095
1096
1097 public String metaData(Node content, String property) {
1098
1099 Object returnValue;
1100 try {
1101 if (property.equals(NodeTypes.Created.CREATED)) {
1102 returnValue = NodeTypes.Created.getCreated(content);
1103 } else if (property.equals(NodeTypes.Created.CREATED_BY)) {
1104 returnValue = NodeTypes.Created.getCreatedBy(content);
1105 } else if (property.equals(NodeTypes.LastModified.LAST_MODIFIED)) {
1106 returnValue = NodeTypes.LastModified.getLastModified(content);
1107 } else if (property.equals(NodeTypes.LastModified.LAST_MODIFIED_BY)) {
1108 returnValue = NodeTypes.LastModified.getLastModifiedBy(content);
1109 } else if (property.equals(NodeTypes.Renderable.TEMPLATE)) {
1110 returnValue = NodeTypes.Renderable.getTemplate(content);
1111 } else if (property.equals(NodeTypes.Activatable.LAST_ACTIVATED)) {
1112 returnValue = NodeTypes.Activatable.getLastActivated(content);
1113 } else if (property.equals(NodeTypes.Activatable.LAST_ACTIVATED_BY)) {
1114 returnValue = NodeTypes.Activatable.getLastActivatedBy(content);
1115 } else if (property.equals(NodeTypes.Activatable.ACTIVATION_STATUS)) {
1116 returnValue = NodeTypes.Activatable.getActivationStatus(content);
1117 } else if (property.equals(NodeTypes.Deleted.DELETED)) {
1118 returnValue = NodeTypes.Deleted.getDeleted(content);
1119 } else if (property.equals(NodeTypes.Deleted.DELETED_BY)) {
1120 returnValue = NodeTypes.Deleted.getDeletedBy(content);
1121 } else if (property.equals(NodeTypes.Deleted.COMMENT)) {
1122
1123 returnValue = NodeTypes.Deleted.getComment(content);
1124 } else {
1125
1126
1127
1128 returnValue = MetaDataUtil.getMetaData(content).getStringProperty(property);
1129
1130
1131 log.warn("Deprecated constant [{}] used to query for meta data property on node [{}]", property, NodeUtil.getPathIfPossible(content));
1132 }
1133 } catch (RepositoryException e) {
1134 log.error("An error occured while trying to get [{}] property at [{}]", property, NodeUtil.getNodePathIfPossible(content), e);
1135 return null;
1136 }
1137
1138 return returnValue instanceof Calendar ? ISO8601.format((Calendar) returnValue) : returnValue != null ? returnValue.toString() : null;
1139 }
1140
1141
1142
1143
1144 public String metaData(ContentMap content, String property) {
1145 return metaData(content.getJCRNode(), property);
1146 }
1147
1148
1149
1150
1151
1152
1153
1154 @Deprecated
1155 public Collection<Node> search(String workspace, String statement, String language, String returnItemType) {
1156 try {
1157 return NodeUtil.getCollectionFromNodeIterator(QueryUtil.search(workspace, statement, language, returnItemType));
1158 } catch (Exception e) {
1159 log.error(e.getMessage(), e);
1160 }
1161 return null;
1162 }
1163
1164
1165
1166
1167
1168
1169
1170
1171 @Deprecated
1172 public Collection<Node> simpleSearch(String workspace, String statement, String returnItemType, String startPath) {
1173 if (StringUtils.isEmpty(statement)) {
1174 log.error("Cannot search with empty statement.");
1175 return null;
1176 }
1177 String query = QueryUtil.buildQuery(statement, startPath);
1178 try {
1179 return NodeUtil.getCollectionFromNodeIterator(QueryUtil.search(workspace, query, "JCR-SQL2", returnItemType));
1180 } catch (Exception e) {
1181 log.error(e.getMessage(), e);
1182 }
1183 return null;
1184 }
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195 public Node siteRoot(Node content) {
1196 return this.siteRoot(content, DefaultTemplateTypes.SITE_ROOT);
1197 }
1198
1199
1200
1201
1202 public ContentMap siteRoot(ContentMap content) {
1203 return this.siteRoot(content, DefaultTemplateTypes.SITE_ROOT);
1204 }
1205
1206
1207
1208
1209 public ContentMap siteRoot(ContentMap content, String siteRootTemplateType) {
1210 return asContentMap(siteRoot(content.getJCRNode(), siteRootTemplateType));
1211 }
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223 public Node siteRoot(Node content, String siteRootTemplateType) {
1224 if (siteRootTemplateType == null) {
1225 siteRootTemplateType = DefaultTemplateTypes.SITE_ROOT;
1226 }
1227 try {
1228 final Node page = page(content);
1229 final Node root = parentWithTemplateType(page, siteRootTemplateType);
1230 return (root == null) ? (Node) page.getAncestor(0) : root;
1231 } catch (RepositoryException e) {
1232 throw new RuntimeException("Can't access site root.", e);
1233 }
1234 }
1235
1236
1237
1238
1239
1240
1241
1242 public String templateType(Node pageNode) {
1243 return templateTypeHelper.getTemplateTypeOrDefault(pageNode);
1244 }
1245
1246
1247
1248
1249 public String templateType(ContentMap page) {
1250 return templateType(asJCRNode(page));
1251 }
1252
1253
1254
1255
1256
1257
1258
1259 public String templateSubtype(Node pageNode) {
1260 return templateTypeHelper.getTemplateSubtypeOrDefault(pageNode);
1261 }
1262
1263
1264
1265
1266 public String templateSubtype(ContentMap page) {
1267 return templateSubtype(asJCRNode(page));
1268 }
1269
1270
1271
1272
1273 public boolean hasTemplateOfType(Node pageNode, String templateType) {
1274 return templateTypeHelper.hasTemplateOfType(pageNode, templateType);
1275 }
1276
1277
1278
1279
1280 public boolean hasTemplateOfType(ContentMap page, String templateType) {
1281 return hasTemplateOfType(asJCRNode(page), templateType);
1282 }
1283
1284
1285
1286
1287 public Node parentWithTemplateType(Node pageNode, String templateType) throws RepositoryException {
1288 return templateTypeHelper.findParentWithTemplateType(pageNode, templateType);
1289 }
1290
1291
1292
1293
1294 public ContentMap parentWithTemplateType(ContentMap page, String templateType) throws RepositoryException {
1295 return asContentMap(parentWithTemplateType(asJCRNode(page), templateType));
1296 }
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308 public List<Node> contentListByTemplateType(Node searchRoot, String templateType, String templateSubtype, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
1309 return templateTypeHelper.getContentListByTemplateType(searchRoot, templateType, templateSubtype, maxResultSize, andClause, orderByClause);
1310 }
1311
1312
1313
1314
1315 public List<ContentMap> contentListByTemplateType(ContentMap searchRoot, String templateType, String templateSubtype, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
1316 return asContentMapList(contentListByTemplateType(asJCRNode(searchRoot), templateType, templateSubtype, maxResultSize, andClause, orderByClause));
1317 }
1318
1319
1320
1321
1322 public List<Node> contentListByTemplateType(Node siteRoot, String templateType, String templateSubtype) throws RepositoryException {
1323 return contentListByTemplateType(siteRoot, templateType, templateSubtype, Integer.MAX_VALUE, null, null);
1324 }
1325
1326
1327
1328
1329 public List<ContentMap> contentListByTemplateType(ContentMap siteRoot, String templateType, String templateSubtype) throws RepositoryException {
1330 return asContentMapList(contentListByTemplateType(asJCRNode(siteRoot), templateType, templateSubtype, Integer.MAX_VALUE, null, null));
1331 }
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342 public List<Node> contentListByTemplateIds(Node searchRoot, Set<String> templateIds, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
1343 return templateTypeHelper.getContentListByTemplateIds(searchRoot, templateIds, maxResultSize, andClause, orderByClause);
1344 }
1345
1346
1347
1348
1349 public List<ContentMap> contentListByTemplateIds(ContentMap searchRoot, Set<String> templateIds, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
1350 return asContentMapList(contentListByTemplateIds(asJCRNode(searchRoot), templateIds, maxResultSize, andClause, orderByClause));
1351 }
1352
1353
1354
1355
1356 public List<Node> contentListByTemplateId(Node searchRoot, String templateId) throws RepositoryException {
1357 return contentListByTemplateIds(searchRoot, Collections.singleton(templateId), Integer.MAX_VALUE, null, null);
1358 }
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369 public List<Node> contentListByTemplateId(Node searchRoot, String templateId, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
1370 return contentListByTemplateIds(searchRoot, Collections.singleton(templateId), maxResultSize, andClause, orderByClause);
1371 }
1372
1373
1374
1375
1376 public String abbreviateString(String stringToAbbreviate, int length, String suffix) {
1377 if (stringToAbbreviate == null) {
1378 return null;
1379 }
1380
1381 if (stringToAbbreviate.length() > length) {
1382 final int lengthMinusSuffix = length - suffix.length();
1383 String abbreviatedString = StringUtils.left(stringToAbbreviate, lengthMinusSuffix);
1384
1385
1386 String firstCharAfterCut = stringToAbbreviate.substring(lengthMinusSuffix, lengthMinusSuffix + 1);
1387 if (!" ".equals(firstCharAfterCut)) {
1388 abbreviatedString = StringUtils.substringBeforeLast(abbreviatedString, " ");
1389 }
1390
1391 return abbreviatedString + suffix;
1392 }
1393
1394 return stringToAbbreviate;
1395 }
1396
1397
1398
1399
1400 public String abbreviateString(String stringToAbbreviate, int length) {
1401 return abbreviateString(stringToAbbreviate, length, " ...");
1402 }
1403
1404
1405
1406
1407 public String fileExtension(String fileName) {
1408 return PathUtil.getExtension(fileName);
1409 }
1410
1411
1412
1413
1414
1415
1416 public String readableFileSize(long sizeBytes) {
1417 return FileUtils.byteCountToDisplaySize(sizeBytes);
1418 }
1419
1420
1421
1422
1423 public boolean isCurrentLocale(String language) {
1424 return StringUtils.equals(webContextProvider.get().getAggregationState().getLocale().toString(), language);
1425 }
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435 public Map<String, String> localizedLinks() throws RepositoryException {
1436 final Node currentNode = webContextProvider.get().getAggregationState().getCurrentContentNode();
1437
1438 return localizedLinks(currentNode);
1439 }
1440
1441
1442
1443
1444
1445
1446 public Map<String, String> localizedLinks(Node content) throws RepositoryException {
1447 final Node pageNode = page(content);
1448
1449 final String pageIdentifier = pageNode.getIdentifier();
1450 final Collection<Locale> locales = i18nContentSupport.get().getLocales();
1451 if (i18nContentSupport.get().isEnabled() && locales.size() > 1) {
1452 final Map<String, String> map = new LinkedHashMap<>();
1453 for (Locale locale : locales) {
1454 final String uri = createURI(pageIdentifier, locale);
1455
1456
1457 final String label = locale.toString();
1458 map.put(label, uri);
1459 }
1460 return map;
1461 }
1462
1463 return Collections.emptyMap();
1464 }
1465
1466 public String dump(Object obj) {
1467 return Inspector.dump(obj);
1468 }
1469
1470 public String dump(Object obj, int depth) {
1471 return Inspector.dump(obj, depth);
1472 }
1473
1474 public String dump(Object obj, int depth, boolean html) {
1475 return Inspector.dump(obj, depth, html);
1476 }
1477
1478
1479
1480
1481
1482
1483 private String createURI(final String identifier, final Locale locale) {
1484
1485
1486 final Locale currentLocale = i18nContentSupport.get().getLocale();
1487 String uri = null;
1488 final AggregationState aggregationState;
1489
1490 if (Components.getComponent(RenderingEngine.class).getEscapeHtml()) {
1491 aggregationState = new HTMLEscapingWebContextWrapper(webContextProvider.get()).getAggregationState();
1492 } else {
1493 aggregationState = webContextProvider.get().getAggregationState();
1494 }
1495 try {
1496 aggregationState.setLocale(locale);
1497 uri = LinkUtil.createAbsoluteLink(RepositoryConstants.WEBSITE, identifier);
1498 } catch (RepositoryException e) {
1499 log.error("Error creating a localized link to node with identifier {} for locale {}", identifier, locale.toString());
1500 } finally {
1501
1502 aggregationState.setLocale(currentLocale);
1503 }
1504
1505 final String selector = aggregationState.getSelector();
1506 if (StringUtils.isNotBlank(selector)) {
1507 final String defaultExtension = Components.getComponent(ServerConfiguration.class).getDefaultExtension();
1508 if (StringUtils.isNotBlank(defaultExtension)) {
1509 uri = StringUtils.substringBeforeLast(uri, "." + defaultExtension) + SelectorUtil.SELECTOR_DELIMITER + selector + SelectorUtil.SELECTOR_DELIMITER + "." + defaultExtension;
1510 } else {
1511 uri = uri + SelectorUtil.SELECTOR_DELIMITER + selector + SelectorUtil.SELECTOR_DELIMITER;
1512 }
1513 }
1514
1515 return uri;
1516 }
1517
1518 }