Save This Page
Home » pentaho-reporting-engine-classic-0.8.10 » org » jfree » report » util » [javadoc | source]
    1   /**
    2    * =========================================================
    3    * Pentaho-Reporting-Classic : a free Java reporting library
    4    * =========================================================
    5    *
    6    * Project Info:  http://reporting.pentaho.org/
    7    *
    8    * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
    9    *
   10    * This library is free software; you can redistribute it and/or modify it under the terms
   11    * of the GNU Lesser General Public License as published by the Free Software Foundation;
   12    * either version 2.1 of the License, or (at your option) any later version.
   13    *
   14    * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   15    * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   16    * See the GNU Lesser General Public License for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License along with this
   19    * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
   20    * Boston, MA 02111-1307, USA.
   21    *
   22    * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
   23    * in the United States and other countries.]
   24    *
   25    * ------------
   26    * WeakReferenceList.java
   27    * ------------
   28    * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
   29    */
   30   
   31   package org.jfree.report.util;
   32   
   33   import java.io.IOException;
   34   import java.io.ObjectInputStream;
   35   import java.io.Serializable;
   36   import java.lang.ref.Reference;
   37   import java.lang.ref.WeakReference;
   38   
   39   /**
   40    * The WeakReference list uses <code>java.lang.ref.WeakReference</code>s to store its contents. In contrast to the
   41    * WeakHashtable, this list knows how to restore missing content, so that garbage collected elements can be restored
   42    * when they are accessed.
   43    * <p/>
   44    * By default this list can contain 25 elements, where the first element is stored using a strong reference, which is
   45    * not garbage collected.
   46    * <p/>
   47    * Restoring the elements is not implemented, concrete implementations will have to override the
   48    * <code>restoreChild(int)</code> method. The <code>getMaxChildCount</code> method defines the maxmimum number of
   49    * children in the list. When more than <code>maxChildCount</code> elements are contained in this list, add will always
   50    * return false to indicate that adding the element failed.
   51    * <p/>
   52    * To customize the list, override createReference to create a different kind of reference.
   53    * <p/>
   54    * This list is able to add or replace elements, but inserting or removing of elements is not possible.
   55    *
   56    * @author Thomas Morgner
   57    */
   58   public abstract class WeakReferenceList implements Serializable, Cloneable
   59   {
   60     /**
   61      * The master element.
   62      */
   63     private Object master;
   64   
   65     /**
   66      * Storage for the references.
   67      */
   68     private transient Reference[] childs;
   69   
   70     /**
   71      * The current number of elements.
   72      */
   73     private int size;
   74   
   75     /**
   76      * The maximum number of elements.
   77      */
   78     private final int maxChilds;
   79   
   80     /**
   81      * Creates a new weak reference list. The storage of the list is limited to getMaxChildCount() elements.
   82      *
   83      * @param maxChildCount the maximum number of elements.
   84      */
   85     protected WeakReferenceList(final int maxChildCount)
   86     {
   87       this.maxChilds = maxChildCount;
   88       this.childs = new Reference[maxChildCount - 1];
   89     }
   90   
   91     /**
   92      * Returns the maximum number of children in this list.
   93      *
   94      * @return the maximum number of elements in this list.
   95      */
   96     protected final int getMaxChildCount()
   97     {
   98       return maxChilds;
   99     }
  100   
  101     /**
  102      * Returns the master element of this list. The master element is the element stored by a strong reference and cannot
  103      * be garbage collected.
  104      *
  105      * @return the master element
  106      */
  107     protected Object getMaster()
  108     {
  109       return master;
  110     }
  111   
  112     /**
  113      * Attempts to restore the child stored on the given index.
  114      *
  115      * @param index the index.
  116      * @return null if the child could not be restored or the restored child.
  117      */
  118     protected abstract Object restoreChild(int index);
  119   
  120     /**
  121      * Returns the child stored at the given index. If the child has been garbage collected, it gets restored using the
  122      * restoreChild function.
  123      *
  124      * @param index the index.
  125      * @return the object.
  126      */
  127     public Object get(final int index)
  128     {
  129       if (isMaster(index))
  130       {
  131         return master;
  132       }
  133       else
  134       {
  135         final Reference ref = childs[getChildPos(index)];
  136         if (ref == null)
  137         {
  138           throw new IllegalStateException("State: " + index);
  139         }
  140         Object ob = ref.get();
  141         if (ob == null)
  142         {
  143           ob = restoreChild(index);
  144           childs[getChildPos(index)] = createReference(ob);
  145         }
  146         return ob;
  147       }
  148     }
  149   
  150     /**
  151      * Replaces the child stored at the given index with the new child which can be null.
  152      *
  153      * @param report the object.
  154      * @param index  the index.
  155      */
  156     public void set(final Object report, final int index)
  157     {
  158       if (isMaster(index))
  159       {
  160         master = report;
  161       }
  162       else
  163       {
  164         childs[getChildPos(index)] = createReference(report);
  165       }
  166     }
  167   
  168     /**
  169      * Creates a new reference for the given object.
  170      *
  171      * @param o the object.
  172      * @return a WeakReference for the object o without any ReferenceQueue attached.
  173      */
  174     private Reference createReference(final Object o)
  175     {
  176       return new WeakReference(o);
  177     }
  178   
  179     /**
  180      * Adds the element to the list. If the maximum size of the list is exceeded, this function returns false to indicate
  181      * that adding failed.
  182      *
  183      * @param rs the object.
  184      * @return true, if the object was successfully added to the list, false otherwise
  185      */
  186     public boolean add(final Object rs)
  187     {
  188       if (size == 0)
  189       {
  190         master = rs;
  191         size = 1;
  192         return true;
  193       }
  194       else
  195       {
  196         if (size < getMaxChildCount())
  197         {
  198           childs[size - 1] = createReference(rs);
  199           size++;
  200           return true;
  201         }
  202         else
  203         {
  204           // was not able to add this to this list, maximum number of entries reached.
  205           return false;
  206         }
  207       }
  208     }
  209   
  210     /**
  211      * Returns true, if the given index denotes a master index of this list.
  212      *
  213      * @param index the index.
  214      * @return true if the index is a master index.
  215      */
  216     protected boolean isMaster(final int index)
  217     {
  218       return index % getMaxChildCount() == 0;
  219     }
  220   
  221     /**
  222      * Returns the internal storage position for the child.
  223      *
  224      * @param index the index.
  225      * @return the internal storage index.
  226      */
  227     protected int getChildPos(final int index)
  228     {
  229       return index % getMaxChildCount() - 1;
  230     }
  231   
  232     /**
  233      * Returns the size of the list.
  234      *
  235      * @return the size.
  236      */
  237     public int getSize()
  238     {
  239       return size;
  240     }
  241   
  242     /**
  243      * Serialisation support. The transient child elements were not saved.
  244      *
  245      * @param in the input stream.
  246      * @throws IOException            if there is an I/O error.
  247      * @throws ClassNotFoundException if a serialized class is not defined on this system.
  248      */
  249     private void readObject(final ObjectInputStream in)
  250         throws IOException, ClassNotFoundException
  251     {
  252       in.defaultReadObject();
  253       childs = new Reference[getMaxChildCount() - 1];
  254       for (int i = 0; i < childs.length; i++)
  255       {
  256         childs[i] = createReference(null);
  257       }
  258     }
  259   
  260     /**
  261      * Creates and returns a copy of this object.  The precise meaning of "copy" may depend on the class of the object.
  262      * The general intent is that, for any object <tt>x</tt>, the expression: <blockquote>
  263      * <pre>
  264      * x.clone() != x</pre></blockquote>
  265      * will be true, and that the expression: <blockquote>
  266      * <pre>
  267      * x.clone().getClass() == x.getClass()</pre></blockquote>
  268      * will be <tt>true</tt>, but these are not absolute requirements. While it is typically the case that: <blockquote>
  269      * <pre>
  270      * x.clone().equals(x)</pre></blockquote>
  271      * will be <tt>true</tt>, this is not an absolute requirement.
  272      * <p/>
  273      * By convention, the returned object should be obtained by calling <tt>super.clone</tt>.  If a class and all of its
  274      * superclasses (except <tt>Object</tt>) obey this convention, it will be the case that <tt>x.clone().getClass() ==
  275      * x.getClass()</tt>.
  276      * <p/>
  277      * By convention, the object returned by this method should be independent of this object (which is being cloned).  To
  278      * achieve this independence, it may be necessary to modify one or more fields of the object returned by
  279      * <tt>super.clone</tt> before returning it.  Typically, this means copying any mutable objects that comprise the
  280      * internal "deep structure" of the object being cloned and replacing the references to these objects with references
  281      * to the copies.  If a class contains only primitive fields or references to immutable objects, then it is usually
  282      * the case that no fields in the object returned by <tt>super.clone</tt> need to be modified.
  283      * <p/>
  284      * The method <tt>clone</tt> for class <tt>Object</tt> performs a specific cloning operation. First, if the class of
  285      * this object does not implement the interface <tt>Cloneable</tt>, then a <tt>CloneNotSupportedException</tt> is
  286      * thrown. Note that all arrays are considered to implement the interface <tt>Cloneable</tt>. Otherwise, this method
  287      * creates a new instance of the class of this object and initializes all its fields with exactly the contents of the
  288      * corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned.
  289      * Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
  290      * <p/>
  291      * The class <tt>Object</tt> does not itself implement the interface <tt>Cloneable</tt>, so calling the <tt>clone</tt>
  292      * method on an object whose class is <tt>Object</tt> will result in throwing an exception at run time.
  293      *
  294      * @return a clone of this instance.
  295      * @throws CloneNotSupportedException if the object's class does not support the <code>Cloneable</code> interface.
  296      *                                    Subclasses that override the <code>clone</code> method can also throw this
  297      *                                    exception to indicate that an instance cannot be cloned.
  298      * @see Cloneable
  299      */
  300     protected Object clone()
  301         throws CloneNotSupportedException
  302     {
  303       final WeakReferenceList list = (WeakReferenceList) super.clone();
  304       list.childs = (Reference[]) childs.clone();
  305       return list;
  306     }
  307   }

Save This Page
Home » pentaho-reporting-engine-classic-0.8.10 » org » jfree » report » util » [javadoc | source]