001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2005, University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs;
021:
022: import edu.umd.cs.findbugs.model.ClassNameRewriter;
023: import edu.umd.cs.findbugs.model.ClassNameRewriterUtil;
024: import edu.umd.cs.findbugs.model.IdentityClassNameRewriter;
025:
026: /**
027: * Very sloppy bug comparator: if the warnings are of the same type,
028: * and in the same class/method/field, assume they are the same.
029: *
030: * @author David Hovemeyer
031: */
032: public class SloppyBugComparator implements WarningComparator {
033:
034: private static final boolean DEBUG = SystemProperties
035: .getBoolean("sloppyComparator.debug");
036:
037: private static final long serialVersionUID = 1L;
038:
039: private ClassNameRewriter classNameRewriter = IdentityClassNameRewriter
040: .instance();
041:
042: /**
043: * Constructor.
044: */
045: public SloppyBugComparator() {
046: }
047:
048: public void setClassNameRewriter(ClassNameRewriter classNameRewriter) {
049: this .classNameRewriter = classNameRewriter;
050: }
051:
052: private int compareNullElements(Object lhs, Object rhs) {
053: if (lhs == null && rhs == null)
054: return 0;
055: else
056: return (lhs == null) ? -1 : 1;
057: }
058:
059: /**
060: * Compare class annotations.
061: *
062: * @param lhs left hand class annotation
063: * @param rhs right hand class annotation
064: * @return comparison of the class annotations
065: */
066: private int compareClassesAllowingNull(ClassAnnotation lhs,
067: ClassAnnotation rhs) {
068: if (lhs == null || rhs == null) {
069: return compareNullElements(lhs, rhs);
070: }
071:
072: String lhsClassName = classNameRewriter.rewriteClassName(lhs
073: .getClassName());
074: String rhsClassName = classNameRewriter.rewriteClassName(rhs
075: .getClassName());
076:
077: if (DEBUG)
078: System.err.println("Comparing " + lhsClassName + " and "
079: + rhsClassName);
080:
081: int cmp = lhsClassName.compareTo(rhsClassName);
082: if (DEBUG)
083: System.err.println("\t==> " + cmp);
084: return cmp;
085: }
086:
087: private int compareMethodsAllowingNull(MethodAnnotation lhs,
088: MethodAnnotation rhs) {
089: if (lhs == null || rhs == null) {
090: return compareNullElements(lhs, rhs);
091: }
092:
093: lhs = convertMethod(lhs);
094: rhs = convertMethod(rhs);
095:
096: return lhs.compareTo(rhs);
097: }
098:
099: private int compareFieldsAllowingNull(FieldAnnotation lhs,
100: FieldAnnotation rhs) {
101: if (lhs == null || rhs == null) {
102: return compareNullElements(lhs, rhs);
103: }
104:
105: lhs = convertField(lhs);
106: rhs = convertField(rhs);
107:
108: if (DEBUG)
109: System.err
110: .println("Compare fields: " + lhs + " and " + rhs);
111:
112: return lhs.compareTo(rhs);
113: }
114:
115: private MethodAnnotation convertMethod(
116: MethodAnnotation methodAnnotation) {
117: return ClassNameRewriterUtil.convertMethodAnnotation(
118: classNameRewriter, methodAnnotation);
119: }
120:
121: private FieldAnnotation convertField(FieldAnnotation fieldAnnotation) {
122: return ClassNameRewriterUtil.convertFieldAnnotation(
123: classNameRewriter, fieldAnnotation);
124: }
125:
126: /* (non-Javadoc)
127: * @see edu.umd.cs.findbugs.WarningComparator#compare(edu.umd.cs.findbugs.BugInstance, edu.umd.cs.findbugs.BugInstance)
128: */
129: public int compare(BugInstance lhs, BugInstance rhs) {
130:
131: int cmp;
132:
133: // Bug abbrevs must match
134: BugPattern lhsPattern = lhs.getBugPattern();
135: BugPattern rhsPattern = rhs.getBugPattern();
136: String lhsAbbrev, rhsAbbrev;
137: if (lhsPattern == null || rhsPattern == null) {
138: lhsAbbrev = getAbbrevFromBugType(lhs.getType());
139: rhsAbbrev = getAbbrevFromBugType(rhs.getType());
140: } else {
141: lhsAbbrev = lhsPattern.getAbbrev();
142: rhsAbbrev = rhsPattern.getAbbrev();
143: }
144: cmp = lhsAbbrev.compareTo(rhsAbbrev);
145: if (cmp != 0) {
146: if (DEBUG)
147: System.err.println("bug abbrevs do not match");
148: return cmp;
149: }
150:
151: // Primary class must match
152: cmp = compareClassesAllowingNull(lhs.getPrimaryClass(), rhs
153: .getPrimaryClass());
154: if (cmp != 0)
155: return cmp;
156:
157: // Primary method must match (if any)
158: cmp = compareMethodsAllowingNull(lhs.getPrimaryMethod(), rhs
159: .getPrimaryMethod());
160: if (cmp != 0) {
161: if (DEBUG)
162: System.err.println("primary methods do not match");
163: return cmp;
164: }
165:
166: // Primary field must match (if any)
167: cmp = compareFieldsAllowingNull(lhs.getPrimaryField(), rhs
168: .getPrimaryField());
169: if (cmp != 0) {
170: if (DEBUG)
171: System.err.println("primary fields do not match");
172: return cmp;
173: }
174:
175: // Assume they're the same
176: return 0;
177: }
178:
179: /**
180: * @param type
181: * @return
182: */
183: private static String getAbbrevFromBugType(String type) {
184: int bar = type.indexOf('_');
185: return (bar >= 0) ? type.substring(0, bar) : "";
186: }
187: }
|