package org.aspectj.weaver.patterns;
import java.io.IOException;
import org.aspectj.weaver.CompressingDataOutputStream;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
public class TypeVariablePattern extends PatternNode {
private static final String anything = "?";
private String name;
private TypePattern upperBound;
private TypePattern[] interfaceBounds;
private TypePattern lowerBound;
public TypeVariablePattern(String variableName) {
this.name = variableName;
this.upperBound = new ExactTypePattern(UnresolvedType.OBJECT, false, false);
this.lowerBound = null;
this.interfaceBounds = null;
}
public TypeVariablePattern(String variableName, TypePattern upperBound) {
this.name = variableName;
this.upperBound = upperBound;
this.lowerBound = null;
this.interfaceBounds = null;
}
public TypeVariablePattern(String variableName, TypePattern upperLimit, TypePattern[] interfaceBounds, TypePattern lowerBound) {
this.name = variableName;
this.upperBound = upperLimit;
if (upperBound == null) {
upperBound = new ExactTypePattern(UnresolvedType.OBJECT, false, false);
}
this.interfaceBounds = interfaceBounds;
this.lowerBound = lowerBound;
}
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
public String getName() {
return name;
}
public boolean isAnythingPattern() {
return name.equals(anything);
}
public TypePattern getRawTypePattern() {
return upperBound;
}
public TypePattern getUpperBound() {
return upperBound;
}
public boolean hasLowerBound() {
return (lowerBound != null);
}
public TypePattern getLowerBound() {
return lowerBound;
}
public boolean hasAdditionalInterfaceBounds() {
return (interfaceBounds != null);
}
public TypePattern[] getAdditionalInterfaceBounds() {
if (interfaceBounds != null) {
return interfaceBounds;
} else {
return new TypePattern[0];
}
}
public boolean equals(Object obj) {
if (!(obj instanceof TypeVariablePattern)) {
return false;
}
TypeVariablePattern other = (TypeVariablePattern) obj;
if (!name.equals(other.name)) {
return false;
}
if (!upperBound.equals(other.upperBound)) {
return false;
}
if (lowerBound != null) {
if (other.lowerBound == null) {
return false;
}
if (!lowerBound.equals(other.lowerBound)) {
return false;
}
} else {
if (other.lowerBound != null) {
return false;
}
}
if (interfaceBounds != null) {
if (other.interfaceBounds == null) {
return false;
}
if (interfaceBounds.length != other.interfaceBounds.length) {
return false;
}
for (int i = 0; i < interfaceBounds.length; i++) {
if (!interfaceBounds[i].equals(other.interfaceBounds[i])) {
return false;
}
}
} else {
if (other.interfaceBounds != null) {
return false;
}
}
return true;
}
public int hashCode() {
int hashCode = 17 + (37 * name.hashCode());
hashCode = hashCode * 37 + upperBound.hashCode();
if (lowerBound != null) {
hashCode = hashCode * 37 + lowerBound.hashCode();
}
if (interfaceBounds != null) {
for (int i = 0; i < interfaceBounds.length; i++) {
hashCode = 37 * hashCode + interfaceBounds[i].hashCode();
}
}
return hashCode;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(name);
sb.append(getExtendsClause());
if (interfaceBounds != null) {
sb.append(" & ");
for (int i = 0; i < interfaceBounds.length; i++) {
sb.append(interfaceBounds[i].toString());
if (i < interfaceBounds.length) {
sb.append(",");
}
}
}
if (lowerBound != null) {
sb.append(" super ");
sb.append(lowerBound.toString());
}
return sb.toString();
}
private String getExtendsClause() {
if (upperBound instanceof ExactTypePattern) {
ExactTypePattern bound = (ExactTypePattern) upperBound;
if (bound.type == UnresolvedType.OBJECT) {
return "";
}
}
return " extends " + upperBound.toString();
}
public void write(CompressingDataOutputStream s) throws IOException {
s.writeUTF(name);
upperBound.write(s);
if (interfaceBounds == null) {
s.writeInt(0);
} else {
s.writeInt(interfaceBounds.length);
for (int i = 0; i < interfaceBounds.length; i++) {
interfaceBounds[i].write(s);
}
}
s.writeBoolean(hasLowerBound());
if (hasLowerBound()) {
lowerBound.write(s);
}
writeLocation(s);
}
public static TypeVariablePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
TypeVariablePattern tv = null;
String name = s.readUTF();
TypePattern upperBound = TypePattern.read(s, context);
TypePattern[] additionalInterfaceBounds = null;
int numInterfaceBounds = s.readInt();
if (numInterfaceBounds > 0) {
additionalInterfaceBounds = new TypePattern[numInterfaceBounds];
for (int i = 0; i < additionalInterfaceBounds.length; i++) {
additionalInterfaceBounds[i] = TypePattern.read(s, context);
}
}
boolean hasLowerBound = s.readBoolean();
TypePattern lowerBound = null;
if (hasLowerBound) {
lowerBound = TypePattern.read(s, context);
}
tv = new TypeVariablePattern(name, upperBound, additionalInterfaceBounds, lowerBound);
tv.readLocation(context, s);
return tv;
}
}