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.cms.taglibs;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.ItemType;
38 import info.magnolia.cms.security.AccessDeniedException;
39 import org.apache.commons.lang.StringUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import javax.jcr.PathNotFoundException;
44 import javax.jcr.RepositoryException;
45 import javax.servlet.http.HttpServletRequest;
46 import javax.servlet.jsp.PageContext;
47 import javax.servlet.jsp.jstl.core.LoopTagStatus;
48 import java.io.Serializable;
49 import java.util.Collection;
50 import java.util.Collections;
51 import java.util.Iterator;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public class ContentNodeIterator extends BaseContentTag {
75 private static final Logger log = LoggerFactory.getLogger(ContentNodeIterator.class);
76
77
78
79
80 public static final String CONTENT_NODE_COLLECTION_NAME = "contentNodeCollectionName";
81
82
83
84
85
86 protected static final String CURRENT_INDEX = "currentIndex";
87
88
89
90
91
92 protected static final String SIZE = "size";
93
94
95
96
97 protected int begin;
98
99
100
101
102 protected Integer end;
103
104
105
106
107 protected int step = 1;
108
109
110
111
112 private String varStatus;
113
114
115
116
117 private Collection items;
118
119 protected int size;
120
121 protected int count;
122 protected int index;
123
124 protected Object current;
125
126 private Iterator contentNodeIterator;
127
128 private LoopTagStatus status;
129
130
131 private Integer outerSize = null;
132
133
134 private Integer outerCurrIdx = null;
135
136
137 private String outerCollName = null;
138
139
140 private String outerResCollName = null;
141
142
143 private Content outerLocalContentNode = null;
144
145
146 private boolean restorePreviousState = false;
147
148
149
150
151
152 public void setBegin(int index) {
153 this.begin = index;
154 }
155
156
157
158
159
160 public void setEnd(Integer index) {
161 this.end = index;
162 }
163
164
165
166
167
168 public void setStep(int step) {
169 this.step = step;
170 }
171
172
173
174
175
176
177
178
179 public void setVarStatus(String varStatus) {
180 this.varStatus = varStatus;
181 }
182
183
184
185
186
187
188
189 public void setItems(Collection items) {
190 this.items = items;
191 }
192
193
194
195
196 public void setNodeDataName(String name) {
197 throw new UnsupportedOperationException("nodeDataName not supported in this tag");
198 }
199
200
201
202
203 public void setContentNodeName(String name) {
204 super.setContentNodeName(name);
205 }
206
207 private Collection getCollection() throws RepositoryException {
208 if (this.items != null) {
209 return this.items;
210 }
211
212 Content page = super.getFirstMatchingNode();
213 return page == null ? Collections.EMPTY_LIST : page.getChildren(ItemType.CONTENTNODE);
214 }
215
216 protected LoopTagStatus getLoopStatus() {
217
218 class Status implements LoopTagStatus, Serializable {
219
220 public Object getCurrent() {
221 return current;
222 }
223
224 public int getIndex() {
225 return count + begin - 1;
226 }
227
228 public int getCount() {
229 return count;
230 }
231
232 public boolean isFirst() {
233 return (count == 1);
234 }
235
236 public boolean isLast() {
237 int lastItem = end != null ? end.intValue() : size;
238 return count + begin == lastItem;
239 }
240
241 public Integer getBegin() {
242 return new Integer(begin);
243 }
244
245 public Integer getEnd() {
246 return end;
247 }
248
249 public Integer getStep() {
250 return new Integer(step);
251 }
252 }
253
254 if (status == null) {
255 status = new Status();
256 }
257
258 return status;
259 }
260
261 public int doStartTag() {
262 index += begin;
263
264 Collection children;
265 try {
266 children = getCollection();
267 }
268 catch (PathNotFoundException e) {
269
270 return SKIP_BODY;
271 }
272 catch (AccessDeniedException e) {
273 log.debug(e.getMessage());
274 return SKIP_BODY;
275 }
276 catch (RepositoryException e) {
277 log.error(e.getMessage(), e);
278 return SKIP_BODY;
279 }
280
281 this.size = children.size();
282
283 this.savePrevState();
284
285 pageContext.setAttribute(ContentNodeIterator.SIZE, new Integer(size), PageContext.REQUEST_SCOPE);
286
287 pageContext.setAttribute(ContentNodeIterator.CURRENT_INDEX, new Integer(this.count), PageContext.REQUEST_SCOPE);
288
289 pageContext.setAttribute(ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME, getContentNodeCollectionName(), PageContext.REQUEST_SCOPE);
290
291 Resource.setLocalContentNodeCollectionName(getContentNodeCollectionName());
292
293 this.contentNodeIterator = children.iterator();
294 for (int i = 0; i < begin; i++) {
295 if (this.contentNodeIterator.hasNext()) {
296 this.contentNodeIterator.next();
297 }
298 }
299
300 return doIteration() ? EVAL_BODY_INCLUDE : SKIP_BODY;
301 }
302
303 public int doAfterBody() {
304 return doIteration() ? EVAL_BODY_AGAIN : SKIP_BODY;
305 }
306
307 private boolean doIteration() {
308 if (this.contentNodeIterator.hasNext()) {
309
310 if (this.end != null && this.count > this.end.intValue()) {
311 return false;
312 }
313
314 pageContext.setAttribute(
315 ContentNodeIterator.CURRENT_INDEX,
316 new Integer(this.count),
317 PageContext.REQUEST_SCOPE);
318
319 if (StringUtils.isNotEmpty(varStatus)) {
320 pageContext.setAttribute(varStatus, getLoopStatus());
321 }
322
323 for (int j = 0; j < this.step; j++) {
324 current = this.contentNodeIterator.next();
325 Resource.setLocalContentNode((Content) current);
326 }
327
328 this.count++;
329
330 return true;
331 }
332 return false;
333 }
334
335 public int doEndTag() {
336
337 this.restorePrevState();
338 this.restorePreviousState = false;
339 this.size = 0;
340 this.count = 0;
341 this.current = null;
342
343 if (varStatus != null) {
344 pageContext.removeAttribute(varStatus, PageContext.PAGE_SCOPE);
345 }
346
347 reset();
348
349 return EVAL_PAGE;
350 }
351
352 public void reset() {
353 setContentNodeCollectionName(null);
354 this.contentNodeIterator = null;
355 this.begin = 0;
356 this.end = null;
357 this.step = 1;
358 this.size = 0;
359 this.count = 0;
360 this.varStatus = null;
361 this.status = null;
362 this.items = null;
363
364 this.outerCollName = null;
365 this.outerCurrIdx = null;
366 this.outerLocalContentNode = null;
367 this.outerResCollName = null;
368 this.outerSize = null;
369 }
370
371
372 private void savePrevState() {
373 HttpServletRequest req = (HttpServletRequest) this.pageContext.getRequest();
374
375
376 this.restorePreviousState = true;
377
378 if (req.getAttribute(ContentNodeIterator.SIZE) != null) {
379 this.outerSize = (Integer) pageContext.getAttribute(ContentNodeIterator.SIZE, PageContext.REQUEST_SCOPE);
380 this.outerCollName = (String) pageContext.getAttribute(
381 ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME,
382 PageContext.REQUEST_SCOPE);
383 this.outerCurrIdx = (Integer) pageContext.getAttribute(
384 ContentNodeIterator.CURRENT_INDEX,
385 PageContext.REQUEST_SCOPE);
386 this.outerLocalContentNode = Resource.getLocalContentNode();
387 this.outerResCollName = Resource.getLocalContentNodeCollectionName();
388 }
389 else{
390 this.outerLocalContentNode = Resource.getLocalContentNode();
391 }
392
393 }
394
395 private void restorePrevState() {
396 if (this.restorePreviousState) {
397 HttpServletRequest req = (HttpServletRequest) this.pageContext.getRequest();
398 if (this.outerSize != null) {
399 pageContext.setAttribute(ContentNodeIterator.SIZE, this.outerSize);
400 pageContext.setAttribute(ContentNodeIterator.CURRENT_INDEX, this.outerCurrIdx);
401 pageContext.setAttribute(ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME, this.outerCollName);
402 Resource.setLocalContentNode(this.outerLocalContentNode);
403 Resource.setLocalContentNodeCollectionName(this.outerResCollName);
404 }
405 else {
406 if(outerLocalContentNode != null){
407 Resource.setLocalContentNode(this.outerLocalContentNode);
408 }
409 else{
410 Resource.removeLocalContentNode();
411 }
412 Resource.removeLocalContentNodeCollectionName();
413 pageContext.removeAttribute(ContentNodeIterator.CURRENT_INDEX);
414 pageContext.removeAttribute(ContentNodeIterator.SIZE);
415 pageContext.removeAttribute(ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME);
416 }
417 }
418 }
419
420 }