KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > type > ArrayType


1 /* ArrayType Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; see the file COPYING. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: ArrayType.java,v 4.19.2.3 2002/05/28 17:34:21 hoenicke Exp $
18  */

19
20 package jode.type;
21 import jode.bytecode.ClassInfo;
22 import java.util.Vector JavaDoc;
23
24 /**
25  * This type represents an array type.
26  *
27  * @author Jochen Hoenicke
28  */

29 public class ArrayType extends ReferenceType {
30     // The interfaces that an array implements:
31
final static ClassInfo[] arrayIfaces = {
32     // Make sure to list all interfaces, even if some interface
33
// implements another (or change code in getGeneralizedType().
34
ClassInfo.forName("java.lang.Cloneable"),
35     ClassInfo.forName("java.io.Serializable")
36     };
37
38     Type elementType;
39
40     ArrayType(Type elementType) {
41         super(TC_ARRAY);
42         this.elementType = elementType;
43     }
44
45     public Type getElementType() {
46         return elementType;
47     }
48
49     public Type getSuperType() {
50     if (elementType instanceof IntegerType)
51         return tRange(tObject, this);
52     else
53         return tRange(tObject,
54               (ReferenceType) tArray(elementType.getSuperType()));
55     }
56
57     public Type getSubType() {
58     if (elementType instanceof IntegerType)
59         return this;
60     else
61         return tArray(elementType.getSubType());
62     }
63
64     public Type getHint() {
65     return tArray(elementType.getHint());
66     }
67     
68     public Type getCanonic() {
69     return tArray(elementType.getCanonic());
70     }
71     
72     /**
73      * Create the type corresponding to the range from bottomType to this.
74      * @param bottomType the start point of the range
75      * @return the range type, or tError if not possible.
76      */

77     public Type createRangeType(ReferenceType bottom) {
78     /*
79      * tArray(y), tArray(x) -> tArray( y.intersection(x) )
80      * obj , tArray(x) -> <obj, tArray(x)>
81      * iff tArray extends and implements obj
82      */

83     if (bottom.getTypeCode() == TC_ARRAY)
84         return tArray(elementType.intersection
85               (((ArrayType)bottom).elementType));
86
87     if (bottom.getTypeCode() == TC_CLASS) {
88         ClassInterfacesType bottomCIT = (ClassInterfacesType)bottom;
89         if (bottomCIT.clazz == null
90         && implementsAllIfaces(null, arrayIfaces, bottomCIT.ifaces))
91         return tRange(bottomCIT, this);
92     }
93     return tError;
94     }
95
96     /**
97      * Returns the common sub type of this and type.
98      * @param type the other type.
99      * @return the common sub type.
100      */

101     public Type getSpecializedType(Type type) {
102     /*
103      * tArray(x), iface -> tArray(x) iff tArray implements iface
104      * tArray(x), tArray(y) -> tArray(x.intersection(y))
105      * tArray(x), other -> tError
106      */

107     if (type.getTypeCode() == TC_RANGE) {
108         type = ((RangeType) type).getBottom();
109     }
110     if (type == tNull)
111         return this;
112     if (type.getTypeCode() == TC_ARRAY) {
113         Type elType = elementType.intersection
114         (((ArrayType)type).elementType);
115         return elType != tError ? tArray(elType) : tError;
116     }
117     if (type.getTypeCode() == TC_CLASS) {
118         ClassInterfacesType other = (ClassInterfacesType) type;
119         if (other.clazz == null
120         && implementsAllIfaces(null, arrayIfaces, other.ifaces))
121         return this;
122     }
123     return tError;
124     }
125
126     /**
127      * Returns the common super type of this and type.
128      * @param type the other type.
129      * @return the common super type.
130      */

131     public Type getGeneralizedType(Type type) {
132     /* tArray(x), tNull -> tArray(x)
133      * tArray(x), tClass(y) -> common ifaces of tArray and tClass
134      * tArray(x), tArray(y) -> tArray(x.intersection(y)) or tObject
135      * tArray(x), other -> tError
136          */

137     if (type.getTypeCode() == TC_RANGE) {
138         type = ((RangeType) type).getTop();
139     }
140     if (type == tNull)
141             return this;
142         if (type.getTypeCode() == TC_ARRAY) {
143         Type elType = elementType.intersection
144         (((ArrayType)type).elementType);
145         if (elType != tError)
146         return tArray(elType);
147         return ClassInterfacesType.create(null, arrayIfaces);
148     }
149     if (type.getTypeCode() == TC_CLASS) {
150         ClassInterfacesType other = (ClassInterfacesType) type;
151         if (implementsAllIfaces(other.clazz, other.ifaces, arrayIfaces))
152         return ClassInterfacesType.create(null, arrayIfaces);
153         if (other.clazz == null
154         && implementsAllIfaces(null, arrayIfaces, other.ifaces))
155         return other;
156         
157         /* Now the more complicated part: find all interfaces, that are
158          * implemented by one interface or class in each group.
159          *
160          * First get all interfaces of this.clazz and this.ifaces.
161          */

162         Vector JavaDoc newIfaces = new Vector JavaDoc();
163     iface_loop:
164         for (int i=0; i < arrayIfaces.length; i++) {
165         /* Now consider each array interface. If any clazz or
166          * interface in other implements it, add it to the
167          * newIfaces vector. */

168         if (other.clazz != null
169             && arrayIfaces[i].implementedBy(other.clazz)) {
170             newIfaces.addElement(arrayIfaces[i]);
171             continue iface_loop;
172         }
173         for (int j=0; j<other.ifaces.length; j++) {
174             if (arrayIfaces[i].implementedBy(other.ifaces[j])) {
175             newIfaces.addElement(arrayIfaces[i]);
176             continue iface_loop;
177             }
178         }
179         }
180         ClassInfo[] ifaceArray = new ClassInfo[newIfaces.size()];
181         newIfaces.copyInto(ifaceArray);
182         return ClassInterfacesType.create(null, ifaceArray);
183     }
184     return tError;
185     }
186
187     /**
188      * Checks if we need to cast to a middle type, before we can cast from
189      * fromType to this type.
190      * @return the middle type, or null if it is not necessary.
191      */

192     public Type getCastHelper(Type fromType) {
193     Type hintType = fromType.getHint();
194     switch (hintType.getTypeCode()) {
195     case TC_ARRAY:
196         if (!elementType.isClassType()
197         || !((ArrayType)hintType).elementType.isClassType())
198         return tObject;
199         Type middleType = elementType.getCastHelper
200         (((ArrayType)hintType).elementType);
201         if (middleType != null)
202         return tArray(middleType);
203         return null;
204     case TC_CLASS:
205         ClassInterfacesType hint = (ClassInterfacesType) hintType;
206         if (hint.clazz == null
207         && implementsAllIfaces(null, arrayIfaces, hint.ifaces))
208         return null;
209         return tObject;
210     case TC_UNKNOWN:
211         return null;
212     }
213     return tObject;
214     }
215
216     /**
217      * Checks if this type represents a valid type instead of a list
218      * of minimum types.
219      */

220     public boolean isValidType() {
221     return elementType.isValidType();
222     }
223
224     public boolean isClassType() {
225         return true;
226     }
227
228     public String JavaDoc getTypeSignature() {
229     return "["+elementType.getTypeSignature();
230     }
231
232     public Class JavaDoc getTypeClass() throws ClassNotFoundException JavaDoc {
233     return Class.forName("["+elementType.getTypeSignature());
234     }
235
236     public String JavaDoc toString() {
237         return elementType.toString()+"[]";
238     }
239
240     private static String JavaDoc pluralize(String JavaDoc singular) {
241         return singular +
242             ((singular.endsWith("s") || singular.endsWith("x")
243               || singular.endsWith("sh") || singular.endsWith("ch"))
244              ? "es" : "s");
245     }
246
247     public String JavaDoc getDefaultName() {
248     if (elementType instanceof ArrayType)
249         return elementType.getDefaultName();
250         return pluralize(elementType.getDefaultName());
251     }
252
253     public boolean equals(Object JavaDoc o) {
254         if (o == this)
255             return true;
256         if (o instanceof ArrayType) {
257             ArrayType type = (ArrayType) o;
258             return type.elementType.equals(elementType);
259         }
260         return false;
261     }
262 }
263
Popular Tags