001    /**
002     * ========================================
003     * JFreeReport : a free Java report library
004     * ========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/
007     *
008     * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     * ------------
026     * $Id: WeakReferenceList.java 3048 2007-07-28 18:02:42Z tmorgner $
027     * ------------
028     * (C) Copyright 2000-2005, by Object Refinery Limited.
029     * (C) Copyright 2005-2007, by Pentaho Corporation.
030     */
031    
032    package org.jfree.report.util;
033    
034    import java.io.IOException;
035    import java.io.Serializable;
036    import java.lang.ref.Reference;
037    import java.lang.ref.WeakReference;
038    
039    /**
040     * The WeakReference list uses <code>java.lang.ref.WeakReference</code>s to store its
041     * contents. In contrast to the WeakHashtable, this list knows how to restore missing
042     * content, so that garbage collected elements can be restored when they are accessed.
043     * <p/>
044     * By default this list can contain 25 elements, where the first element is stored using a
045     * strong reference, which is not garbage collected.
046     * <p/>
047     * Restoring the elements is not implemented, concrete implementations will have to
048     * override the <code>restoreChild(int)</code> method. The <code>getMaxChildCount</code>
049     * method defines the maxmimum number of children in the list. When more than
050     * <code>maxChildCount</code> elements are contained in this list, add will always return
051     * false to indicate that adding the element failed.
052     * <p/>
053     * To customize the list, override createReference to create a different kind of
054     * reference.
055     * <p/>
056     * This list is able to add or clearFromParent elements, but inserting or removing of elements is
057     * not possible.
058     * <p/>
059     *
060     * @author Thomas Morgner
061     */
062    public abstract class WeakReferenceList implements Serializable, Cloneable
063    {
064      /**
065       * The master element.
066       */
067      private Object master;
068    
069      /**
070       * Storage for the references.
071       */
072      private Reference[] childs;
073    
074      /**
075       * The current number of elements.
076       */
077      private int size;
078    
079      /**
080       * The maximum number of elements.
081       */
082      private final int maxChilds;
083    
084      /**
085       * Creates a new weak reference list. The storage of the list is limited to
086       * getMaxChildCount() elements.
087       *
088       * @param maxChildCount the maximum number of elements.
089       */
090      protected WeakReferenceList (final int maxChildCount)
091      {
092        this.maxChilds = maxChildCount;
093        this.childs = new Reference[maxChildCount - 1];
094      }
095    
096      /**
097       * Returns the maximum number of children in this list.
098       *
099       * @return the maximum number of elements in this list.
100       */
101      protected final int getMaxChildCount ()
102      {
103        return maxChilds;
104      }
105    
106      /**
107       * Returns the master element of this list. The master element is the element stored by
108       * a strong reference and cannot be garbage collected.
109       *
110       * @return the master element
111       */
112      protected Object getMaster ()
113      {
114        return master;
115      }
116    
117      /**
118       * Attempts to restore the child stored on the given index.
119       *
120       * @param index the index.
121       * @return null if the child could not be restored or the restored child.
122       */
123      protected abstract Object restoreChild (int index);
124    
125      /**
126       * Returns the child stored at the given index. If the child has been garbage collected,
127       * it gets restored using the restoreChild function.
128       *
129       * @param index the index.
130       * @return the object.
131       */
132      public Object get (final int index)
133      {
134        if (isMaster(index))
135        {
136          return master;
137        }
138        else
139        {
140          final Reference ref = childs[getChildPos(index)];
141          if (ref == null)
142          {
143            throw new IllegalStateException("State: " + index);
144          }
145          Object ob = ref.get();
146          if (ob == null)
147          {
148            ob = restoreChild(index);
149            childs[getChildPos(index)] = createReference(ob);
150          }
151          return ob;
152        }
153      }
154    
155      /**
156       * Replaces the child stored at the given index with the new child which can be null.
157       *
158       * @param report the object.
159       * @param index  the index.
160       */
161      public void set (final Object report, final int index)
162      {
163        if (isMaster(index))
164        {
165          master = report;
166        }
167        else
168        {
169          childs[getChildPos(index)] = createReference(report);
170        }
171      }
172    
173      /**
174       * Creates a new reference for the given object.
175       *
176       * @param o the object.
177       * @return a WeakReference for the object o without any ReferenceQueue attached.
178       */
179      private Reference createReference (final Object o)
180      {
181        return new WeakReference(o);
182      }
183    
184      /**
185       * Adds the element to the list. If the maximum size of the list is exceeded, this
186       * function returns false to indicate that adding failed.
187       *
188       * @param rs the object.
189       * @return true, if the object was successfully added to the list, false otherwise
190       */
191      public boolean add (final Object rs)
192      {
193        if (size == 0)
194        {
195          master = rs;
196          size = 1;
197          return true;
198        }
199        else
200        {
201          if (size < getMaxChildCount())
202          {
203            childs[size - 1] = createReference(rs);
204            size++;
205            return true;
206          }
207          else
208          {
209            // was not able to add this to this list, maximum number of entries reached.
210            return false;
211          }
212        }
213      }
214    
215      /**
216       * Returns true, if the given index denotes a master index of this list.
217       *
218       * @param index the index.
219       * @return true if the index is a master index.
220       */
221      protected boolean isMaster (final int index)
222      {
223        return index % getMaxChildCount() == 0;
224      }
225    
226      /**
227       * Returns the internal storage position for the child.
228       *
229       * @param index the index.
230       * @return the internal storage index.
231       */
232      protected int getChildPos (final int index)
233      {
234        return index % getMaxChildCount() - 1;
235      }
236    
237      /**
238       * Returns the size of the list.
239       *
240       * @return the size.
241       */
242      public int getSize ()
243      {
244        return size;
245      }
246    
247      /**
248       * Serialisation support. The transient child elements are not saved.
249       *
250       * @param out the output stream.
251       * @throws IOException if there is an I/O error.
252       */
253      private void writeObject (final java.io.ObjectOutputStream out)
254              throws IOException
255      {
256        final Reference[] orgChilds = childs;
257        try
258        {
259          childs = null;
260          out.defaultWriteObject();
261        }
262        finally
263        {
264          childs = orgChilds;
265        }
266      }
267    
268      /**
269       * Serialisation support. The transient child elements were not saved.
270       *
271       * @param in the input stream.
272       * @throws IOException            if there is an I/O error.
273       * @throws ClassNotFoundException if a serialized class is not defined on this system.
274       */
275      private void readObject (final java.io.ObjectInputStream in)
276              throws IOException, ClassNotFoundException
277      {
278        in.defaultReadObject();
279        childs = new Reference[getMaxChildCount() - 1];
280        for (int i = 0; i < childs.length; i++)
281        {
282          childs[i] = createReference(null);
283        }
284      }
285    
286      /**
287       * Creates and returns a copy of this object.  The precise meaning of "copy" may depend
288       * on the class of the object. The general intent is that, for any object <tt>x</tt>,
289       * the expression: <blockquote>
290       * <pre>
291       * x.clone() != x</pre></blockquote>
292       * will be true, and that the expression: <blockquote>
293       * <pre>
294       * x.clone().getClass() == x.getClass()</pre></blockquote>
295       * will be <tt>true</tt>, but these are not absolute requirements. While it is typically
296       * the case that: <blockquote>
297       * <pre>
298       * x.clone().equals(x)</pre></blockquote>
299       * will be <tt>true</tt>, this is not an absolute requirement.
300       * <p/>
301       * By convention, the returned object should be obtained by calling
302       * <tt>super.clone</tt>.  If a class and all of its superclasses (except
303       * <tt>Object</tt>) obey this convention, it will be the case that
304       * <tt>x.clone().getClass() == x.getClass()</tt>.
305       * <p/>
306       * By convention, the object returned by this method should be independent of this
307       * object (which is being cloned).  To achieve this independence, it may be necessary to
308       * modify one or more fields of the object returned by <tt>super.clone</tt> before
309       * returning it.  Typically, this means copying any mutable objects that comprise the
310       * internal "deep structure" of the object being cloned and replacing the references to
311       * these objects with references to the copies.  If a class contains only primitive
312       * fields or references to immutable objects, then it is usually the case that no fields
313       * in the object returned by <tt>super.clone</tt> need to be modified.
314       * <p/>
315       * The method <tt>clone</tt> for class <tt>Object</tt> performs a specific cloning
316       * operation. First, if the class of this object does not implement the interface
317       * <tt>Cloneable</tt>, then a <tt>CloneNotSupportedException</tt> is thrown. Note that
318       * all arrays are considered to implement the interface <tt>Cloneable</tt>. Otherwise,
319       * this method creates a new instance of the class of this object and initializes all
320       * its fields with exactly the contents of the corresponding fields of this object, as
321       * if by assignment; the contents of the fields are not themselves cloned. Thus, this
322       * method performs a "shallow copy" of this object, not a "deep copy" operation.
323       * <p/>
324       * The class <tt>Object</tt> does not itself implement the interface <tt>Cloneable</tt>,
325       * so calling the <tt>clone</tt> method on an object whose class is <tt>Object</tt> will
326       * result in throwing an exception at run time.
327       *
328       * @return a clone of this instance.
329       *
330       * @throws CloneNotSupportedException if the object's class does not support the
331       *                                    <code>Cloneable</code> interface. Subclasses that
332       *                                    override the <code>clone</code> method can also
333       *                                    throw this exception to indicate that an instance
334       *                                    cannot be cloned.
335       * @see Cloneable
336       */
337      protected Object clone ()
338              throws CloneNotSupportedException
339      {
340        final WeakReferenceList list = (WeakReferenceList) super.clone();
341        list.childs = (Reference[]) childs.clone();
342        return list;
343      }
344    }