Frames | No Frames |
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: }