001 package edu.rice.cs.cunit.instrumentors.threadCheck;
002
003 import edu.rice.cs.cunit.instrumentors.util.IScannerStrategy;
004
005 /**
006 * Storage class for subtyping warnings.
007 */
008 public class SubtypingWarning implements IScannerStrategy.IScanResult, Comparable<SubtypingWarning> {
009 /**
010 * Name of the subclass that contained the annotation.
011 */
012 public final String subClassName;
013
014 /**
015 * Name of the superclass that did not contain the annotation.
016 */
017 public final String superClassName;
018
019 /**
020 * Name of the method.
021 */
022 public final String methodName;
023
024 /**
025 * Descriptor of the method.
026 */
027 public final String methodDescriptor;
028
029 /**
030 * Name of the annotation.
031 */
032 public final String annotationName;
033
034 /**
035 * Create a new subtyping warning
036 * @param subClassName name of the subclass that contained the annotation
037 * @param superClassName name of the superclass that did not contain the annotation
038 * @param methodName name of the method, or null if on class level
039 * @param methodDescriptor descriptor of the method, or null if on class level
040 * @param annotationName name of the annotation
041 */
042 public SubtypingWarning(String subClassName,
043 String superClassName,
044 String methodName,
045 String methodDescriptor,
046 String annotationName) {
047 this.subClassName = subClassName;
048 this.superClassName = superClassName;
049 this.methodName = methodName;
050 this.methodDescriptor = methodDescriptor;
051 this.annotationName = annotationName;
052 }
053
054 /**
055 * Return true if this object is equal to the other object.
056 * @param o other object
057 * @return true if equal
058 */
059 public boolean equals(Object o) {
060 if (this == o) {
061 return true;
062 }
063 if (o == null || getClass() != o.getClass()) {
064 return false;
065 }
066
067 SubtypingWarning that = (SubtypingWarning)o;
068
069 if (annotationName != null ? !annotationName.equals(that.annotationName) : that.annotationName != null) {
070 return false;
071 }
072 if (methodDescriptor != null ? !methodDescriptor.equals(that.methodDescriptor) :
073 that.methodDescriptor != null) {
074 return false;
075 }
076 if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) {
077 return false;
078 }
079 if (subClassName != null ? !subClassName.equals(that.subClassName) : that.subClassName != null) {
080 return false;
081 }
082 if (superClassName != null ? !superClassName.equals(that.superClassName) : that.superClassName != null) {
083 return false;
084 }
085
086 return true;
087 }
088
089 /**
090 * Return a hash code for this object.
091 * @return hash code
092 */
093 public int hashCode() {
094 int result;
095 result = (subClassName != null ? subClassName.hashCode() : 0);
096 result = 31 * result + (superClassName != null ? superClassName.hashCode() : 0);
097 result = 31 * result + (methodName != null ? methodName.hashCode() : 0);
098 result = 31 * result + (methodDescriptor != null ? methodDescriptor.hashCode() : 0);
099 result = 31 * result + (annotationName != null ? annotationName.hashCode() : 0);
100 return result;
101 }
102
103 /**
104 * Compares this object with the specified object for order.
105 * @param o the Object to be compared.
106 *
107 * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than
108 * the specified object.
109 *
110 * @throws ClassCastException if the specified object's type prevents it from being compared to this Object.
111 */
112 public int compareTo(SubtypingWarning o) {
113 int res;
114 res = subClassName.compareTo(o.subClassName);
115 if(res!=0) { return res; }
116
117 if ((methodName==null) || (methodDescriptor==null)) {
118 if ((o.methodName!=null) && (methodDescriptor!=null)) {
119 return -1; // put class warnings before method warnings
120 }
121 }
122 if ((methodName!=null) && (methodDescriptor!=null)) {
123 if ((o.methodName==null)) {
124 return 1; // put class warnings before method warnings
125 }
126 }
127
128 if ((methodName!=null) && (methodDescriptor==null)) {
129 res = methodName.compareTo(o.methodName);
130 if(res!=0) { return res; }
131 res = methodDescriptor.compareTo(o.methodDescriptor);
132 if(res!=0) { return res; }
133 }
134
135 res = annotationName.compareTo(o.annotationName);
136 if(res!=0) { return res; }
137
138 res = superClassName.compareTo(o.superClassName);
139 if(res!=0) { return res; }
140
141 return 0;
142 }
143
144 /**
145 * Returns a string representation of the object.
146 * @return a string representation of the object
147 */
148 public String toString() {
149 StringBuilder sb = new StringBuilder();
150 if ((methodName==null) || (methodDescriptor==null)) {
151 // class level warning
152 sb.append(subClassName);
153 sb.append(" has ");
154 sb.append(annotationName);
155 sb.append(" but ");
156 sb.append(superClassName);
157 sb.append(" does not");
158 }
159 else {
160 // method level warning
161 sb.append(subClassName);
162 sb.append('.');
163 sb.append(methodName);
164 sb.append(methodDescriptor);
165 sb.append(" has ");
166 sb.append(annotationName);
167 sb.append(" but ");
168 sb.append(superClassName);
169 sb.append('.');
170 sb.append(methodName);
171 sb.append(methodDescriptor);
172 sb.append(" does not");
173 }
174 return sb.toString();
175 }
176
177 /**
178 * Return the name of the property that was scanned for.
179 * @return property name
180 */
181 public String getPropertyName() {
182 return "ThreadChecker Subtyping Warnings";
183 }
184 }