00001 package edu.ksu.cis.bandera.jjjc.symboltable;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.util.*;
00036 import java.lang.reflect.Modifier;
00037 import edu.ksu.cis.bandera.jjjc.*;
00038 import edu.ksu.cis.bandera.jjjc.exception.*;
00039
00040 public class ClassOrInterfaceType extends ReferenceType {
00041 public static int NOT_LOADED = 0;
00042 public static int LOADING = 1;
00043 public static int LOADED = 2;
00044 public static int INHERITING = 3;
00045 public static int DONE = 4;
00046
00047 private Package containingPackage;
00048 private int modifiers = 0;
00049 private boolean isInterface = false;
00050 private String path;
00051
00052 private ClassOrInterfaceType declaringClass = null;
00053 private Hashtable superClasses = new Hashtable();
00054 private Hashtable superInterfaces = new Hashtable();
00055 private ClassOrInterfaceType directSuperClass;
00056 private Hashtable directSuperInterfaces = new Hashtable();
00057 private Hashtable fields = new Hashtable();
00058 private Vector constructors = new Vector();
00059 private Hashtable methods = new Hashtable();
00060 private Hashtable types = new Hashtable();
00061 private String msg;
00062
00063 private int state = NOT_LOADED;
00064 private SymbolTable symTable;
00065
00066
00067
00068
00069
00070
00071 public ClassOrInterfaceType(Package containingPackage, Name name, String path) throws InvalidNameException {
00072 msg = "class or interface named '" + name.toString() + "'";
00073
00074 if (!(name.isSimpleName()) || Package.hasPackage(new Name(containingPackage.getName(), name)))
00075 throw new InvalidNameException("Cannot have a " + msg + " in package '"
00076 + containingPackage.getName().toString() + "'");
00077 else {
00078 this.containingPackage = containingPackage;
00079 this.name = new Name(containingPackage.getName(), name);
00080 this.path = path;
00081 }
00082 }
00083
00084
00085
00086
00087 public void addConstructor(Method constructor) throws AlreadyDeclaredException {
00088 if (declaresConstructor(constructor.getParameterTypes()))
00089 throw new AlreadyDeclaredException("Constructor '" + constructor.getName()
00090 + "' with the given signature has already been defined in " + msg);
00091
00092 constructors.addElement(constructor);
00093 constructor.setDeclaringClassOrInterface(this);
00094 }
00095
00096
00097
00098
00099 public void addDeclaredType(ClassOrInterfaceType classOrInterfaceType) throws AlreadyDeclaredException{
00100 Name simpleName = new Name(classOrInterfaceType.getName().getLastIdentifier());
00101 if (types.get(simpleName) == null)
00102 types.put(simpleName, classOrInterfaceType);
00103 else
00104 throw new AlreadyDeclaredException("Type named '" + simpleName
00105 + "' has already declared in " + msg);
00106 }
00107
00108
00109
00110
00111 public void addField(Field field) throws AlreadyDeclaredException {
00112 Name name = field.getName();
00113
00114 try {
00115 if (getField(name).getDeclaringClassOrInterface() == this)
00116 throw new AlreadyDeclaredException("Field named '" + field.getName().toString()
00117 + "' has already declared in " + msg);
00118 } catch (NotDeclaredException nde) {
00119 }
00120
00121 fields.put(field.getName(), field);
00122 field.setDeclaringClassOrInterface(this);
00123 }
00124
00125
00126
00127
00128 public void addMethod(Method method) throws AlreadyDeclaredException {
00129 if (containsMethod(method.getName(), method.getParameterTypes()))
00130 throw new AlreadyDeclaredException("Method '" + method.getName() + "' with the given signature has already been "
00131 + "defined in " + msg);
00132
00133 Vector methods = (Vector) this.methods.get(method.getName());
00134 if (methods == null) {
00135 methods = new Vector();
00136 this.methods.put(method.getName(), methods);
00137 }
00138 methods.addElement(method);
00139 method.setDeclaringClassOrInterface(this);
00140 }
00141
00142
00143
00144
00145 public void addSuperInterface(ClassOrInterfaceType interfaceType) {
00146 directSuperInterfaces.put(interfaceType.getName(), interfaceType);
00147 }
00148
00149
00150
00151
00152
00153 public static boolean areValidClassModifiers(int modifiers) {
00154 if (Modifier.isProtected(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)
00155 || Modifier.isNative(modifiers) || Modifier.isSynchronized(modifiers) || Modifier.isTransient(modifiers)
00156 || Modifier.isVolatile(modifiers))
00157 return false;
00158 else return !(Modifier.isAbstract(modifiers) && Modifier.isFinal(modifiers));
00159 }
00160
00161
00162
00163
00164
00165 public static boolean areValidInterfaceModifiers(int modifiers) {
00166 if (Modifier.isProtected(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)
00167 || Modifier.isNative(modifiers) || Modifier.isSynchronized(modifiers) || Modifier.isTransient(modifiers)
00168 || Modifier.isVolatile(modifiers) || Modifier.isFinal(modifiers))
00169 return false;
00170 else return true;
00171 }
00172
00173
00174
00175
00176
00177 public boolean areValidModifiers(int modifiers) {
00178 return (path == null) || areValidModifiers(modifiers, isInterface);
00179 }
00180
00181
00182
00183
00184
00185
00186 public static boolean areValidModifiers(int modifiers, boolean isInterface) {
00187 return (isInterface) ? areValidInterfaceModifiers(modifiers) : areValidClassModifiers(modifiers);
00188 }
00189
00190
00191
00192
00193
00194 public boolean containsField(Name name) {
00195 return (fields.get(name) != null);
00196 }
00197
00198
00199
00200
00201
00202
00203 public boolean containsMethod(Name name, Vector parameterTypes) {
00204 Vector methods = (Vector) this.methods.get(name);
00205
00206 if (methods == null)
00207 return false;
00208
00209 for (int i = 0; i < methods.size(); i++) {
00210 Method m = (Method) methods.elementAt(i);
00211 if (m.hasSignature(name, parameterTypes))
00212 return true;
00213 }
00214
00215 return false;
00216 }
00217
00218
00219
00220
00221
00222 public boolean declaresConstructor(Vector parameterTypes) {
00223 for (int i = 0; i < constructors.size(); i++) {
00224 Method m = (Method) constructors.elementAt(i);
00225 if (m.hasSignature(name, parameterTypes))
00226 return true;
00227 }
00228
00229 return false;
00230 }
00231
00232
00233
00234
00235
00236 public Vector getApplicableConstructors(Vector argumentTypes) {
00237 Vector result = new Vector();
00238
00239 for (int i = 0; i < constructors.size(); i++) {
00240 Method constructor = (Method) constructors.elementAt(i);
00241 if (constructor.isApplicable(argumentTypes))
00242 result.addElement(constructor);
00243 }
00244
00245 return result;
00246 }
00247
00248
00249
00250
00251
00252
00253 public Vector getApplicableMethods(Name name, Vector argumentTypes) {
00254 Vector result = new Vector();
00255 Vector methods = (Vector) this.methods.get(name);
00256
00257 if (methods == null)
00258 return result;
00259
00260 for (int i = 0; i < methods.size(); i++) {
00261 Method method = (Method) methods.elementAt(i);
00262 if (method.isApplicable(argumentTypes))
00263 result.addElement(method);
00264 }
00265
00266 return result;
00267 }
00268
00269
00270
00271
00272
00273 public Method getConstructor(Vector parameterTypes) throws NotDeclaredException{
00274 for (int i = 0; i < constructors.size(); i++) {
00275 Method m = (Method) constructors.elementAt(i);
00276 if (m.hasSignature(name, parameterTypes))
00277 return m;
00278 }
00279
00280 throw new NotDeclaredException("Contructor with the given signature is not declared in " + msg);
00281 }
00282
00283
00284
00285
00286 public Enumeration getConstructors() {
00287 return constructors.elements();
00288 }
00289
00290
00291
00292
00293 public Package getContainingPackage() {
00294 return containingPackage;
00295 }
00296
00297
00298
00299
00300
00301 public ClassOrInterfaceType getDeclaredType(Name name) throws NotDeclaredException {
00302 if (name.isSimpleName()) {
00303 if (types.get(name) != null)
00304 return (ClassOrInterfaceType) types.get(name);
00305 } else {
00306 if (name.getSuperName().equals(this.name))
00307 return getDeclaredType(new Name(name.getLastIdentifier()));
00308 }
00309 throw new NotDeclaredException("Type named '" + name + "' is not declared in " + msg);
00310 }
00311
00312
00313
00314
00315 public Enumeration getDeclaredTypes() {
00316 return types.elements();
00317 }
00318
00319
00320
00321
00322 public ClassOrInterfaceType getDeclaringClass() {
00323 return declaringClass;
00324 }
00325
00326
00327
00328
00329 public ClassOrInterfaceType getDirectSuperClass() {
00330 return directSuperClass;
00331 }
00332
00333
00334
00335
00336 public Enumeration getDirectSuperInterfaces() {
00337 return directSuperInterfaces.elements();
00338 }
00339
00340
00341
00342
00343
00344 public Field getField(Name name) throws NotDeclaredException{
00345 Field f = (Field) fields.get(name);
00346 if (f != null)
00347 return f;
00348 else throw new NotDeclaredException("Field named '" + name.toString()
00349 + "' is not contained in " + msg);
00350 }
00351
00352
00353
00354
00355 public Enumeration getFields() {
00356 return fields.elements();
00357 }
00358
00359
00360
00361
00362 public String getFullyQualifiedName() {
00363 return name.toString();
00364 }
00365
00366
00367
00368
00369
00370
00371 public Method getMethod(Name name, Vector parameterTypes) throws NotDeclaredException {
00372 Vector methods = (Vector) this.methods.get(name);
00373 String msg1 = "Method named '" + name.toString() + "' with the given parameters is not contained in " + msg;
00374
00375 if (methods == null)
00376 throw new NotDeclaredException(msg1);
00377
00378 for (int i = 0; i < methods.size(); i++) {
00379 Method m = (Method) methods.elementAt(i);
00380 if (m.hasSignature(name, parameterTypes))
00381 return m;
00382 }
00383
00384 throw new NotDeclaredException(msg1);
00385 }
00386
00387
00388
00389
00390 public Enumeration getMethods() {
00391 return methods.elements();
00392 }
00393
00394
00395
00396
00397
00398 public Enumeration getMethods(Name name) throws NotDeclaredException {
00399 if (methods.get(name) != null)
00400 return ((Vector) methods.get(name)).elements();
00401 else
00402 throw new NotDeclaredException("Method named '" + name + "' is not declared in type '" + this.name + "'");
00403 }
00404
00405
00406
00407
00408 public int getModifiers() {
00409 return modifiers;
00410 }
00411
00412
00413
00414
00415 public Name getName() {
00416 return name;
00417 }
00418
00419
00420
00421
00422 public String getPath() {
00423 return path;
00424 }
00425
00426
00427
00428
00429 public Enumeration getSuperClasses() {
00430 try {
00431 loadReferences();
00432 } catch (CompilerException e) {
00433 }
00434 return superClasses.elements();
00435 }
00436
00437
00438
00439
00440 public Enumeration getSuperInterfaces() {
00441 try {
00442 loadReferences();
00443 } catch (CompilerException e) {
00444 }
00445 return superInterfaces.elements();
00446 }
00447
00448
00449
00450
00451 public SymbolTable getSymbolTable() {
00452 return symTable;
00453 }
00454
00455
00456
00457
00458
00459 public boolean hasSuperClass(ClassOrInterfaceType classType) {
00460 try {
00461 loadReferences();
00462 } catch (CompilerException e) {
00463 }
00464 return hasSuperClass(classType.getName());
00465 }
00466
00467
00468
00469
00470
00471 public boolean hasSuperClass(Name name) {
00472 try {
00473 loadReferences();
00474 } catch (CompilerException e) {
00475 }
00476 return (superClasses.get(name) != null);
00477 }
00478
00479
00480
00481
00482
00483 public boolean hasSuperInterface(ClassOrInterfaceType interfaceType) {
00484 try {
00485 loadReferences();
00486 } catch (CompilerException e) {
00487 }
00488 return hasSuperInterface(interfaceType.getName());
00489 }
00490
00491
00492
00493
00494
00495 public boolean hasSuperInterface(Name name) {
00496 try {
00497 loadReferences();
00498 } catch (CompilerException e) {
00499 }
00500 return (superInterfaces.get(name) != null);
00501 }
00502
00503
00504
00505
00506 protected void inheritFields(ClassOrInterfaceType classOrInterfaceType) throws NotDeclaredException,
00507 AmbiguousFieldException {
00508 for (Enumeration e = classOrInterfaceType.fields.elements(); e.hasMoreElements();) {
00509 Field f = (Field) e.nextElement();
00510 if (Modifier.isPrivate(f.getModifiers()))
00511 continue;
00512 else if (containsField(f.getName())) {
00513 ClassOrInterfaceType declaringClassOrInterface = getField(f.getName()).getDeclaringClassOrInterface();
00514 if (declaringClassOrInterface == this)
00515 continue;
00516 else if (declaringClassOrInterface != f.getDeclaringClassOrInterface())
00517 throw new AmbiguousFieldException("Ambiguous inheritance of field named '" + f.getName()
00518 + "' in " + msg);
00519 }
00520 fields.put(f.getName(), f);
00521 }
00522 }
00523
00524
00525
00526 protected void inheritFromDirectSuperClass() throws CompilerException {
00527 if (directSuperClass == null)
00528 return;
00529
00530 directSuperClass.loadReferences();
00531
00532 superClasses.put(directSuperClass.getName(), directSuperClass);
00533
00534 for (Enumeration e = directSuperClass.superClasses.keys(); e.hasMoreElements();) {
00535 Name name = (Name) e.nextElement();
00536 superClasses.put(name, directSuperClass.superClasses.get(name));
00537 }
00538
00539 for (Enumeration e = directSuperClass.superInterfaces.keys(); e.hasMoreElements();) {
00540 Name name = (Name) e.nextElement();
00541 superInterfaces.put(name, directSuperClass.superInterfaces.get(name));
00542 }
00543
00544 inheritFields(directSuperClass);
00545 inheritMethods(directSuperClass);
00546 }
00547
00548
00549
00550 protected void inheritFromDirectSuperInterfaces() throws CompilerException {
00551 for (Enumeration enum = directSuperInterfaces.elements(); enum.hasMoreElements();) {
00552 ClassOrInterfaceType directSuperInterface = (ClassOrInterfaceType) enum.nextElement();
00553
00554 directSuperInterface.loadReferences();
00555
00556 superInterfaces.put(directSuperInterface.getName(), directSuperInterface);
00557
00558 for (Enumeration e = directSuperInterface.superInterfaces.keys(); e.hasMoreElements();) {
00559 Name name = (Name) e.nextElement();
00560 superInterfaces.put(name, directSuperInterface.superInterfaces.get(name));
00561 }
00562
00563 inheritFields(directSuperInterface);
00564 inheritMethods(directSuperInterface);
00565 }
00566 }
00567
00568
00569
00570
00571 protected void inheritMethods(ClassOrInterfaceType classOrInterfaceType) throws NotDeclaredException,
00572 AmbiguousMethodException {
00573 for (Enumeration enum = classOrInterfaceType.methods.keys(); enum.hasMoreElements();) {
00574 Name methodName = (Name) enum.nextElement();
00575 Vector thisMethods = (Vector) methods.get(methodName);
00576 Vector otherMethods = (Vector) classOrInterfaceType.methods.get(methodName);
00577
00578 if (thisMethods == null) {
00579 thisMethods = new Vector();
00580 methods.put(methodName, thisMethods);
00581 }
00582
00583 for (Enumeration e = otherMethods.elements(); e.hasMoreElements();) {
00584 Method m = (Method) e.nextElement();
00585 if (Modifier.isPrivate(m.getModifiers()))
00586 continue;
00587 else if (containsMethod(m.getName(), m.getParameterTypes())) {
00588 ClassOrInterfaceType declaringClassOrInterface = getMethod(m.getName(),
00589 m.getParameterTypes()).getDeclaringClassOrInterface();
00590 if (declaringClassOrInterface == this)
00591 continue;
00592
00593
00594
00595 else continue;
00596 }
00597 thisMethods.addElement(m);
00598 }
00599 }
00600 }
00601
00602
00603
00604
00605
00606 public boolean isAccesible(ClassOrInterfaceType otherClassOrInterfaceType) {
00607 if (Modifier.isPublic(modifiers))
00608 return true;
00609 else return this.containingPackage == otherClassOrInterfaceType.containingPackage;
00610 }
00611
00612
00613
00614
00615 public boolean isInterface() {
00616 return isInterface;
00617 }
00618
00619
00620
00621
00622 public boolean isLoaded() {
00623 return (state >= LOADED);
00624 }
00625
00626
00627
00628
00629
00630 public boolean isValidNarrowingConversion(Type otherType) {
00631 if (!(otherType instanceof ClassOrInterfaceType))
00632 return false;
00633
00634 ClassOrInterfaceType otherClassOrInterfaceType = (ClassOrInterfaceType) otherType;
00635
00636 if (this.isInterface) {
00637 if (!(otherClassOrInterfaceType.isInterface))
00638 if (Modifier.isFinal(otherClassOrInterfaceType.getModifiers()))
00639 return otherClassOrInterfaceType.hasSuperInterface(this);
00640 else return true;
00641 else
00642 if (!this.hasSuperInterface(otherClassOrInterfaceType)) {
00643 boolean result = true;
00644
00645 for (Enumeration e = otherClassOrInterfaceType.getMethods(); e.hasMoreElements();) {
00646 Vector methods1 = (Vector) e.nextElement();
00647 Vector methods2 = (Vector) otherClassOrInterfaceType.methods.get(((Method) methods1.elementAt(0)).getName());
00648 if (methods2 == null)
00649 continue;
00650
00651 for (int i = 0; i < methods1.size(); i++) {
00652 Method m1 = (Method) methods1.elementAt(i);
00653 for (int j = 0; j < methods2.size(); j++) {
00654 Method m2 = (Method) methods2.elementAt(j);
00655 if (m1.hasSameSignature(m2))
00656 return false;
00657 }
00658 }
00659 return true;
00660 }
00661
00662 return true;
00663 } else return false;
00664 } else {
00665 String objectName = "java.lang.Object";
00666 try {
00667 objectName = Package.getClassOrInterfaceType(new Name("Object")).getFullyQualifiedName();
00668
00669
00670
00671 } catch (Exception e) {}
00672
00673 if (otherClassOrInterfaceType.isInterface)
00674 return !Modifier.isFinal(this.modifiers) && !this.hasSuperInterface(otherClassOrInterfaceType);
00675 else if (!(otherClassOrInterfaceType.isInterface))
00676 return otherClassOrInterfaceType.hasSuperClass(this);
00677 else if (objectName.equals(this.getFullyQualifiedName()))
00678 return (otherType instanceof ReferenceType);
00679 else return false;
00680 }
00681 }
00682
00683
00684
00685
00686
00687 public boolean isValidWideningConversion(Type otherType) {
00688 if (!(otherType instanceof ClassOrInterfaceType))
00689 return false;
00690
00691 ClassOrInterfaceType otherClassOrInterfaceType = (ClassOrInterfaceType) otherType;
00692
00693 String objectName = "java.lang.Object";
00694 try {
00695 objectName = Package.getClassOrInterfaceType(new Name("Object")).getFullyQualifiedName();
00696
00697
00698
00699 } catch (Exception e) {}
00700
00701 if (this.isInterface) {
00702 if (otherClassOrInterfaceType.isInterface)
00703 return this.hasSuperInterface(otherClassOrInterfaceType);
00704 else
00705 return objectName.equals(otherClassOrInterfaceType.getFullyQualifiedName());
00706 } else {
00707 if (!(otherClassOrInterfaceType.isInterface))
00708 return this.hasSuperClass(otherClassOrInterfaceType);
00709 else if (otherClassOrInterfaceType.isInterface)
00710 return this.hasSuperInterface(otherClassOrInterfaceType);
00711 else return objectName.equals(otherClassOrInterfaceType.getFullyQualifiedName());
00712 }
00713 }
00714
00715
00716
00717 public void loadReferences() throws CompilerException {
00718 if (state == NOT_LOADED) {
00719 SymbolTable symbolTable = CompilationManager.buildSymbolTable(name);
00720 }
00721
00722 if (state == LOADING) {
00723
00724 } else if (state == LOADED) {
00725 state = INHERITING;
00726 inheritFromDirectSuperClass();
00727 inheritFromDirectSuperInterfaces();
00728 state = DONE;
00729 } else if (state == INHERITING) {
00730 throw new ClassCircularityException("Class circularity in " + msg);
00731 }
00732 }
00733
00734
00735
00736
00737 public void setDeclaringClass(ClassOrInterfaceType declaringClass) {
00738 this.declaringClass = declaringClass;
00739 }
00740
00741
00742
00743
00744 public void setInterface(boolean isInterface) {
00745 this.isInterface = isInterface;
00746 }
00747
00748
00749
00750 public void setLoadedState() {
00751 state = LOADED;
00752
00753 for (Enumeration e = types.elements(); e.hasMoreElements();) {
00754 ((ClassOrInterfaceType) e.nextElement()).setLoadedState();
00755 }
00756 }
00757
00758
00759
00760 public void setLoadingState() {
00761 state = LOADING;
00762
00763 for (Enumeration e = types.elements(); e.hasMoreElements();) {
00764 ((ClassOrInterfaceType) e.nextElement()).setLoadingState();
00765 }
00766 }
00767
00768
00769
00770
00771 public void setModifiers(int modifiers) throws InvalidModifiersException {
00772 if (areValidModifiers(modifiers))
00773 this.modifiers = modifiers;
00774 else
00775 throw new InvalidModifiersException("Invalid modifiers for " + msg);
00776 }
00777
00778
00779
00780
00781 public void setPath(String path) {
00782 this.path = path;
00783 }
00784
00785
00786
00787
00788 public void setSuperClass(ClassOrInterfaceType classType) {
00789 directSuperClass = classType;
00790 }
00791
00792
00793
00794
00795 public void setSymbolTable(SymbolTable symbolTable) {
00796 symTable = symbolTable;
00797 }
00798 }