001: /* ========================================================================
002: * JCommon : a free general purpose class library for the Java(tm) platform
003: * ========================================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jcommon/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * -----------------------
028: * AbstractObjectList.java
029: * -----------------------
030: * (C)opyright 2003, 2004, by Object Refinery Limited and Contributors.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): Bill Kelemen;
034: * Nicolas Brodu
035: *
036: * $Id: AbstractObjectList.java,v 1.5 2005/10/18 13:24:19 mungady Exp $
037: *
038: * Changes
039: * -------
040: * 13-Aug-2003 : Version 1, based on ObjectList (DG);
041: * 24-Aug-2003 : Fixed size (BK);
042: * 15-Sep-2003 : Fix serialization for subclasses (ShapeList, PaintList) (NB);
043: */
044:
045: package org.jfree.util;
046:
047: import java.io.IOException;
048: import java.io.ObjectInputStream;
049: import java.io.ObjectOutputStream;
050: import java.io.Serializable;
051: import java.util.Arrays;
052:
053: /**
054: * A list of objects that can grow as required.
055: *
056: * @author David Gilbert
057: */
058: public class AbstractObjectList implements Cloneable, Serializable {
059:
060: /** For serialization. */
061: private static final long serialVersionUID = 7789833772597351595L;
062:
063: /** The default initial capacity of the list. */
064: public static final int DEFAULT_INITIAL_CAPACITY = 8;
065:
066: /** Storage for the objects. */
067: private transient Object[] objects;
068:
069: /** The current list size. */
070: private int size = 0;
071:
072: /** The default increment. */
073: private int increment = DEFAULT_INITIAL_CAPACITY;
074:
075: /**
076: * Creates a new list with the default initial capacity.
077: */
078: protected AbstractObjectList() {
079: this (DEFAULT_INITIAL_CAPACITY);
080: }
081:
082: /**
083: * Creates a new list.
084: *
085: * @param initialCapacity the initial capacity.
086: */
087: protected AbstractObjectList(final int initialCapacity) {
088: this (initialCapacity, initialCapacity);
089: }
090:
091: /**
092: * Creates a new list.
093: *
094: * @param initialCapacity the initial capacity.
095: * @param increment the increment.
096: */
097: protected AbstractObjectList(final int initialCapacity,
098: final int increment) {
099: 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,
132: this .objects.length);
133: this .objects = enlarged;
134: }
135: this .objects[index] = object;
136: this .size = Math.max(this .size, index + 1);
137: }
138:
139: /**
140: * Clears the list.
141: */
142: public void clear() {
143: Arrays.fill(this .objects, null);
144: this .size = 0;
145: }
146:
147: /**
148: * Returns the size of the list.
149: *
150: * @return The size of the list.
151: */
152: public int size() {
153: return this .size;
154: }
155:
156: /**
157: * Returns the index of the specified object, or -1 if the object is not in
158: * the list.
159: *
160: * @param object the object.
161: *
162: * @return The index or -1.
163: */
164: protected int indexOf(final Object object) {
165: for (int index = 0; index < this .size; index++) {
166: if (this .objects[index] == object) {
167: return (index);
168: }
169: }
170: return -1;
171: }
172:
173: /**
174: * Tests this list for equality with another object.
175: *
176: * @param obj the object to test.
177: *
178: * @return A boolean.
179: */
180: public boolean equals(final Object obj) {
181:
182: if (obj == null) {
183: return false;
184: }
185:
186: if (obj == this ) {
187: return true;
188: }
189:
190: if (!(obj instanceof AbstractObjectList)) {
191: return false;
192: }
193:
194: final AbstractObjectList other = (AbstractObjectList) obj;
195: final int listSize = size();
196: for (int i = 0; i < listSize; i++) {
197: if (!ObjectUtilities.equal(get(i), other.get(i))) {
198: return false;
199: }
200: }
201: return true;
202: }
203:
204: /**
205: * Returns a hash code value for the object.
206: *
207: * @return the hashcode
208: */
209: public int hashCode() {
210: return super .hashCode();
211: }
212:
213: /**
214: * Clones the list of objects. The objects in the list are not cloned, so
215: * this is method makes a 'shallow' copy of the list.
216: *
217: * @return A clone.
218: *
219: * @throws CloneNotSupportedException if an item in the list does not
220: * support cloning.
221: */
222: public Object clone() throws CloneNotSupportedException {
223:
224: final AbstractObjectList clone = (AbstractObjectList) super
225: .clone();
226: if (this .objects != null) {
227: clone.objects = new Object[this .objects.length];
228: System.arraycopy(this .objects, 0, clone.objects, 0,
229: this .objects.length);
230: }
231: return clone;
232:
233: }
234:
235: /**
236: * Provides serialization support.
237: *
238: * @param stream the output stream.
239: *
240: * @throws IOException if there is an I/O error.
241: */
242: private void writeObject(final ObjectOutputStream stream)
243: throws IOException {
244:
245: stream.defaultWriteObject();
246: final int count = size();
247: stream.writeInt(count);
248: for (int i = 0; i < count; i++) {
249: final Object object = get(i);
250: if (object != null && object instanceof Serializable) {
251: stream.writeInt(i);
252: stream.writeObject(object);
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: }
|