001: /*
002: * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.java;
027:
028: import java.util.*;
029:
030: /**
031: * The MethodSet structure is used to store methods for a class.
032: * It maintains the invariant that it never stores two methods
033: * with the same signature. MethodSets are able to lookup
034: * all methods with a given name and the unique method with a given
035: * signature (name, args).
036: *
037: * WARNING: The contents of this source file are not part of any
038: * supported API. Code that depends on them does so at its own risk:
039: * they are subject to change or removal without notice.
040: */
041:
042: public class MethodSet {
043:
044: /**
045: * A Map containing Lists of MemberDefinitions. The Lists
046: * contain methods which share the same name.
047: */
048: private final Map lookupMap;
049:
050: /**
051: * The number of methods stored in the MethodSet.
052: */
053: private int count;
054:
055: /**
056: * Is this MethodSet currently frozen? See freeze() for more details.
057: */
058: private boolean frozen;
059:
060: /**
061: * Creates a brand new MethodSet
062: */
063: public MethodSet() {
064: frozen = false;
065: lookupMap = new HashMap();
066: count = 0;
067: }
068:
069: /**
070: * Returns the number of distinct methods stored in the MethodSet.
071: */
072: public int size() {
073: return count;
074: }
075:
076: /**
077: * Adds `method' to the MethodSet. No method of the same signature
078: * should be already defined.
079: */
080: public void add(MemberDefinition method) {
081: // Check for late additions.
082: if (frozen) {
083: throw new CompilerError("add()");
084: }
085:
086: // todo: Check for method??
087:
088: Identifier name = method.getName();
089:
090: // Get a List containing all methods of this name.
091: List methodList = (List) lookupMap.get(name);
092:
093: if (methodList == null) {
094: // There is no method with this name already.
095: // Create a List, and insert it into the hash.
096: methodList = new ArrayList();
097: lookupMap.put(name, methodList);
098: }
099:
100: // Make sure that no method with the same signature has already
101: // been added to the MethodSet.
102: int size = methodList.size();
103: for (int i = 0; i < size; i++) {
104: if (((MemberDefinition) methodList.get(i)).getType()
105: .equalArguments(method.getType())) {
106: throw new CompilerError("duplicate addition");
107: }
108: }
109:
110: // We add the method to the appropriate list.
111: methodList.add(method);
112: count++;
113: }
114:
115: /**
116: * Adds `method' to the MethodSet, replacing any previous definition
117: * with the same signature.
118: */
119: public void replace(MemberDefinition method) {
120: // Check for late additions.
121: if (frozen) {
122: throw new CompilerError("replace()");
123: }
124:
125: // todo: Check for method??
126:
127: Identifier name = method.getName();
128:
129: // Get a List containing all methods of this name.
130: List methodList = (List) lookupMap.get(name);
131:
132: if (methodList == null) {
133: // There is no method with this name already.
134: // Create a List, and insert it into the hash.
135: methodList = new ArrayList();
136: lookupMap.put(name, methodList);
137: }
138:
139: // Replace the element which has the same signature as
140: // `method'.
141: int size = methodList.size();
142: for (int i = 0; i < size; i++) {
143: if (((MemberDefinition) methodList.get(i)).getType()
144: .equalArguments(method.getType())) {
145: methodList.set(i, method);
146: return;
147: }
148: }
149:
150: // We add the method to the appropriate list.
151: methodList.add(method);
152: count++;
153: }
154:
155: /**
156: * If the MethodSet contains a method with the same signature
157: * then lookup() returns it. Otherwise, this method returns null.
158: */
159: public MemberDefinition lookupSig(Identifier name, Type type) {
160: // Go through all methods of the same name and see if any
161: // have the right signature.
162: Iterator matches = lookupName(name);
163: MemberDefinition candidate;
164:
165: while (matches.hasNext()) {
166: candidate = (MemberDefinition) matches.next();
167: if (candidate.getType().equalArguments(type)) {
168: return candidate;
169: }
170: }
171:
172: // No match.
173: return null;
174: }
175:
176: /**
177: * Returns an Iterator of all methods contained in the
178: * MethodSet which have a given name.
179: */
180: public Iterator lookupName(Identifier name) {
181: // Find the List containing all methods of this name, and
182: // return that List's Iterator.
183: List methodList = (List) lookupMap.get(name);
184: if (methodList == null) {
185: // If there is no method of this name, return a bogus, empty
186: // Iterator.
187: return Collections.emptyIterator();
188: }
189: return methodList.iterator();
190: }
191:
192: /**
193: * Returns an Iterator of all methods in the MethodSet
194: */
195: public Iterator iterator() {
196:
197: //----------------------------------------------------------
198: // The inner class MethodIterator is used to create our
199: // Iterator of all methods in the MethodSet.
200: class MethodIterator implements Iterator {
201: Iterator hashIter = lookupMap.values().iterator();
202: Iterator listIter = Collections.emptyIterator();
203:
204: public boolean hasNext() {
205: if (listIter.hasNext()) {
206: return true;
207: } else {
208: if (hashIter.hasNext()) {
209: listIter = ((List) hashIter.next()).iterator();
210:
211: // The following should be always true.
212: if (listIter.hasNext()) {
213: return true;
214: } else {
215: throw new CompilerError(
216: "iterator() in MethodSet");
217: }
218: }
219: }
220:
221: // We've run out of Lists.
222: return false;
223: }
224:
225: public Object next() {
226: return listIter.next();
227: }
228:
229: public void remove() {
230: throw new UnsupportedOperationException();
231: }
232: }
233: // end MethodIterator
234: //----------------------------------------------------------
235:
236: // A one-liner.
237: return new MethodIterator();
238: }
239:
240: /**
241: * After freeze() is called, the MethodSet becomes (mostly)
242: * immutable. Any calls to add() or addMeet() lead to
243: * CompilerErrors. Note that the entries themselves are still
244: * (unfortunately) open for mischievous and wanton modification.
245: */
246: public void freeze() {
247: frozen = true;
248: }
249:
250: /**
251: * Tells whether freeze() has been called on this MethodSet.
252: */
253: public boolean isFrozen() {
254: return frozen;
255: }
256:
257: /**
258: * Returns a (big) string representation of this MethodSet
259: */
260: public String toString() {
261: int len = size();
262: StringBuffer buf = new StringBuffer();
263: Iterator all = iterator();
264: buf.append("{");
265:
266: while (all.hasNext()) {
267: buf.append(all.next().toString());
268: len--;
269: if (len > 0) {
270: buf.append(", ");
271: }
272: }
273: buf.append("}");
274: return buf.toString();
275: }
276: }
|