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.freemarker.models;
35
36 import static info.magnolia.jcr.util.NodeUtil.*;
37 import static java.util.stream.Collectors.toList;
38
39 import info.magnolia.jcr.util.ContentMap;
40
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.stream.Stream;
44
45 import javax.jcr.Node;
46 import javax.jcr.RepositoryException;
47
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import freemarker.template.AdapterTemplateModel;
52 import freemarker.template.ObjectWrapper;
53 import freemarker.template.SimpleCollection;
54 import freemarker.template.TemplateCollectionModel;
55 import freemarker.template.TemplateHashModelEx;
56 import freemarker.template.TemplateModel;
57 import freemarker.template.TemplateModelException;
58 import freemarker.template.TemplateNodeModel;
59 import freemarker.template.TemplateScalarModel;
60 import freemarker.template.TemplateSequenceModel;
61
62
63
64
65 public class ContentMapModel implements TemplateHashModelEx, TemplateNodeModel, TemplateScalarModel, AdapterTemplateModel {
66
67 private static final Logger log = LoggerFactory.getLogger(ContentMapModel.class);
68
69 static final MagnoliaModelFactoryelFactory.html#MagnoliaModelFactory">MagnoliaModelFactory FACTORY = new MagnoliaModelFactory() {
70 @Override
71 public Class factoryFor() {
72 return ContentMap.class;
73 }
74
75 @Override
76 public AdapterTemplateModel create(Object object, ObjectWrapper wrapper) {
77 return new ContentMapModel((ContentMap) object, (MagnoliaObjectWrapper) wrapper);
78 }
79 };
80
81 private final ContentMap content;
82 private final MagnoliaObjectWrapper wrapper;
83
84 ContentMapModel(ContentMap content, MagnoliaObjectWrapper wrapper) {
85 this.content = content;
86 this.wrapper = wrapper;
87 }
88
89 @Override
90 public String getAsString() {
91 return (String) content.get("@name");
92 }
93
94 @Override
95 public TemplateModel get(String key) throws TemplateModelException {
96 Object value = content.get(key);
97 if (value instanceof Node) {
98 return wrapper.wrap(new ContentMap((Node)value));
99 } else {
100 return wrapper.wrap(value);
101 }
102 }
103
104 @Override
105 public boolean isEmpty() throws TemplateModelException {
106 return (size() == 0);
107 }
108
109 @Override
110 public int size() throws TemplateModelException {
111 return content.size();
112 }
113
114 @Override
115 public TemplateCollectionModel keys() throws TemplateModelException {
116 return new SimpleCollection(getKeys(content).iterator(), null);
117 }
118
119 @Override
120 public TemplateCollectionModel values() throws TemplateModelException {
121 List<Object> values = getKeys(content)
122 .map(content::get)
123 .collect(toList());
124 return (TemplateCollectionModel) wrapper.wrap(values.iterator());
125 }
126
127 private static Stream<String> getKeys(ContentMap content) {
128 return content.keySet().stream()
129 .filter(key -> !content.isSpecialProperty("@" + key));
130 }
131
132 @Override
133 public TemplateNodeModel getParentNode() throws TemplateModelException {
134 try {
135
136
137 final ContentMap parent = new ContentMap(content.getJCRNode().getParent());
138 return (TemplateNodeModel) wrapper.wrap(parent);
139 } catch (RepositoryException e) {
140 throw new TemplateModelException("Can't get parent of " + content + ":" + e.getMessage(), e);
141 }
142 }
143
144
145
146
147 @Override
148 public TemplateSequenceModel getChildNodes() throws TemplateModelException {
149 List<ContentMap> children;
150 try {
151 children = asList(getNodes(content.getJCRNode())).stream()
152 .map(ContentMap::new)
153 .collect(toList());
154 } catch (RepositoryException e) {
155 log.error("Failed to read children of {}", content.getJCRNode(), e);
156 children = new ArrayList<>();
157 }
158 return (TemplateSequenceModel) wrapper.wrap(children);
159 }
160
161 @Override
162 public String getNodeName() throws TemplateModelException {
163 return (String) content.get("@name");
164 }
165
166 @Override
167 public String getNodeType() throws TemplateModelException {
168 return content.get("@nodeType").toString();
169 }
170
171 @Override
172 public String getNodeNamespace() throws TemplateModelException {
173 return null;
174 }
175
176 @Override
177 public Object getAdaptedObject(Class hint) {
178 return this.content;
179 }
180
181 public Node getJCRNode() {
182 return content.getJCRNode();
183 }
184 }