KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > template > SimpleCollection


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.template;
54
55 import java.io.Serializable JavaDoc;
56 import java.util.*;
57
58 /**
59  * A simple implementation of {@link TemplateCollectionModel}.
60  * It's able to wrap <tt>java.util.Iterator</tt>-s and <tt>java.util.Collection</tt>-s.
61  * If you wrap an <tt>Iterator</tt>, the variable can be &lt;list>-ed (&lt;forach>-ed) only once!
62  *
63  * <p>Consider using {@link SimpleSequence} instead of this class if you want to wrap <tt>Iterator</tt>s.
64  * <tt>SimpleSequence</tt> will read all elements of the <tt>Iterator</tt>, and store them in a <tt>List</tt>
65  * (this may cause too high resource consumption in some applications), so you can list the variable
66  * for unlimited times. Also, if you want to wrap <tt>Collection</tt>s, and then list the resulting
67  * variable for many times, <tt>SimpleSequence</tt> may gives better performance, as the
68  * wrapping of non-<tt>TemplateModel</tt> objects happens only once.
69  *
70  * <p>This class is thread-safe. The returned <tt>TemplateModelIterator</tt>-s
71  * are <em>not</em> thread-safe.
72  *
73  * @version $Id: SimpleCollection.java,v 1.13 2004/11/27 14:49:57 ddekany Exp $
74  */

75 public class SimpleCollection extends WrappingTemplateModel
76 implements TemplateCollectionModel, Serializable JavaDoc {
77     
78     private boolean iteratorDirty;
79     private Iterator iterator;
80     private Collection collection;
81
82     public SimpleCollection(Iterator iterator) {
83         this.iterator = iterator;
84     }
85
86     public SimpleCollection(Collection collection) {
87         this.collection = collection;
88     }
89
90     public SimpleCollection(Iterator iterator, ObjectWrapper wrapper) {
91         super(wrapper);
92         this.iterator = iterator;
93     }
94
95     public SimpleCollection(Collection collection, ObjectWrapper wrapper) {
96         super(wrapper);
97         this.collection = collection;
98     }
99
100     /**
101      * Retrieves a template model iterator that is used to iterate over the elements in this collection.
102      *
103      * <p>When you wrap an <tt>Iterator</tt> and you get <tt>TemplateModelIterator</tt> for multiple times,
104      * only on of the returned <tt>TemplateModelIterator</tt> instances can be really used. When you have called a
105      * method of a <tt>TemplateModelIterator</tt> instance, all other instance will throw a
106      * <tt>TemplateModelException</tt> when you try to call their methods, since the wrapped <tt>Iterator</tt>
107      * can't return the first element.
108      */

109     public TemplateModelIterator iterator() {
110         if (iterator != null) {
111             return new SimpleTemplateModelIterator(iterator, true);
112         } else {
113             synchronized (collection) {
114                 return new SimpleTemplateModelIterator(collection.iterator(), false);
115             }
116         }
117     }
118     
119     /*
120      * An instance of this class must be accessed only from a single thread.
121      * The encapsulated Iterator may accessible from multiple threads (as multiple
122      * SimpleTemplateModelIterator instance can wrap the same Iterator instance),
123      * but the first thread which uses the shared Iterator will monopolize that.
124      */

125     private class SimpleTemplateModelIterator implements TemplateModelIterator {
126         
127         private Iterator iterator;
128         private boolean iteratorShared;
129             
130         SimpleTemplateModelIterator(Iterator iterator, boolean iteratorShared) {
131             this.iterator = iterator;
132             this.iteratorShared = iteratorShared;
133         }
134
135         public TemplateModel next() throws TemplateModelException {
136             if (iteratorShared) makeIteratorDirty();
137             
138             if (!iterator.hasNext()) {
139                 throw new TemplateModelException("The collection has no more elements.");
140             }
141             
142             Object JavaDoc value = iterator.next();
143             if (value instanceof TemplateModel) {
144                 return (TemplateModel) value;
145             } else {
146                 return wrap(value);
147             }
148         }
149
150         public boolean hasNext() throws TemplateModelException {
151             /*
152              * Theorically this should not make the iterator dirty,
153              * but I met sync. problems if I don't do it here. :(
154              */

155             if (iteratorShared) makeIteratorDirty();
156             return iterator.hasNext();
157         }
158         
159         private void makeIteratorDirty() throws TemplateModelException {
160             synchronized (SimpleCollection.this) {
161                 if (iteratorDirty) {
162                     throw new TemplateModelException(
163                             "This collection variable wraps a java.util.Iterator, "
164                             + "thus it can be <list>-ed or <foreach>-ed only once");
165                 } else {
166                     iteratorDirty = true;
167                     iteratorShared = false;
168                 }
169             }
170         }
171     }
172 }
173
Popular Tags