Source for org.jfree.util.AbstractObjectList

   1: /* ========================================================================
   2:  * JCommon : a free general purpose class library for the Java(tm) platform
   3:  * ========================================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  * 
   7:  * Project Info:  http://www.jfree.org/jcommon/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  * 
  27:  * -----------------------
  28:  * AbstractObjectList.java
  29:  * -----------------------
  30:  * (C)opyright 2003, 2004, by Object Refinery Limited and Contributors.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   Bill Kelemen; 
  34:  *                   Nicolas Brodu
  35:  *
  36:  * $Id: AbstractObjectList.java,v 1.5 2005/10/18 13:24:19 mungady Exp $
  37:  *
  38:  * Changes
  39:  * -------
  40:  * 13-Aug-2003 : Version 1, based on ObjectList (DG);
  41:  * 24-Aug-2003 : Fixed size (BK);
  42:  * 15-Sep-2003 : Fix serialization for subclasses (ShapeList, PaintList) (NB);
  43:  */
  44: 
  45: package org.jfree.util;
  46: 
  47: import java.io.IOException;
  48: import java.io.ObjectInputStream;
  49: import java.io.ObjectOutputStream;
  50: import java.io.Serializable;
  51: import java.util.Arrays;
  52: 
  53: /**
  54:  * A list of objects that can grow as required.
  55:  *
  56:  * @author David Gilbert
  57:  */
  58: public class AbstractObjectList implements Cloneable, Serializable {
  59: 
  60:     /** For serialization. */
  61:     private static final long serialVersionUID = 7789833772597351595L;
  62:     
  63:     /** The default initial capacity of the list. */
  64:     public static final int DEFAULT_INITIAL_CAPACITY = 8;
  65: 
  66:     /** Storage for the objects. */
  67:     private transient Object[] objects;
  68: 
  69:     /** The current list size. */
  70:     private int size = 0;
  71: 
  72:     /** The default increment. */
  73:     private int increment = DEFAULT_INITIAL_CAPACITY;
  74: 
  75:     /**
  76:      * Creates a new list with the default initial capacity.
  77:      */
  78:     protected AbstractObjectList() {
  79:         this(DEFAULT_INITIAL_CAPACITY);
  80:     }
  81: 
  82:     /**
  83:      * Creates a new list.
  84:      *
  85:      * @param initialCapacity  the initial capacity.
  86:      */
  87:     protected AbstractObjectList(final int initialCapacity) {
  88:         this (initialCapacity, initialCapacity);
  89:     }
  90: 
  91:     /**
  92:      * Creates a new list.
  93:      * 
  94:      * @param initialCapacity  the initial capacity.
  95:      * @param increment  the increment.
  96:      */
  97:     protected AbstractObjectList(final int initialCapacity, 
  98:                                  final int increment) {
  99:         this.objects = new Object[initialCapacity];
 100:         this.increment = increment;
 101:     }
 102: 
 103:     /**
 104:      * Returns the object at the specified index, if there is one, or 
 105:      * <code>null</code>.
 106:      *
 107:      * @param index  the object index.
 108:      *
 109:      * @return The object or <code>null</code>.
 110:      */
 111:     protected Object get(final int index) {
 112:         Object result = null;
 113:         if (index >= 0 && index < this.size) {
 114:             result = this.objects[index];
 115:         }
 116:         return result;
 117:     }
 118: 
 119:     /**
 120:      * Sets an object reference (overwriting any existing object).
 121:      *
 122:      * @param index  the object index.
 123:      * @param object  the object (<code>null</code> permitted).
 124:      */
 125:     protected void set(final int index, final Object object) {
 126:         if (index < 0) {
 127:             throw new IllegalArgumentException("Requires index >= 0.");
 128:         }
 129:         if (index >= this.objects.length) {
 130:             final Object[] enlarged = new Object[index + this.increment];
 131:             System.arraycopy(this.objects, 0, enlarged, 0, this.objects.length);
 132:             this.objects = enlarged;
 133:         }
 134:         this.objects[index] = object;
 135:         this.size = Math.max(this.size, index + 1);
 136:     }
 137: 
 138:     /**
 139:      * Clears the list.
 140:      */
 141:     public void clear() {
 142:         Arrays.fill(this.objects, null);
 143:         this.size = 0;
 144:     }
 145: 
 146:     /**
 147:      * Returns the size of the list.
 148:      *
 149:      * @return The size of the list.
 150:      */
 151:     public int size() {
 152:         return this.size;
 153:     }
 154: 
 155:     /**
 156:      * Returns the index of the specified object, or -1 if the object is not in
 157:      * the list.
 158:      *
 159:      * @param object  the object.
 160:      *
 161:      * @return The index or -1.
 162:      */
 163:     protected int indexOf(final Object object) {
 164:         for (int index = 0; index < this.size; index++) {
 165:             if (this.objects[index] == object) {
 166:                 return (index);
 167:             }
 168:         }
 169:         return -1;
 170:     }
 171: 
 172:     /**
 173:      * Tests this list for equality with another object.
 174:      *
 175:      * @param obj  the object to test.
 176:      * 
 177:      * @return A boolean.
 178:      */
 179:     public boolean equals(final Object obj) {
 180: 
 181:         if (obj == null) {
 182:             return false;
 183:         }
 184: 
 185:         if (obj == this) {
 186:             return true;
 187:         }
 188: 
 189:         if (!(obj instanceof AbstractObjectList)) {
 190:             return false;
 191:         }
 192: 
 193:         final AbstractObjectList other = (AbstractObjectList) obj;
 194:         final int listSize = size();
 195:         for (int i = 0; i < listSize; i++) {
 196:            if (!ObjectUtilities.equal(get(i), other.get(i))) {
 197:                return false;
 198:            }
 199:         }
 200:         return true;
 201:     }
 202: 
 203:     /**
 204:      * Returns a hash code value for the object.
 205:      *
 206:      * @return the hashcode
 207:      */
 208:     public int hashCode() {
 209:         return super.hashCode();
 210:     }
 211: 
 212:     /**
 213:      * Clones the list of objects.  The objects in the list are not cloned, so 
 214:      * this is method makes a 'shallow' copy of the list.
 215:      *
 216:      * @return A clone.
 217:      * 
 218:      * @throws CloneNotSupportedException if an item in the list does not 
 219:      *         support cloning.
 220:      */
 221:     public Object clone() throws CloneNotSupportedException {
 222: 
 223:         final AbstractObjectList clone = (AbstractObjectList) super.clone();
 224:         if (this.objects != null) {
 225:             clone.objects = new Object[this.objects.length];
 226:             System.arraycopy(
 227:                 this.objects, 0, clone.objects, 0, this.objects.length
 228:             );
 229:         }
 230:         return clone;
 231: 
 232:     }
 233: 
 234:     /**
 235:      * Provides serialization support.
 236:      *
 237:      * @param stream  the output stream.
 238:      *
 239:      * @throws IOException  if there is an I/O error.
 240:      */
 241:     private void writeObject(final ObjectOutputStream stream) 
 242:         throws IOException {
 243: 
 244:         stream.defaultWriteObject();
 245:         final int count = size();
 246:         stream.writeInt(count);
 247:         for (int i = 0; i < count; i++) {
 248:             final Object object = get(i);
 249:             if (object != null && object instanceof Serializable) {
 250:                 stream.writeInt(i);
 251:                 stream.writeObject(object);
 252:             }
 253:             else {
 254:                 stream.writeInt(-1);
 255:             }
 256:         }
 257: 
 258:     }
 259:     
 260:     /**
 261:      * Provides serialization support.
 262:      *
 263:      * @param stream  the input stream.
 264:      *
 265:      * @throws IOException  if there is an I/O error.
 266:      * @throws ClassNotFoundException  if there is a classpath problem.
 267:      */
 268:     private void readObject(final ObjectInputStream stream) 
 269:         throws IOException, ClassNotFoundException {
 270: 
 271:         stream.defaultReadObject();
 272:         this.objects = new Object[this.size];
 273:         final int count = stream.readInt();
 274:         for (int i = 0; i < count; i++) {
 275:             final int index = stream.readInt();
 276:             if (index != -1) {
 277:                 set(index, stream.readObject());
 278:             }
 279:         }
 280:         
 281:     }
 282:   
 283: }