/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * 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 Business Objects 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR 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. */ /* * Status.java * Creation date: Sep 23, 2002. * By: Edward Lam */ package org.openquark.cal.services; import org.openquark.cal.compiler.CompilerMessage; import org.openquark.cal.compiler.MessageKind; /** * A class representing the status of an action. * @author Edward Lam */ public class Status { /* * Implementation note: * There is a bit of a problem here, as this class doubles as a logger. * This class should probably be split up into at least two pieces: * - a logger * - a message to be logged. * The ability to log a tree-structured message could potentially be preserved by logging other loggers as messages. * There should also be simple (leaf) messages which are guaranteed not to have children / be mutable. */ /** The severity level of this status. */ private Severity severity = Severity.OK; /** The message associated with this status. */ private final String message; /** The associated throwable, or null if none. */ private Throwable throwable; /** The child status objects. */ private Status[] children = new Status[0]; /** * Severity enum pattern. * @author Edward Lam */ public static final class Severity implements Comparable<Severity> { /** The default status level. */ public static final Severity OK = new Severity("Ok", 0); /** Purely informational, and not a problem of any sort. */ public static final Severity INFO = new Severity("Info", 1); /** * A problem that does not prevent the program from continuing in the regular way, * but nevertheless may be of interest to the user as it indicates a potential problem. */ public static final Severity WARNING = new Severity("Warning", 2); /** A problem which prevents the program from continuing in the regular way. */ public static final Severity ERROR = new Severity("Error", 3); private final int level; private final String typeString; /** * Constructor for a Severity object. */ private Severity(String s, int level) { typeString = s; this.level = level; } /** * Get the severity. This number should only be used for comparative purposes. * @return int the comparative severity level */ public int getLevel(){ return level; } /** * @return the internal string describing the severity level. */ public String getTypeString() { return typeString; } /** * {@inheritDoc} */ @Override public String toString() { return typeString + "(" + level + ")"; } /** * {@inheritDoc} */ public int compareTo(Severity otherSeverity) { int otherLevel = otherSeverity.getLevel(); if (level < otherLevel) { return -1; } else if (level == otherLevel) { return 0; } else { return 1; } } } /** * Constructor for a Status. * @param message The message associated with this status object. */ public Status(String message) { Assert.isNotNullArgument(message, "message"); this.message = message; } /** * Constructor for a Status. * * @param message The message associated with this status object. * @param throwable the associated throwable, or null if none. */ public Status(String message, Throwable throwable) { this(message); this.throwable = throwable; } /** * Constructor for a Status. * * @param severity the status severity. * @param message The message associated with this status object. */ public Status(Severity severity, String message) { this(severity, message, null); } /** * Constructor for a Status. * * @param severity the status severity. * @param message The message associated with this status object. * @param throwable the associated throwable, or null if none. */ public Status(Severity severity, String message, Throwable throwable) { this(message, throwable); this.severity = severity; } /** * @return the associated Throwable object, or null if none. */ public Throwable getThrowable() { return throwable; } /** * @return the associated message. */ public String getMessage() { return message; } /** * Returns a string representation of the status, suitable for debugging purposes only. * @return a string representation of the status and its children, suitable for debugging purposes. */ public String getDebugMessage() { StringBuilder sb = new StringBuilder(); // If the status has children, it's just the component statuses if (children.length > 0) { for (int i = 0; i < children.length; i++) { if (i != 0) { sb.append("\n"); } sb.append(children[i].getDebugMessage()); } } else { sb.append(this.severity.getTypeString().toUpperCase() + ": "); sb.append(message); if (throwable != null) { sb.append(' '); sb.append(throwable); } } return sb.toString(); } /** * @return the severity */ public Severity getSeverity() { return severity; } /** * Return whether the severity of this status is OK. * @return whether the associated severity is Severity.OK. */ public boolean isOK() { return severity == Severity.OK; } /** * Add a given status as a child of this status. * * @param status the new child status */ public void add(Status status) { Assert.isNotNullArgument(status, "status"); Status[] newChildren = new Status[children.length + 1]; System.arraycopy(children, 0, newChildren, 0, children.length); newChildren[newChildren.length - 1] = status; this.children = newChildren; Severity newSev = status.getSeverity(); if (newSev.getLevel() > severity.getLevel()) { this.severity = newSev; } } /** * Returns a list of status object immediately contained in this * status, or an empty list if this is not a multi-status. * * @return an array of status objects */ public Status[] getChildren() { return children; } /** * Returns a string representation of the status, suitable for debugging purposes only. * @return the string representation. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Status "); sb.append(severity.getTypeString()); sb.append(' '); sb.append(message); if (throwable != null) { sb.append(' '); sb.append(throwable); } sb.append(" children=["); for (int i = 0; i < children.length; i++) { if (i != 0) { sb.append(" "); } sb.append(children[i].toString()); } sb.append("]"); return sb.toString(); } /** * @return a CompilerMessage which corresponds to this status object. */ public CompilerMessage asCompilerMessage() { if (severity == Severity.OK || severity == Severity.INFO) { return new CompilerMessage(new MessageKind.Info.DebugMessage(getDebugMessage())); } else if (severity == Severity.WARNING) { return new CompilerMessage(new MessageKind.Warning.DebugMessage(getDebugMessage())); } else if (severity == Severity.ERROR) { return new CompilerMessage(new MessageKind.Error.DebugMessage(getDebugMessage())); } else { throw new IllegalStateException("Unknown Severity type:" + severity); } } }