/* * Copyright 2013-2016 Cel Skeggs * * This file is part of the CCRE, the Common Chicken Runtime Engine. * * The CCRE 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 3 of the License, or (at your option) any * later version. * * The CCRE 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 the CCRE. If not, see <http://www.gnu.org/licenses/>. */ package ccre.log; import java.io.Serializable; import java.util.Iterator; import java.util.NoSuchElementException; import ccre.verifier.FlowPhase; /** * Represents a Logging level. This represents how important/severe a logging * message is. The levels are, in order of descending severity: severe, warning, * info, config, fine, finer, finest. * * @author skeggsc */ public class LogLevel implements Serializable { private static final long serialVersionUID = 6646883245419060561L; /** * A severe error. This usually means that something major didn't work, or * an impossible condition occurred. */ public static final LogLevel SEVERE = new LogLevel(9, "SEVERE"); /** * A warning. This usually means that something bad happened, but most * things should probably still work. */ public static final LogLevel WARNING = new LogLevel(6, "WARNING"); /** * A piece of info. This usually means something happened that the user * might want to know. */ public static final LogLevel INFO = new LogLevel(3, "INFO"); /** * A piece of configuration information. This usually means something that * isn't really important, but is something triggered by configuration * instead of normal operation. */ public static final LogLevel CONFIG = new LogLevel(0, "CONFIG"); /** * A top-level debugging message. This can be caused by anything, but * probably shouldn't be logged particularly often. */ public static final LogLevel FINE = new LogLevel(-3, "FINE"); /** * A mid-level debugging message. This can be caused by anything, and can be * logged relatively often. */ public static final LogLevel FINER = new LogLevel(-6, "FINER"); /** * A low-level debugging message. This can be caused by anything, and might * be called many times per second. */ public static final LogLevel FINEST = new LogLevel(-9, "FINEST"); private static final LogLevel[] levels = new LogLevel[] { FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE }; /** * A read-only iterator that iterates over all of the logging levels, from * FINEST to SEVERE, in that order. */ public static final Iterable<LogLevel> allLevels = () -> new Iterator<LogLevel>() { private int i = 0; @Override public boolean hasNext() { return i < levels.length; } @Override public LogLevel next() { if (!hasNext()) { throw new NoSuchElementException(); } return levels[i++]; } }; /** * Get a LogLevel from its ID level. This should probably only be called on * the result of toByte. An IllegalArgumentException will be thrown for * invalid IDs. * * @param id the ID of the LogLevel. * @return the LogLevel with this ID. * @see #id * @see #toByte(ccre.log.LogLevel) * @throws IllegalArgumentException if the ID is invalid. */ @FlowPhase public static LogLevel fromByte(byte id) { if ((id + 9) % 3 != 0 || id < -9 || id > 9) { throw new IllegalArgumentException("Invalid LogLevel ID: " + id); } return levels[(id + 9) / 3]; } /** * Return a byte representing this logging level - that is, its ID. Used in * fromByte. * * @param level the LogLevel to serialize. * @return the byte version of the LogLevel. * @see #id * @see #fromByte(byte) */ public static byte toByte(LogLevel level) { return level.id; } /** * The ID of the LogLevel. The higher, the more severe. SEVERE is 9, FINEST * is -9, for example. */ public final byte id; /** * The long-form message representing this level. */ public final String message; private LogLevel(int id, String msg) { // this means that id cannot be out of byte's range! this.id = (byte) id; message = msg; } /** * Check if this logging level is at least as important/severe as the other * logging level. * * @param other the logging level to compare to. * @return if this is at least as important. */ public boolean atLeastAsImportant(LogLevel other) { return id >= other.id; } /** * Convert this LogLevel to a string. Returns the message. * * @return the message. */ @Override public String toString() { return message; } private Object readResolve() { return fromByte(id); } /** * Get the next (more severe) LogLevel, or the least severe if the current * level is the most severe. * * The idea is that this can be used in a user interface to iterate around * the list of LogLevels. * * @return the next LogLevel. */ public LogLevel next() { for (int i = 0; i < levels.length - 1; i++) { if (levels[i] == this) { return levels[i + 1]; } } return levels[0]; } }