001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Vasily Zakharov
021: * @version $Revision: 1.1.2.2 $
022: */package org.apache.harmony.rmi.common;
023:
024: import java.util.Collection;
025: import java.util.Iterator;
026: import java.util.Vector;
027:
028: /**
029: * Stores list of classes ({@link Class} instances), making sure
030: * no duplicates are stored, and taking inheritance into account.
031: *
032: * The classes are stores in order they were added, so that no class
033: * in the list inherits any other class in the list. When each new class
034: * is added to the list, all its superclasses (or subclasses, if
035: * <em>inverse</em> flag was set in constructor) are removed from the list.
036: *
037: * @author Vasily Zakharov
038: * @version $Revision: 1.1.2.2 $
039: */
040: public final class ClassList {
041:
042: /**
043: * Storage vector.
044: */
045: private Vector vector;
046:
047: /**
048: * Inverse flag.
049: */
050: private boolean inverse;
051:
052: /**
053: * Creates empty list, equivalent to
054: * {@link #ClassList(boolean) ClassList(false)}.
055: */
056: public ClassList() {
057: this (false);
058: }
059:
060: /**
061: * Creates empty list.
062: *
063: * @param inverse
064: * Inverse flag, see {@linkplain ClassList class description}.
065: */
066: public ClassList(boolean inverse) {
067: this .inverse = inverse;
068: vector = new Vector();
069: }
070:
071: /**
072: * Creates list and all the elements from the specified array, equivalent to
073: * {@link #ClassList(Class[], boolean) ClassList(Class[], false)}.
074: *
075: * @param classes
076: * Initial classes to put to the list.
077: */
078: public ClassList(Class[] classes) {
079: this (false);
080: addAll(classes);
081: }
082:
083: /**
084: * Creates list and all the elements from the specified array.
085: *
086: * @param classes
087: * Initial classes to put to the list.
088: *
089: * @param inverse
090: * Inverse flag, see {@linkplain ClassList class description}.
091: */
092: public ClassList(Class[] classes, boolean inverse) {
093: this (inverse);
094: addAll(classes);
095: }
096:
097: /**
098: * Creates list and all the elements from the specified collection,
099: * equivalent to
100: * {@link #ClassList(Collection, boolean) ClassList(Collection, false)}.
101: *
102: * @param classes
103: * Initial classes to put to the list.
104: */
105: public ClassList(Collection classes) {
106: this (false);
107: addAll(classes);
108: }
109:
110: /**
111: * Creates list and all the elements from the specified collection.
112: *
113: * @param classes
114: * Initial classes to put to the list.
115: *
116: * @param inverse
117: * Inverse flag, see {@linkplain ClassList class description}.
118: */
119: public ClassList(Collection classes, boolean inverse) {
120: this (inverse);
121: addAll(classes);
122: }
123:
124: /**
125: * Creates list and all the elements from the specified list, equivalent to
126: * {@link #ClassList(ClassList, boolean) ClassList(ClassList, false)}.
127: *
128: * @param classes
129: * Initial classes to put to the list.
130: */
131: public ClassList(ClassList classes) {
132: this (false);
133: addAll(classes);
134: }
135:
136: /**
137: * Creates list and all the elements from the specified list.
138: *
139: * @param classes
140: * Initial classes to put to the list.
141: *
142: * @param inverse
143: * Inverse flag, see {@linkplain ClassList class description}.
144: */
145: public ClassList(ClassList classes, boolean inverse) {
146: this (inverse);
147: addAll(classes);
148: }
149:
150: /**
151: * Return <code>true</code>
152: * if <code>cls2</code> is assignable from <code>cls1</code>
153: * and {@linkplain ClassList inverse flag} is <code>true</code>
154: * or if <code>cls1</code> is assignable from <code>cls2</code>
155: * and {@linkplain ClassList inverse flag} is <code>false</code>,
156: * <code>false</code> otherwise.
157: *
158: * @param cls1
159: * Class to check.
160: *
161: * @param cls2
162: * Class to check.
163: *
164: * @return <code>true</code> if <code>cls2</code> is assignable from
165: * <code>cls1</code> and {@linkplain ClassList inverse flag}
166: * is <code>true</code> or if <code>cls1</code> is assignable
167: * from <code>cls2</code> and {@linkplain ClassList inverse flag}
168: * is <code>false</code>, <code>false</code> otherwise.
169: */
170: private boolean checkAssign(Class cls1, Class cls2) {
171: return (inverse ? cls2.isAssignableFrom(cls1) : cls1
172: .isAssignableFrom(cls2));
173: }
174:
175: /**
176: * Returns <code>true</code> if the list contains the specified
177: * class or any of its subclasses/superclasses (depending on
178: * {@linkplain ClassList inverse flag}), <code>false</code> otherwise.
179: *
180: * @param cls
181: * Class to check.
182: *
183: * @return <code>true</code> if the list contains the specified
184: * class or any of its subclasses/superclasses (depending
185: * on {@linkplain ClassList inverse flag}), <code>false</code>
186: * otherwise.
187: */
188: public boolean contains(Class cls) {
189: int size = vector.size();
190:
191: for (int i = 0; i < size; i++) {
192: if (checkAssign(cls, (Class) vector.elementAt(i))) {
193: return true;
194: }
195: }
196: return false;
197: }
198:
199: /**
200: * Adds the specified class to the end of the list. All its
201: * superclasses/subclasses
202: * (depending on {@linkplain ClassList inverse flag}),
203: * if present, are removed. If class itself or any of its
204: * subclasses/superclasses is already present, nothing is done.
205: *
206: * @param cls
207: * Class to add.
208: */
209: public void add(Class cls) {
210: boolean exist = false;
211:
212: // Do not pre-calculate size, it will change.
213: for (int i = 0; i < vector.size(); i++) {
214: Class element = (Class) vector.elementAt(i);
215:
216: // If subclass/superclass is present, do nothing, return.
217: if (checkAssign(cls, element)) {
218: return;
219: }
220:
221: // If superclass/subclass is present, make sure class is present,
222: // remove any other other superclasses/subclasses.
223: if (checkAssign(element, cls)) {
224: if (!exist) {
225: vector.setElementAt(cls, i);
226: exist = true;
227: } else {
228: vector.removeElementAt(i);
229: }
230: }
231: }
232:
233: if (!exist) {
234: vector.addElement(cls);
235: }
236: }
237:
238: /**
239: * Adds the all classes in the specified array to the list.
240: * See {@link #add(Class)} for details.
241: *
242: * @param classes
243: * Classes to add.
244: */
245: public void addAll(Class[] classes) {
246: for (int i = 0; i < classes.length; i++) {
247: add(classes[i]);
248: }
249: }
250:
251: /**
252: * Adds the all classes in the specified collection to the list.
253: * See {@link #add(Class)} for details.
254: *
255: * @param classes
256: * Classes to add.
257: */
258: public void addAll(Collection classes) {
259: for (Iterator i = classes.iterator(); i.hasNext();) {
260: add((Class) i.next());
261: }
262: }
263:
264: /**
265: * Adds the all classes in the specified list to this list.
266: * See {@link #add(Class)} for details.
267: *
268: * @param classes
269: * Classes to add.
270: */
271: public void addAll(ClassList classes) {
272: addAll(classes.vector);
273: }
274:
275: /**
276: * Removes the specified class from the list.
277: * If class itself is not present, but its superclasses/subclasses
278: * (depending on {@linkplain ClassList inverse flag}) are, they are removed.
279: *
280: * @param cls
281: * Class to remove.
282: */
283: public void remove(Class cls) {
284: boolean changed = false;
285:
286: // Do not pre-calculate size, it will change.
287: for (int i = 0; i < vector.size(); i++) {
288: Class element = (Class) vector.elementAt(i);
289:
290: // If superclass/subclass is found, remove it.
291: if (checkAssign(element, cls)) {
292: vector.removeElementAt(i);
293:
294: // If class itself is found, return.
295: if (cls == element) {
296: return;
297: }
298: }
299: }
300: }
301:
302: /**
303: * Returns an iterator over the elements
304: * in this list in proper sequence.
305: *
306: * @return Iterator over the elements in this list
307: * in proper sequence.
308: */
309: public Iterator iterator() {
310: return vector.iterator();
311: }
312:
313: /**
314: * Returns string representation of this list.
315: *
316: * @return String representation of this list.
317: */
318: public String toString() {
319: return vector.toString();
320: }
321: }
|