001: package com.ibm.sigtest;
002:
003: import java.io.BufferedReader;
004: import java.io.IOException;
005: import java.lang.reflect.Modifier;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Vector;
009:
010: /**
011: * This class stores all the information needed to compare the signature of one
012: * class to another.
013: * @author Matthew J. Duftler (duftler@us.ibm.com)
014: */
015: public class ClassDesc extends MemberDesc {
016:
017: private String super ClassName = null;
018:
019: private List interfaceNames = new Vector();
020:
021: private List constructorDescs = new Vector();
022:
023: private List methodDescs = new Vector();
024:
025: public ClassDesc(String name, int modifiers) {
026: super (name, modifiers);
027: }
028:
029: public void setSuperClassName(String super ClassName) {
030: this .super ClassName = super ClassName;
031: }
032:
033: public String getSuperClassName() {
034: return super ClassName;
035: }
036:
037: public void setInterfaceNames(List interfaceNames) {
038: this .interfaceNames = interfaceNames;
039: }
040:
041: public List getInterfaceNames() {
042: return interfaceNames;
043: }
044:
045: public void addConstructorDesc(MethodDesc constructorDesc) {
046: constructorDescs.add(constructorDesc);
047: }
048:
049: public void setConstructorDescs(List constructorDescs) {
050: this .constructorDescs = constructorDescs;
051: }
052:
053: public List getConstructorDescs() {
054: return constructorDescs;
055: }
056:
057: public void addMethodDesc(MethodDesc methodDesc) {
058: methodDescs.add(methodDesc);
059: }
060:
061: public void setMethodDescs(List methodDescs) {
062: this .methodDescs = methodDescs;
063: }
064:
065: public List getMethodDescs() {
066: return methodDescs;
067: }
068:
069: public static ClassDesc parseClassDesc(
070: BufferedReader classDescReader) throws IOException {
071: String classDescStr = classDescReader.readLine();
072: List tokens = SigTestUtils.stringToList(classDescStr, " ");
073: int size = tokens.size();
074: int i = 0;
075: int modifiers = Integer.parseInt((String) tokens.get(i++));
076: String className = (String) tokens.get(i++);
077: String super ClassName = null;
078: String interfaceNamesListStr = null;
079: List interfaceNames = null;
080:
081: while (size > i) {
082: String tempToken = (String) tokens.get(i++);
083:
084: if (tempToken.equals("extends")) {
085: super ClassName = (String) tokens.get(i++);
086: } else if (tempToken.equals("implements")) {
087: interfaceNamesListStr = (String) tokens.get(i++);
088: }
089: }
090:
091: if (interfaceNamesListStr != null) {
092: interfaceNames = SigTestUtils.stringToList(
093: interfaceNamesListStr, ",");
094: }
095:
096: ClassDesc classDesc = new ClassDesc(className, modifiers);
097:
098: classDesc.setSuperClassName(super ClassName);
099:
100: if (interfaceNames != null) {
101: classDesc.setInterfaceNames(interfaceNames);
102: }
103:
104: classDescReader.readLine();
105:
106: String tempLine = null;
107:
108: while (!(tempLine = classDescReader.readLine()).equals("}")) {
109: MethodDesc methodDesc = MethodDesc
110: .parseMethodDesc(tempLine);
111:
112: if (methodDesc.getReturnTypeName() == null) {
113: classDesc.addConstructorDesc(methodDesc);
114: } else {
115: classDesc.addMethodDesc(methodDesc);
116: }
117: }
118:
119: return classDesc;
120: }
121:
122: public boolean equals(Object obj) {
123: if (obj == null) {
124: return false;
125: } else if (obj == this ) {
126: return true;
127: } else {
128: ClassDesc that = (ClassDesc) obj;
129:
130: if (!SigTestUtils.objectsEqual(name, that.name)) {
131: return false;
132: } else if (modifiers != that.modifiers) {
133: return false;
134: } else if (!SigTestUtils.objectsEqual(super ClassName,
135: that.super ClassName)) {
136: return false;
137: } else if (!SigTestUtils.collectionsMatch(interfaceNames,
138: that.interfaceNames)) {
139: return false;
140: } else if (!SigTestUtils.collectionsMatch(constructorDescs,
141: that.constructorDescs)) {
142: return false;
143: } else if (!SigTestUtils.collectionsMatch(methodDescs,
144: that.methodDescs)) {
145: return false;
146: } else {
147: return true;
148: }
149: }
150: }
151:
152: public String compare(ClassDesc that) {
153: StringBuffer strBuf = new StringBuffer();
154:
155: if (modifiers != that.modifiers) {
156: strBuf.append("On class '" + name
157: + "', the modifiers are '"
158: + Modifier.toString(that.modifiers)
159: + "', when they should be '"
160: + Modifier.toString(modifiers) + "'.");
161: }
162:
163: if (!SigTestUtils.objectsEqual(super ClassName,
164: that.super ClassName)) {
165: strBuf.append("\nClass '"
166: + name
167: + "' "
168: + (that.super ClassName != null ? "extends '"
169: + that.super ClassName + "'"
170: : "does not extend any class")
171: + ", when it should"
172: + (super ClassName != null ? " extend '"
173: + super ClassName + "'."
174: : "n't extend any class."));
175: }
176:
177: if (!SigTestUtils.collectionsMatch(interfaceNames,
178: that.interfaceNames)) {
179: strBuf.append("\nClass '"
180: + name
181: + "' "
182: + (that.interfaceNames.size() > 0 ? "implements '"
183: + that.interfaceNames + "'"
184: : "does not implement any interfaces")
185: + ", when it should"
186: + (interfaceNames.size() > 0 ? " implement '"
187: + interfaceNames + "'."
188: : "n't implement any interfaces."));
189: }
190:
191: List referenceExtras = new Vector();
192: List candidateExtras = new Vector();
193:
194: SigTestUtils
195: .findExtras(constructorDescs, that.constructorDescs,
196: referenceExtras, candidateExtras);
197:
198: if (referenceExtras.size() > 0 || candidateExtras.size() > 0) {
199: strBuf
200: .append("\nClass '"
201: + name
202: + "'"
203: + (candidateExtras.size() > 0 ? " has extraneous constructor"
204: + (candidateExtras.size() > 1 ? "s"
205: : "")
206: + " "
207: + SigTestUtils
208: .getExpandedMethodList(candidateExtras)
209: : "")
210: + (referenceExtras.size() > 0 ? (candidateExtras
211: .size() > 0 ? " and" : "")
212: + " is missing constructor"
213: + (referenceExtras.size() > 1 ? "s"
214: : "")
215: + " "
216: + SigTestUtils
217: .getExpandedMethodList(referenceExtras)
218: : "") + ".");
219: }
220:
221: referenceExtras = new Vector();
222: candidateExtras = new Vector();
223:
224: SigTestUtils.findExtras(methodDescs, that.methodDescs,
225: referenceExtras, candidateExtras);
226:
227: if (referenceExtras.size() > 0 || candidateExtras.size() > 0) {
228: strBuf
229: .append("\nClass '"
230: + name
231: + "'"
232: + (candidateExtras.size() > 0 ? " has extraneous method"
233: + (candidateExtras.size() > 1 ? "s"
234: : "")
235: + " "
236: + SigTestUtils
237: .getExpandedMethodList(candidateExtras)
238: : "")
239: + (referenceExtras.size() > 0 ? (candidateExtras
240: .size() > 0 ? " and" : "")
241: + " is missing method"
242: + (referenceExtras.size() > 1 ? "s"
243: : "")
244: + " "
245: + SigTestUtils
246: .getExpandedMethodList(referenceExtras)
247: : "") + ".");
248: }
249:
250: return (strBuf.length() > 0) ? strBuf.toString() : null;
251: }
252:
253: public String toString() {
254: StringBuffer strBuf = new StringBuffer();
255:
256: strBuf.append(modifiers
257: + " "
258: + name
259: + (super ClassName != null ? " extends "
260: + super ClassName : "")
261: + (interfaceNames.size() > 0 ? " implements "
262: + SigTestUtils.listToString(interfaceNames)
263: : "") + "\n{\n");
264:
265: Iterator constrIterator = constructorDescs.iterator();
266:
267: while (constrIterator.hasNext()) {
268: strBuf.append(" " + constrIterator.next() + "\n");
269: }
270:
271: Iterator methodIterator = methodDescs.iterator();
272:
273: while (methodIterator.hasNext()) {
274: strBuf.append(" " + methodIterator.next() + "\n");
275: }
276:
277: strBuf.append("}");
278:
279: return strBuf.toString();
280: }
281:
282: public int hashCode() {
283: return toString().hashCode();
284: }
285: }
|