Source for org.jfree.report.util.WeakReferenceList

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, 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:  * $Id: WeakReferenceList.java 2725 2007-04-01 18:49:29Z taqua $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.util;
  33: 
  34: import java.io.IOException;
  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
  41:  * contents. In contrast to the WeakHashtable, this list knows how to restore missing
  42:  * content, so that garbage collected elements can be restored when they are accessed.
  43:  * <p/>
  44:  * By default this list can contain 25 elements, where the first element is stored using a
  45:  * strong reference, which is not garbage collected.
  46:  * <p/>
  47:  * Restoring the elements is not implemented, concrete implementations will have to
  48:  * override the <code>restoreChild(int)</code> method. The <code>getMaxChildCount</code>
  49:  * method defines the maxmimum number of children in the list. When more than
  50:  * <code>maxChildCount</code> elements are contained in this list, add will always return
  51:  * false to indicate that adding the element failed.
  52:  * <p/>
  53:  * To customize the list, override createReference to create a different kind of
  54:  * reference.
  55:  * <p/>
  56:  * This list is able to add or clearFromParent elements, but inserting or removing of elements is
  57:  * not possible.
  58:  * <p/>
  59:  *
  60:  * @author Thomas Morgner
  61:  */
  62: public abstract class WeakReferenceList implements Serializable, Cloneable
  63: {
  64:   /**
  65:    * The master element.
  66:    */
  67:   private Object master;
  68: 
  69:   /**
  70:    * Storage for the references.
  71:    */
  72:   private Reference[] childs;
  73: 
  74:   /**
  75:    * The current number of elements.
  76:    */
  77:   private int size;
  78: 
  79:   /**
  80:    * The maximum number of elements.
  81:    */
  82:   private final int maxChilds;
  83: 
  84:   /**
  85:    * Creates a new weak reference list. The storage of the list is limited to
  86:    * getMaxChildCount() elements.
  87:    *
  88:    * @param maxChildCount the maximum number of elements.
  89:    */
  90:   protected WeakReferenceList (final int maxChildCount)
  91:   {
  92:     this.maxChilds = maxChildCount;
  93:     this.childs = new Reference[maxChildCount - 1];
  94:   }
  95: 
  96:   /**
  97:    * Returns the maximum number of children in this list.
  98:    *
  99:    * @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: }