]> source.dussan.org Git - aspectj.git/commitdiff
early commit of TypeVariable for Andy...
authoracolyer <acolyer>
Wed, 22 Jun 2005 14:38:36 +0000 (14:38 +0000)
committeracolyer <acolyer>
Wed, 22 Jun 2005 14:38:36 +0000 (14:38 +0000)
weaver/src/org/aspectj/weaver/TypeVariable.java [new file with mode: 0644]

diff --git a/weaver/src/org/aspectj/weaver/TypeVariable.java b/weaver/src/org/aspectj/weaver/TypeVariable.java
new file mode 100644 (file)
index 0000000..73c92ac
--- /dev/null
@@ -0,0 +1,131 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * Represents a type variable with bounds
+ */
+public class TypeVariable {
+       
+       /**
+        * whether or not the bounds of this type variable have been 
+        * resolved
+        */
+       private boolean isResolved = false;
+       
+       /**
+        * the name of the type variable as recorded in the generic signature
+        */
+       private String name;
+       
+       /**
+        * the upper bound of the type variable (default to Object).
+        * From the extends clause, eg. T extends Number.
+        */
+       private TypeX upperBound = TypeX.OBJECT;
+       
+       /**
+        * any additional upper (interface) bounds.
+        * from the extends clause, e.g. T extends Number & Comparable
+        */
+       private TypeX[] additionalInterfaceBounds = new TypeX[0];
+       
+       /**
+        * any lower bound.
+        * from the super clause, eg T super Foo
+        */
+       private TypeX lowerBound = null;
+       
+       public TypeVariable(String aName) {
+               this.name = aName;
+       }
+       
+       public TypeVariable(String aName, TypeX anUpperBound) {
+               this(aName);
+               this.upperBound = anUpperBound;
+       }
+       
+       public TypeVariable(String aName, TypeX anUpperBound, 
+                                               TypeX[] someAdditionalInterfaceBounds) {
+               this(aName,anUpperBound);
+               this.additionalInterfaceBounds = someAdditionalInterfaceBounds;
+       }
+       
+       public TypeVariable(String aName, TypeX anUpperBound, 
+            TypeX[] someAdditionalInterfaceBounds, TypeX aLowerBound) {
+               this(aName,anUpperBound,someAdditionalInterfaceBounds);
+               this.lowerBound = aLowerBound;
+       }
+       
+       public TypeX getUpperBound() {
+               return upperBound;
+       }
+       
+       public TypeX[] getAdditionalInterfaceBounds() {
+               return additionalInterfaceBounds;
+       }
+       
+       public TypeX getLowerBound() {
+               return lowerBound;
+       }
+       
+       public String getName() {
+               return name;
+       }
+       
+       /**
+        * resolve all the bounds of this type variable
+        */
+       public void resolve(World inSomeWorld) {
+               if (isResolved) throw new IllegalStateException("already resolved!");
+               
+               upperBound = upperBound.resolve(inSomeWorld);
+               if (lowerBound != null) lowerBound = lowerBound.resolve(inSomeWorld);
+               
+               for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                       additionalInterfaceBounds[i] = additionalInterfaceBounds[i].resolve(inSomeWorld);
+               }
+               
+               isResolved = true;
+       }
+       
+       /**
+        * answer true if the given type satisfies all of the bound constraints of this
+        * type variable.
+        * If type variable has not been resolved then throws IllegalStateException
+        */
+       public boolean canBeBoundTo(ResolvedTypeX aCandidateType) {
+               if (!isResolved) throw new IllegalStateException("Can't answer binding questions prior to resolving");
+               // can be bound iff...
+               //  aCandidateType is a subtype of upperBound
+               if (!isASubtypeOf(upperBound,aCandidateType)) {
+                       return false;
+               }
+               //  aCandidateType is a subtype of all additionalInterfaceBounds
+               for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                       if (!isASubtypeOf(additionalInterfaceBounds[i], aCandidateType)) {
+                               return false;
+                       }
+               }
+               //  lowerBound is a subtype of aCandidateType
+               if ((lowerBound != null) && (!isASubtypeOf(aCandidateType,lowerBound))) {
+                       return false;
+               }
+               return true;
+       }
+       
+       private boolean isASubtypeOf(TypeX candidateSuperType, TypeX candidateSubType) {
+               ResolvedTypeX superType = (ResolvedTypeX) candidateSuperType;
+               ResolvedTypeX subType = (ResolvedTypeX) candidateSubType;
+               return superType.isAssignableFrom(subType);
+       }
+}