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 public void setNodeDataName(String name) {
198 throw new UnsupportedOperationException("nodeDataName not supported in this tag");
199 }
200
201
202
203
204 public void setContentNodeName(String name) {
205 super.setContentNodeName(name);
206 }
207
208 private Collection getCollection() throws RepositoryException {
209 if (this.items != null) {
210 return this.items;
211 }
212
213 Content page = super.getFirstMatchingNode();
214 return page == null ? Collections.EMPTY_LIST : page.getChildren(ItemType.CONTENTNODE);
215 }
216
217 protected LoopTagStatus getLoopStatus() {
218
219
220
221 class Status implements LoopTagStatus, Serializable {
222
223 public Object getCurrent() {
224 return current;
225 }
226
227 public int getIndex() {
228 return count + begin - 1;
229 }
230
231 public int getCount() {
232 return count;
233 }
234
235 public boolean isFirst() {
236 return (count == 1);
237 }
238
239 public boolean isLast() {
240 int lastItem = end != null ? end.intValue() : size;
241 return count + begin == lastItem;
242 }
243
244 public Integer getBegin() {
245 return new Integer(begin);
246 }
247
248 public Integer getEnd() {
249 return end;
250 }
251
252 public Integer getStep() {
253 return new Integer(step);
254 }
255 }
256
257 if (status == null) {
258 status = new Status();
259 }
260
261 return status;
262 }
263
264 public int doStartTag() {
265 index += begin;
266
267 Collection children;
268 try {
269 children = getCollection();
270 }
271 catch (PathNotFoundException e) {
272
273 return SKIP_BODY;
274 }
275 catch (AccessDeniedException e) {
276 log.debug(e.getMessage());
277 return SKIP_BODY;
278 }
279 catch (RepositoryException e) {
280 log.error(e.getMessage(), e);
281 return SKIP_BODY;
282 }
283
284 this.size = children.size();
285
286 this.savePrevState();
287
288 pageContext.setAttribute(ContentNodeIterator.SIZE, new Integer(size), PageContext.REQUEST_SCOPE);
289
290 pageContext.setAttribute(ContentNodeIterator.CURRENT_INDEX, new Integer(this.count), PageContext.REQUEST_SCOPE);
291
292 pageContext.setAttribute(ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME, getContentNodeCollectionName(), PageContext.REQUEST_SCOPE);
293
294 Resource.setLocalContentNodeCollectionName(getContentNodeCollectionName());
295
296 this.contentNodeIterator = children.iterator();
297 for (int i = 0; i < begin; i++) {
298 if (this.contentNodeIterator.hasNext()) {
299 this.contentNodeIterator.next();
300 }
301 }
302
303 return doIteration() ? EVAL_BODY_INCLUDE : SKIP_BODY;
304 }
305
306 public int doAfterBody() {
307 return doIteration() ? EVAL_BODY_AGAIN : SKIP_BODY;
308 }
309
310 private boolean doIteration() {
311 if (this.contentNodeIterator.hasNext()) {
312
313 if (this.end != null && this.count > this.end.intValue()) {
314 return false;
315 }
316
317 pageContext.setAttribute(
318 ContentNodeIterator.CURRENT_INDEX,
319 new Integer(this.count),
320 PageContext.REQUEST_SCOPE);
321
322 if (StringUtils.isNotEmpty(varStatus)) {
323 pageContext.setAttribute(varStatus, getLoopStatus());
324 }
325
326 for (int j = 0; j < this.step; j++) {
327 current = this.contentNodeIterator.next();
328 Resource.setLocalContentNode((Content) current);
329 }
330
331 this.count++;
332
333 return true;
334 }
335 return false;
336 }
337
338 public int doEndTag() {
339
340 this.restorePrevState();
341 this.restorePreviousState = false;
342 this.size = 0;
343 this.count = 0;
344 this.current = null;
345
346 if (varStatus != null) {
347 pageContext.removeAttribute(varStatus, PageContext.PAGE_SCOPE);
348 }
349
350 reset();
351
352 return EVAL_PAGE;
353 }
354
355 public void reset() {
356 setContentNodeCollectionName(null);
357 this.contentNodeIterator = null;
358 this.begin = 0;
359 this.end = null;
360 this.step = 1;
361 this.size = 0;
362 this.count = 0;
363 this.varStatus = null;
364 this.status = null;
365 this.items = null;
366
367 this.outerCollName = null;
368 this.outerCurrIdx = null;
369 this.outerLocalContentNode = null;
370 this.outerResCollName = null;
371 this.outerSize = null;
372 }
373
374
375 private void savePrevState() {
376 HttpServletRequest req = (HttpServletRequest) this.pageContext.getRequest();
377
378
379 this.restorePreviousState = true;
380
381 if (req.getAttribute(ContentNodeIterator.SIZE) != null) {
382 this.outerSize = (Integer) pageContext.getAttribute(ContentNodeIterator.SIZE, PageContext.REQUEST_SCOPE);
383 this.outerCollName = (String) pageContext.getAttribute(
384 ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME,
385 PageContext.REQUEST_SCOPE);
386 this.outerCurrIdx = (Integer) pageContext.getAttribute(
387 ContentNodeIterator.CURRENT_INDEX,
388 PageContext.REQUEST_SCOPE);
389 this.outerLocalContentNode = Resource.getLocalContentNode();
390 this.outerResCollName = Resource.getLocalContentNodeCollectionName();
391 }
392 else{
393 this.outerLocalContentNode = Resource.getLocalContentNode();
394 }
395
396 }
397
398 private void restorePrevState() {
399 if (this.restorePreviousState) {
400 HttpServletRequest req = (HttpServletRequest) this.pageContext.getRequest();
401 if (this.outerSize != null) {
402 pageContext.setAttribute(ContentNodeIterator.SIZE, this.outerSize);
403 pageContext.setAttribute(ContentNodeIterator.CURRENT_INDEX, this.outerCurrIdx);
404 pageContext.setAttribute(ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME, this.outerCollName);
405 Resource.setLocalContentNode(this.outerLocalContentNode);
406 Resource.setLocalContentNodeCollectionName(this.outerResCollName);
407 }
408 else {
409 if(outerLocalContentNode != null){
410 Resource.setLocalContentNode(this.outerLocalContentNode);
411 }
412 else{
413 Resource.removeLocalContentNode();
414 }
415 Resource.removeLocalContentNodeCollectionName();
416 pageContext.removeAttribute(ContentNodeIterator.CURRENT_INDEX);
417 pageContext.removeAttribute(ContentNodeIterator.SIZE);
418 pageContext.removeAttribute(ContentNodeIterator.CONTENT_NODE_COLLECTION_NAME);
419 }
420 }
421 }
422
423 }