/* * 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(this.timestamp, o.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; } }