KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > clirr > core > ApiDifference


1 //////////////////////////////////////////////////////////////////////////////
2
// Clirr: compares two versions of a java library for binary compatibility
3
// Copyright (C) 2003 - 2005 Lars Kühne
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
14
//
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
//////////////////////////////////////////////////////////////////////////////
19

20 package net.sf.clirr.core;
21
22
23 /**
24  * Describes an API change.
25  *
26  * @author Lars
27  */

28 public final class ApiDifference
29 {
30     private static final int HASHCODE_MAGIC = 29;
31
32     /**
33      * Object representing the message text to be output (or null if
34      * the constructor which takes a message string directly is used).
35      */

36     private Message message = null;
37
38     /** human readable change report. */
39     private String JavaDoc report;
40
41     /**
42      * severity of the change in terms of binary compatibility,
43      * as determined by clirr.
44      */

45     private Severity binaryCompatibilitySeverity;
46
47     /**
48      * severity of the change in terms of source compatibility,
49      * as determined by clirr.
50      */

51     private Severity sourceCompatibilitySeverity;
52
53     /** The fully qualified class name that is affected by the API change. */
54     private String JavaDoc affectedClass;
55
56     /**
57      * The method that is affected, if any.
58      * <p/>
59      * The content is the method name plus the fully qualified
60      * parameter types separated by comma and space and enclosed in
61      * brackets, e.g. "doStuff(java.lang.String, int)".
62      * <p/>
63      * This value is <code>null</code> if no single method is
64      * affected, i.e. if the
65      * api change affects a field or is global
66      * (like "class is now final").
67      */

68     private String JavaDoc affectedMethod;
69
70     /**
71      * The field that is affected, if any.
72      * <p/>
73      * The content is the field name, e.g. "someValue".
74      * Type information for the field is not available.
75      * <p/>
76      * This value is <code>null</code> if no single field is
77      * affected, i.e. if the
78      * api change affects a method or is global
79      * (like "class is now final").
80      */

81     private String JavaDoc affectedField;
82
83     /**
84      * The set of additional parameters that are available for use
85      * when building the actual message description. These vary depending
86      * upon the actual difference being reported.
87      */

88     private String JavaDoc[] extraInfo;
89
90     /**
91      * Invokes the two-severity-level version of this constructor.
92      */

93     public ApiDifference(
94         Message message,
95         Severity severity,
96         String JavaDoc clazz,
97         String JavaDoc method,
98         String JavaDoc field,
99         String JavaDoc[] args)
100     {
101         this(message, severity, severity, clazz, method, field, args);
102     }
103
104     /**
105      * Create a new API difference representation.
106      *
107      * @param message is the key of a human readable string describing the
108      * change that was made.
109      *
110      * @param binarySeverity the severity in terms of binary compatibility,
111      * must be non-null.
112      *
113      * @param sourceSeverity the severity in terms of source code compatibility,
114      * must be non-null.
115      *
116      * @param clazz is the fully-qualified name of the class in which the
117      * change occurred, must be non-null.
118      *
119      * @param method the method signature of the method that changed,
120      * <code>null</code> if no method was affected.
121      *
122      * @param field the field name where the change occured, <code>null</code>
123      * if no field was affected.
124      *
125      * @param args is a set of additional change-specific strings which are
126      * made available for the message description string to reference via
127      * the standard {n} syntax.
128      */

129     public ApiDifference(
130         Message message,
131         Severity binarySeverity, Severity sourceSeverity,
132         String JavaDoc clazz, String JavaDoc method, String JavaDoc field,
133         String JavaDoc[] args)
134     {
135         checkNonNull(message);
136         checkNonNull(binarySeverity);
137         checkNonNull(sourceSeverity);
138         checkNonNull(clazz);
139
140         this.message = message;
141         this.binaryCompatibilitySeverity = binarySeverity;
142         this.sourceCompatibilitySeverity = sourceSeverity;
143         this.affectedClass = clazz;
144         this.affectedField = field;
145         this.affectedMethod = method;
146         this.extraInfo = args;
147     }
148
149     /**
150      * Trivial utility method to verify that a specific object is non-null.
151      */

152     private void checkNonNull(Object JavaDoc o)
153     {
154         if (o == null)
155         {
156             throw new IllegalArgumentException JavaDoc();
157         }
158     }
159
160     /**
161      * Return the message object (if any) associated with this difference.
162      * <p>
163      * Checks which support the "new" message API will provide ApiDifference
164      * objects with non-null message objects.
165      */

166     public Message getMessage()
167     {
168         return message;
169     }
170
171     /**
172      * The Severity of the API difference in terms of binary compatibility.
173      * ERROR means that clients will definitely break, WARNING means that
174      * clients may break, depending on how they use the library.
175      * See the eclipse paper for further explanation.
176      *
177      * @return the severity of the API difference in terms of binary compatibility.
178      */

179     public Severity getBinaryCompatibilitySeverity()
180     {
181         return binaryCompatibilitySeverity;
182     }
183
184     /**
185      * The Severity of the API difference in terms of source compatibility.
186      * Sometimes this is different than {@link #getBinaryCompatibilitySeverity
187      * binary compatibility severity}, for example adding a checked exception
188      * to a method signature is binary compatible but not source compatible.
189      * ERROR means that clients will definitely break, WARNING means that
190      * clients may break, depending on how they use the library.
191      * See the eclipse paper for further explanation.
192      *
193      * @return the severity of the API difference in terms of source code
194      * compatibility.
195      */

196     public Severity getSourceCompatibilitySeverity()
197     {
198         return sourceCompatibilitySeverity;
199     }
200
201     /**
202      * Return the maximum of the binary and source compatibility severities.
203      */

204     public Severity getMaximumSeverity()
205     {
206         final Severity src = getSourceCompatibilitySeverity();
207         final Severity bin = getBinaryCompatibilitySeverity();
208         return src.compareTo(bin) < 0 ? bin : src;
209     }
210
211     /**
212      * Human readable api change description.
213      *
214      * @return a human readable description of this API difference.
215      */

216     public String JavaDoc getReport(MessageTranslator translator)
217     {
218         if (report != null)
219         {
220             return report;
221         }
222
223         String JavaDoc desc = translator.getDesc(message);
224         int nArgs = 0;
225         if (extraInfo != null)
226         {
227             nArgs = extraInfo.length;
228         }
229         String JavaDoc[] strings = new String JavaDoc[nArgs + 3];
230         strings[0] = affectedClass;
231         strings[1] = affectedMethod;
232         strings[2] = affectedField;
233         for (int i = 0; i < nArgs; ++i)
234         {
235             strings[i + 3] = extraInfo[i];
236         }
237
238         return java.text.MessageFormat.format(desc, strings);
239     }
240
241     /**
242      * The fully qualified class name of the class that has changed.
243      * @return fully qualified class name of the class that has changed.
244      */

245     public String JavaDoc getAffectedClass()
246     {
247         return affectedClass;
248     }
249
250     /**
251      * Method signature of the method that has changed, if any.
252      * @return method signature or <code>null</code> if no method is affected.
253      */

254     public String JavaDoc getAffectedMethod()
255     {
256         return affectedMethod;
257     }
258
259     /**
260      * Field name of the field that has changed, if any.
261      * @return field name or <code>null</code> if no field is affected.
262      */

263     public String JavaDoc getAffectedField()
264     {
265         return affectedField;
266     }
267
268     /**
269      * {@inheritDoc}
270      */

271     public String JavaDoc toString()
272     {
273         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
274         buf.append(message.getId());
275         appendCommonData(buf);
276         return buf.toString();
277     }
278
279     /**
280      * Get a human-readable description of this object. Intended for use by
281      * the unit tests.
282      */

283     public String JavaDoc toString(MessageTranslator translator)
284     {
285         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
286         buf.append(getReport(translator));
287         appendCommonData(buf);
288         return buf.toString();
289     }
290
291     /**
292      * Build a string containing a string representation of most of the
293      * fields in this object, but not the message-id or the string
294      * translation thereof.
295      */

296     private void appendCommonData(StringBuffer JavaDoc buf)
297     {
298         buf.append(" (");
299         buf.append(binaryCompatibilitySeverity);
300
301         if (sourceCompatibilitySeverity != binaryCompatibilitySeverity)
302         {
303             buf.append(",");
304             buf.append(sourceCompatibilitySeverity);
305         }
306
307         buf.append(") - ");
308         buf.append(affectedClass);
309         buf.append("[");
310         buf.append(affectedField);
311         buf.append("/");
312         buf.append(affectedMethod);
313         buf.append("]");
314     }
315 }
316
Popular Tags