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