001 package edu.rice.cs.cunit.instrumentors.threadCheck;
002
003 import edu.rice.cs.cunit.util.XMLConfig;
004
005 import java.io.Serializable;
006 import java.util.HashSet;
007 import java.util.HashMap;
008
009 /**
010 * Class that keeps track an invariant (ThreadCheckAnnotationRecord) and the classes and methods its applied to.
011 */
012 public class ThreadCheckDefinitionRecord implements Serializable {
013 /**
014 * The invariant applied to the classes and methods below.
015 */
016 public final ThreadCheckAnnotationRecord invariant;
017
018 /**
019 * A set of class names.
020 */
021 public final HashSet<String> classNames;
022
023 /**
024 * A map of method strings, generated by concatenating the class name, "::" and the method signature.
025 * Example: The method "void run()" in the class "sample.threadCheck.ThreadCheckSample4" has the string
026 * "sample.threadCheck.ThreadCheckSample4::run()V".
027 * The value is true if subtyping warnings should be suppressed.
028 */
029 public final HashMap<String,Boolean> methodClassAndSigs;
030
031 /**
032 * Create a new empty definition record that just specifies the invariant.
033 * @param inv the invariant of this definition
034 */
035 public ThreadCheckDefinitionRecord(ThreadCheckAnnotationRecord inv) {
036 invariant = inv;
037 classNames = new HashSet<String>();
038 methodClassAndSigs = new HashMap<String,Boolean>();
039 }
040
041 /**
042 * Add the specified class to the set of classes.
043 * @param className name of the class
044 */
045 public void addClass(String className) {
046 classNames.add(className);
047 }
048
049 /**
050 * Add the specified method to the set of methods.
051 * @param className name of the class
052 * @param methodSig signature of the method
053 * @param suppressSubtypingWarning true if subtyping warnings should be suppressed
054 */
055 public void addMethod(String className, String methodSig, boolean suppressSubtypingWarning) {
056 methodClassAndSigs.put(className+AThreadCheckStrategy.CLASS_SIG_SEPARATOR_STRING+methodSig, suppressSubtypingWarning);
057 }
058
059 /**
060 * Return true if the invariant applies to the specified class.
061 * @param className name of the class
062 * @return true if the invariant applies
063 */
064 public boolean appliesToClass(String className) {
065 return classNames.contains(className);
066 }
067
068 /**
069 * Return true if the invariant applies to the specified method.
070 * @param className name of the class
071 * @param methodSig signature of the method
072 * @return true if the invariant applies
073 */
074 public boolean appliesToMethod(String className, String methodSig) {
075 return methodClassAndSigs.keySet().contains(className+AThreadCheckStrategy.CLASS_SIG_SEPARATOR_STRING +methodSig);
076 }
077
078 /**
079 * Return the invariant of this definition.
080 * @return the invariant, a ThreadCheckAnnotationRecord
081 */
082 public ThreadCheckAnnotationRecord getInvariant() {
083 return invariant;
084 }
085
086 /**
087 * Return true if there is nothing specified in this definition record.
088 * @return true if nothing specified
089 */
090 public boolean empty() {
091 return (classNames.size()==0) && (methodClassAndSigs.size()==0);
092 }
093
094 // /**
095 // * Returns true if the two ThreadCheckDefinitionRecords are equal.
096 // * @param o other object
097 // * @return true if equal
098 // */
099 // public boolean equals(Object o) {
100 // if (this == o) {
101 // return true;
102 // }
103 // if (o == null || getClass() != o.getClass()) {
104 // return false;
105 // }
106 //
107 // ThreadCheckDefinitionRecord that = (ThreadCheckDefinitionRecord)o;
108 //
109 // if (!classNames.equals(that.classNames)) {
110 // return false;
111 // }
112 // if (!invariant.equals(that.invariant)) {
113 // return false;
114 // }
115 // if (!methodClassAndSigs.equals(that.methodClassAndSigs)) {
116 // return false;
117 // }
118 //
119 // return true;
120 // }
121 //
122 // /**
123 // * Return a hashcode for this ThreadCheckDefinitionRecord.
124 // * @return hashcode
125 // */
126 // public int hashCode() {
127 // int result;
128 // result = invariant.hashCode();
129 // result = 31 * result + classNames.hashCode();
130 // result = 31 * result + methodClassAndSigs.hashCode();
131 // return result;
132 // }
133
134
135 /**
136 * Returns true if the two ThreadCheckDefinitionRecords are equal.
137 * @param o other object
138 * @return true if equal
139 */
140 public boolean equals(Object o) {
141 if (this == o) {
142 return true;
143 }
144 if (o == null || getClass() != o.getClass()) {
145 return false;
146 }
147
148 ThreadCheckDefinitionRecord that = (ThreadCheckDefinitionRecord)o;
149
150 if (!classNames.equals(that.classNames)) {
151 return false;
152 }
153 if (!invariant.equals(that.invariant)) {
154 return false;
155 }
156 if (!methodClassAndSigs.equals(that.methodClassAndSigs)) {
157 return false;
158 }
159
160 return true;
161 }
162
163 /**
164 * Return a hashcode for this ThreadCheckDefinitionRecord.
165 * @return hashcode
166 */
167 public int hashCode() {
168 int result;
169 result = invariant.hashCode();
170 result = 31 * result + classNames.hashCode();
171 result = 31 * result + methodClassAndSigs.hashCode();
172 return result;
173 }
174
175 /**
176 * Returns a string representation of the object.
177 * @return a string representation of the object.
178 */
179 public String toString() {
180 StringBuilder sb = new StringBuilder();
181 sb.append("Invariant: ");
182 sb.append(invariant);
183 sb.append(XMLConfig.NL);
184 if (classNames.size()>0) {
185 sb.append("\tClasses: "+classNames.size());
186 for(String s: classNames) {
187 sb.append("\t\t");
188 sb.append(s);
189 sb.append(XMLConfig.NL);
190 }
191 }
192 if (methodClassAndSigs.size()>0) {
193 sb.append("\tMethods: "+methodClassAndSigs.size());
194 for(String s: classNames) {
195 sb.append("\t\t");
196 sb.append(s);
197 sb.append(XMLConfig.NL);
198 }
199 }
200 return super.toString();
201 }
202 }