/* * $Id$ * * Copyright 2006, The jCoderZ.org Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the jCoderZ.org Project nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jcoderz.phoenix.report; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import edu.umd.cs.findbugs.Detector; /** * Enumerated type of a severity. * * <p>The severity of a finding shall reflect the urgency of a * fix needed. Higher severity levels require more urgent actions * where lower levels might denote findings that are for information * only.</p> * * <p>This class also defines the weight of a finding * ({@link #getPenalty()} and thus * how much the quality is affected by the finding of * this severity.</p> * * <p>Instances of this class are immutable.</p> * * <p>The following severities are defined: * <ol> * <li>{@link #CPD}</li> * <li>{@link #WARNING}</li> * <li>{@link #DESIGN}</li> * <li>{@link #CODE_STYLE}</li> * <li>{@link #INFO}</li> * <li>{@link #COVERAGE}</li> * <li>{@link #FILTERED}</li> * </ol> * </p> * * @author Andreas Mandel */ public final class Severity implements Serializable, Comparable { /** * Scale of the penalty points. One penalty point marks * <code>1 / PENALTY_SCALE</code> lines as bad. */ public static final int PENALTY_SCALE = 10; private static final long serialVersionUID = 2L; /** Ordinal of next severity to be created. */ private static int sNextOrdinal = 0; /** Assign a ordinal to this severity. */ private final int mOrdinal = sNextOrdinal++; /** * The penalty for violations of this severity level. */ private final transient int mPenalty; /** The name of the severity */ private final transient String mName; /** Maps a string representation to an enumerated value. */ private static final Map FROM_STRING = new HashMap(); /** * Severity for filtered findings. * <p>Findings that are not appropriate for whatever reason * (ex. being a false positive) should get this level assigned by * the filtering style sheet.</p> * <p>A finding of this severity marks no lines of code as bad.</p> */ public static final Severity FILTERED = new Severity("filtered", 0); /** * Severity level used to denote no finding. */ public static final Severity OK = new Severity("ok", 0); /** * Severity for informational finders like to-do markers or code * that uses outdated API which should be updated but has no side * effect. * <p>A finding of this severity marks no lines of code as bad.</p> */ public static final Severity INFO = new Severity("info", 0); /** * Severity for code-style type of findings. * <p>All finders that report indentation, position of braces or this * kind of violation should use this level. There is no deeper * differentiation for this type of findings.</p> * <p>A finding of this severity marks 0.5 lines of code as bad.</p> */ public static final Severity CODE_STYLE = new Severity("code-style", 5); /** * Severity for code that is not covered by test cases. * <p>If code coverage is enabled each line with a coverage of 0 * gets marked with this violation.</p> * <p>A finding of this severity marks 0.8 lines of code as bad.</p> */ public static final Severity COVERAGE = new Severity("coverage", 8); /** * This severity level is for design related findings. * <p>Inheritance problems or broken implementation of standard methods * should get this severity level, unless {@link #ERROR} or * {@link #WARNING} fits better.</p> * <p>A finding of this severity marks three lines of code as bad.</p> */ public static final Severity DESIGN = new Severity("design", 30); /** * Warning level severities. * <p>A finding of this severity marks 5 lines of code as bad.</p> */ public static final Severity WARNING = new Severity("warning", 50); /** * Detected copied & pasted code. * <p>The copy and paste detector detected a number of similar lines * at a different position. This should be refactored immediately.</p> * <p>A finding of this severity marks 10 lines of code as bad.</p> */ public static final Severity CPD = new Severity("cpd", 100); /** * Severe findings requiring immediate action. * <p>Findings of this severity are serious errors. Finders that detect * style or design violations or finders that produce a certain number * of false positives must not use this severity.</p> * <p>Findings of this severity should prevent a project from being * released. A severity of this level marks 10 lines as bad.</p> */ public static final Severity ERROR = new Severity("error", 100); /** * The maximum possible severity. * Is {@link #ERROR}. */ public static final Severity MAX_SEVERITY = ERROR; /** The maximum possible severity as int. */ public static final int MAX_SEVERITY_INT = MAX_SEVERITY.toInt(); /** Internal list of all available severities. */ private static final Severity[] PRIVATE_VALUES = { Severity.FILTERED, Severity.OK, Severity.COVERAGE, Severity.INFO, Severity.CODE_STYLE, Severity.DESIGN, Severity.WARNING, Severity.CPD, Severity.ERROR }; /** Immutable list of the severities. */ public static final List VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES)); /** Private Constructor. */ private Severity (String name, int penalty) { mName = name; mPenalty = penalty; FROM_STRING.put(mName, this); } /** * Creates a Severity object from its int representation. * * @param i the int representation of the severity to be returned. * @return the Severity object represented by this int. * @throws IllegalArgumentException If the assigned int value isn't * listed in the internal severity table */ public static Severity fromInt (int i) throws IllegalArgumentException { try { return PRIVATE_VALUES[i]; } catch (ArrayIndexOutOfBoundsException e) { final IllegalArgumentException ex = new IllegalArgumentException( "Illegal int representation " + i + " of Severity"); ex.initCause(e); throw ex; } } /** * Creates a Severity object from its String representation. * * @param str the string representation of the severity to be * returned. * @return the Severity object represented by this string. * @throws IllegalArgumentException If the given string value isn't * listed in the internal severity table */ public static Severity fromString (String str) throws IllegalArgumentException { final Severity result = (Severity) FROM_STRING.get(str); if (result == null) { throw new IllegalArgumentException( "Illegal string representation " + str + " of Severity"); } return result; } /** * Returns the int representation of this severity. * @return the int representation of this severity. */ public int toInt () { return mOrdinal; } /** * Returns the String representation of this severity. * @return the String representation of this severity. */ public String toString () { return mName; } /** * Returns the penalty assigned to findings of this severity. * The number is the ten times the number of lines a finding of this * severity should mark as bad. * @return the penalty assigned to this severity. */ public int getPenalty () { return mPenalty; } /** {@inheritDoc} */ public int compareTo (Object o) { return mOrdinal - ((Severity) o).mOrdinal; } /** {@inheritDoc} */ public boolean equals (Object o) { return (o instanceof Severity) && (mOrdinal == ((Severity) o).mOrdinal); } /** {@inheritDoc} */ public int hashCode () { return mOrdinal; } /** * Parses the findbugs severity representation. * @param priority the string read from the xml * @return the jCoderZ severity representation. */ public static Severity fromFindBugsPriority (String priority) { final Severity ret; switch (Integer.parseInt(priority)) { case Detector.IGNORE_PRIORITY: ret = Severity.FILTERED; break; case Detector.EXP_PRIORITY: /* fall through */ case Detector.LOW_PRIORITY: ret = Severity.INFO; break; case Detector.NORMAL_PRIORITY: ret = Severity.WARNING; break; case Detector.HIGH_PRIORITY: ret = Severity.ERROR; break; default : throw new RuntimeException("Unknown priority from FindBugs: " + priority); } return ret; } /** * Converts the jCoderZ priority in the FindBugs XML representation. * @return the jCoderZ priority in FindBugs XML representation. */ public String toFindBugsPriority () { final String ret; if (Severity.ERROR == this) { ret = String.valueOf(Detector.HIGH_PRIORITY); } else if (Severity.WARNING == this) { ret = String.valueOf(Detector.NORMAL_PRIORITY); } else if (Severity.FILTERED == this) { ret = String.valueOf(Detector.IGNORE_PRIORITY); } else { ret = String.valueOf(Detector.LOW_PRIORITY); } return ret; } /** * Returns the maximum severe code of this and the given severity. * @param other the severity to compare with. * @return the maximum severe code of this and the given severity. */ public Severity max (Severity other) { final Severity result; if (compareTo(other) > 0) { result = this; } else { result = other; } return result; } /** * Resolves instances being de-serialized to a single instance * per severity. */ private Object readResolve () { return PRIVATE_VALUES[mOrdinal]; } }