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