/* * FindBugs - Find Bugs in Java programs * Copyright (C) 2006, University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.umd.cs.findbugs; import java.io.IOException; import java.io.Serializable; import javax.annotation.Nonnull; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.cloud.Cloud.UserDesignation; import edu.umd.cs.findbugs.util.Util; import edu.umd.cs.findbugs.xml.XMLAttributeList; import edu.umd.cs.findbugs.xml.XMLOutput; import edu.umd.cs.findbugs.xml.XMLWriteable; /** * class to hold the user annotation and user designation for a BugInstance */ public class BugDesignation implements XMLWriteable, Serializable, Comparable<BugDesignation> { /** * The default key for the user designation. Bad things could happen if this * key isn't in getUserDesignations() */ public static final String UNCLASSIFIED = UserDesignation.UNCLASSIFIED.name(); /** * user designation -- value should be one of the keys returned by * I18N.getInstance().getUserDesignations() */ @NonNull private String designation = UNCLASSIFIED; @Override public String toString() { String result = designation; if (user != null) result += " by " + user; if (annotationText != null && annotationText.length() > 0) result += " : " + annotationText; return result; } private boolean dirty; public boolean isDirty() { return dirty; } public void cleanDirty() { dirty = false; } private @javax.annotation.CheckForNull String user; public BugDesignation() { } /** * @param designation * @param timestamp * @param annotationText * @param user */ public BugDesignation(String designation, long timestamp, String annotationText, String user) { this.designation = designation; this.timestamp = timestamp; this.annotationText = annotationText; this.user = user; } public BugDesignation(BugDesignation that) { this(that.designation, that.timestamp, that.annotationText, that.user); } private long timestamp = System.currentTimeMillis(); /** free text from the user */ // TODO: make this @CheckForNull private String annotationText; /** * return the user designation E.g., "MOSTLY_HARMLESS", "CRITICAL", * "NOT_A_BUG", etc. * * Note that this is the key, suitable for writing to XML, but not for * showing to the user. * * @see I18N#getUserDesignation(String key) */ @NonNull public String getDesignationKey() { return designation; } /** * set the user designation E.g., "MOSTLY_HARMLESS", "CRITICAL", * "NOT_A_BUG", etc. * * If the argument is null, it will be treated as UNCLASSIFIED. * * Note that this is the key, suitable for writing to XML, but not what the * user sees. Strange things could happen if designationKey is not one of * the keys returned by I18N.instance().getUserDesignations(). * * @see I18N#getUserDesignationKeys() */ public void setDesignationKey(String designationKey) { if (designation.equals(designationKey)) return; dirty = true; timestamp = System.currentTimeMillis(); designation = (designationKey != null ? designationKey : UNCLASSIFIED); } @CheckForNull public String getUser() { return user; } public void setUser(String u) { user = u; } public long getTimestamp() { return timestamp; } public void setTimestamp(long ts) { if (timestamp != ts) { timestamp = ts; dirty = true; } } @CheckForNull public String getAnnotationText() { return annotationText; } @Nonnull public String getNonnullAnnotationText() { if (annotationText == null) return ""; return annotationText; } public void setAnnotationText(String s) { if (s.equals(annotationText)) return; dirty = true; annotationText = s; timestamp = System.currentTimeMillis(); } public void writeXML(XMLOutput xmlOutput) throws IOException { XMLAttributeList attributeList = new XMLAttributeList(); // all three of these xml attributes are optional if (designation != null && !UNCLASSIFIED.equals(designation)) attributeList.addAttribute("designation", designation); if (user != null && !"".equals(user)) attributeList.addAttribute("user", user); if (timestamp > 0) attributeList.addAttribute("timestamp", String.valueOf(timestamp)); if ((annotationText != null && !"".equals(annotationText))) { xmlOutput.openTag("UserAnnotation", attributeList); xmlOutput.writeCDATA(annotationText); xmlOutput.closeTag("UserAnnotation"); } else { xmlOutput.openCloseTag("UserAnnotation", attributeList); } } /** * replace unset fields of this user designation with values set in the * other */ public void merge(@CheckForNull BugDesignation other) { if (other == null) return; boolean changed = false; if ((annotationText == null || annotationText.length() == 0) && other.annotationText != null && other.annotationText.length() > 0) { annotationText = other.annotationText; dirty = true; changed = true; } if ((designation == null || UNCLASSIFIED.equals(designation) || designation.length() == 0) && other.designation != null && other.designation.length() > 0) { designation = other.designation; dirty = true; changed = true; } if (!changed) return; // if no changes don't even try to copy user or timestamp if ((user == null || user.length() == 0) && other.user != null && other.user.length() > 0) { user = other.user; } if (timestamp == 0 && other.timestamp != 0) { timestamp = other.timestamp; } } @Override public int hashCode() { int hash = (int) this.timestamp; if (user != null) hash += user.hashCode(); if (designation != null) hash += designation.hashCode(); if (annotationText != null) hash += annotationText.hashCode(); return hash; } @Override public boolean equals(Object o) { if (!(o instanceof BugDesignation)) return false; return this.compareTo((BugDesignation) o) == 0; } public int compareTo(BugDesignation o) { if (this == o) return 0; int result = Util.compare(o.timestamp, this.timestamp); if (result != 0) return result; result = Util.nullSafeCompareTo(this.user, o.user); if (result != 0) return result; result = Util.nullSafeCompareTo(this.designation, o.designation); if (result != 0) return result; result = Util.nullSafeCompareTo(this.annotationText, o.annotationText); if (result != 0) return result; return 0; } }