From: aclement Date: Wed, 14 Jul 2010 23:19:53 +0000 (+0000) Subject: generics X-Git-Tag: V1_6_10RC1~102 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b38e0f133ab326b156348712efc91b7ecc06a5b3;p=aspectj.git generics --- diff --git a/bridge/src/org/aspectj/bridge/AbortException.java b/bridge/src/org/aspectj/bridge/AbortException.java index 7c4ed13af..acde7cd28 100644 --- a/bridge/src/org/aspectj/bridge/AbortException.java +++ b/bridge/src/org/aspectj/bridge/AbortException.java @@ -18,23 +18,23 @@ import java.io.PrintWriter; import java.util.ArrayList; /** - * Signal that a process was aborted before completion. - * This may contain a structured IMessage which indicates - * why the process was aborted (e.g., the underlying exception). - * For processes using try/catch to complete a method abruptly - * but complete the process normally (e.g., a test failure - * causes the test to abort but the reporting and testing continues - * normally), use the static methods to borrow and return a "porter" - * to avoid the expense of constructing a stack trace each time. - * A porter stack trace is invalid, and it should only be used - * to convey a message. E.g., to print the stack of the - * AbortException and any contained message: - *
catch (AbortException ae) {
+ * Signal that a process was aborted before completion. This may contain a structured IMessage which indicates why the process was
+ * aborted (e.g., the underlying exception). For processes using try/catch to complete a method abruptly but complete the process
+ * normally (e.g., a test failure causes the test to abort but the reporting and testing continues normally), use the static methods
+ * to borrow and return a "porter" to avoid the expense of constructing a stack trace each time. A porter stack trace is invalid,
+ * and it should only be used to convey a message. E.g., to print the stack of the AbortException and any contained message:
+ * 
+ * 
+ * catch (AbortException ae) {
  *     IMessage m = ae.getMessage();
  *     if (!ae.isPorter()) ae.printStackTrace(System.err);
  *     Throwable thrown = ae.getThrown();
  *     if (null != thrown) thrown.printStackTrace(System.err);
- * }
+ * } + *
+ * + * @author PARC + * @author Andy Clement */ public class AbortException extends RuntimeException { // XXX move porters out, handle proxy better @@ -42,189 +42,185 @@ public class AbortException extends RuntimeException { // XXX move porters out, private boolean isSilent = false; - /** used when message text is null */ - public static final String NO_MESSAGE_TEXT - = "AbortException (no message)"; - - private static final ArrayList porters = new ArrayList(); - - /** - * Get a porter exception from the pool. - * Porter exceptions do not have valid stack traces. - * They are used only to avoid generating stack traces when - * using throw/catch to abruptly complete but continue. - */ - public static AbortException borrowPorter(IMessage message) { - AbortException result; - synchronized(porters) { - if (porters.size() > 0) { - result = (AbortException) porters.get(0); - } else { - result = new AbortException(); - result.setIsSilent(false); - } - } - result.setIMessage(message); - result.isPorter = true; - return result; - } - - /** - * Return (or add) a porter exception to the pool. - */ - public static void returnPorter(AbortException porter) { - synchronized(porters) { - if (porters.contains(porter)) { - throw new IllegalStateException("already have " + porter); - } else { - porters.add(porter); - } - } - } - - /** @return NO_MESSAGE_TEXT or message.getMessage() if not null */ - private static String extractMessage(IMessage message) { - if (null == message) { - return NO_MESSAGE_TEXT; - } else { - String m = message.getMessage(); - if (null == m) { - return NO_MESSAGE_TEXT; - } else { - return m; - } - } - } - - /** structured message abort */ - protected IMessage message; - - /** true if this is a porter exception - only used to hold message */ - protected boolean isPorter; - - /** abort with default String message */ - public AbortException() { - this("ABORT"); - isSilent = true; - } - - /** abort with message */ - public AbortException(String s) { - super(null != s ? s : NO_MESSAGE_TEXT); - this.message = null; - } - - /** abort with structured message */ - public AbortException(IMessage message) { - super(extractMessage(message)); - this.message = message; - } - - /** @return IMessage structured message, if set */ - public IMessage getIMessage() { - return message; - } - - /** - * The stack trace of a porter is invalid; it is only used - * to carry a message (which may itself have a wrapped exception). - * @return true if this exception is only to carry exception - */ - public boolean isPorter() { - return isPorter; - } - - /** @return Throwable at bottom of IMessage chain, if any */ - public Throwable getThrown() { - Throwable result = null; - IMessage m = getIMessage(); - if (null != m) { - result = m.getThrown(); - if (result instanceof AbortException) { - return ((AbortException) result).getThrown(); - } - } - return result; - } - - private void setIMessage(IMessage message) { - this.message = message; - } - - // ----------- proxy attempts - /** - * Get message for this AbortException, - * either associated explicitly as message - * or implicitly as IMessage message or - * its thrown message. + /** used when message text is null */ + public static final String NO_MESSAGE_TEXT = "AbortException (no message)"; + + private static final ArrayList porters = new ArrayList(); + + /** + * Get a porter exception from the pool. Porter exceptions do not have valid stack traces. They are used only to avoid + * generating stack traces when using throw/catch to abruptly complete but continue. + */ + public static AbortException borrowPorter(IMessage message) { + AbortException result; + synchronized (porters) { + if (porters.size() > 0) { + result = porters.get(0); + } else { + result = new AbortException(); + result.setIsSilent(false); + } + } + result.setIMessage(message); + result.isPorter = true; + return result; + } + + /** + * Return (or add) a porter exception to the pool. + */ + public static void returnPorter(AbortException porter) { + synchronized (porters) { + if (porters.contains(porter)) { + throw new IllegalStateException("already have " + porter); + } else { + porters.add(porter); + } + } + } + + /** @return NO_MESSAGE_TEXT or message.getMessage() if not null */ + private static String extractMessage(IMessage message) { + if (null == message) { + return NO_MESSAGE_TEXT; + } else { + String m = message.getMessage(); + if (null == m) { + return NO_MESSAGE_TEXT; + } else { + return m; + } + } + } + + /** structured message abort */ + protected IMessage message; + + /** true if this is a porter exception - only used to hold message */ + protected boolean isPorter; + + /** abort with default String message */ + public AbortException() { + this("ABORT"); + isSilent = true; + } + + /** abort with message */ + public AbortException(String s) { + super(null != s ? s : NO_MESSAGE_TEXT); + this.message = null; + } + + /** abort with structured message */ + public AbortException(IMessage message) { + super(extractMessage(message)); + this.message = message; + } + + /** @return IMessage structured message, if set */ + public IMessage getIMessage() { + return message; + } + + /** + * The stack trace of a porter is invalid; it is only used to carry a message (which may itself have a wrapped exception). + * + * @return true if this exception is only to carry exception + */ + public boolean isPorter() { + return isPorter; + } + + /** @return Throwable at bottom of IMessage chain, if any */ + public Throwable getThrown() { + Throwable result = null; + IMessage m = getIMessage(); + if (null != m) { + result = m.getThrown(); + if (result instanceof AbortException) { + return ((AbortException) result).getThrown(); + } + } + return result; + } + + private void setIMessage(IMessage message) { + this.message = message; + } + + // ----------- proxy attempts + /** + * Get message for this AbortException, either associated explicitly as message or implicitly as IMessage message or its thrown + * message. + * * @see java.lang.Throwable#getMessage() */ public String getMessage() { - String message = super.getMessage(); - if ((null == message) || (NO_MESSAGE_TEXT == message)) { - IMessage m = getIMessage(); - if (null != m) { - message = m.getMessage(); - if (null == message) { - Throwable thrown = m.getThrown(); - if (null != thrown) { - message = thrown.getMessage(); - } - } - } - if (null == message) { - message = NO_MESSAGE_TEXT; // better than nothing - } - } - return message; - } - - /** + String message = super.getMessage(); + if ((null == message) || (NO_MESSAGE_TEXT == message)) { + IMessage m = getIMessage(); + if (null != m) { + message = m.getMessage(); + if (null == message) { + Throwable thrown = m.getThrown(); + if (null != thrown) { + message = thrown.getMessage(); + } + } + } + if (null == message) { + message = NO_MESSAGE_TEXT; // better than nothing + } + } + return message; + } + + /** * @see java.lang.Throwable#printStackTrace() */ public void printStackTrace() { - printStackTrace(System.out); + printStackTrace(System.out); } - /** - * Print the stack trace of any enclosed thrown - * or this otherwise. + /** + * Print the stack trace of any enclosed thrown or this otherwise. + * * @see java.lang.Throwable#printStackTrace(PrintStream) */ public void printStackTrace(PrintStream s) { - IMessage m = getIMessage(); - Throwable thrown = (null == m? null : m.getThrown()); - if (!isPorter() || (null == thrown)) { - s.println("Message: " + m); - super.printStackTrace(s); - } else { - thrown.printStackTrace(s); - } - } - - /** - * Print the stack trace of any enclosed thrown - * or this otherwise. - * @see java.lang.Throwable#printStackTrace(PrintWriter) - */ - public void printStackTrace(PrintWriter s) { - IMessage m = getIMessage(); - Throwable thrown = (null == m? null : m.getThrown()); - if (null == thrown) { // Always print - if (isPorter()) { - s.println("(Warning porter AbortException without thrown)"); - } - s.println("Message: " + m); - super.printStackTrace(s); - } else { - thrown.printStackTrace(s); - } - } + IMessage m = getIMessage(); + Throwable thrown = (null == m ? null : m.getThrown()); + if (!isPorter() || (null == thrown)) { + s.println("Message: " + m); + super.printStackTrace(s); + } else { + thrown.printStackTrace(s); + } + } + + /** + * Print the stack trace of any enclosed thrown or this otherwise. + * + * @see java.lang.Throwable#printStackTrace(PrintWriter) + */ + public void printStackTrace(PrintWriter s) { + IMessage m = getIMessage(); + Throwable thrown = (null == m ? null : m.getThrown()); + if (null == thrown) { // Always print + if (isPorter()) { + s.println("(Warning porter AbortException without thrown)"); + } + s.println("Message: " + m); + super.printStackTrace(s); + } else { + thrown.printStackTrace(s); + } + } public boolean isSilent() { return isSilent; } - + public void setIsSilent(boolean isSilent) { this.isSilent = isSilent; } diff --git a/bridge/src/org/aspectj/bridge/CountingMessageHandler.java b/bridge/src/org/aspectj/bridge/CountingMessageHandler.java index 52d759678..4ce550876 100644 --- a/bridge/src/org/aspectj/bridge/CountingMessageHandler.java +++ b/bridge/src/org/aspectj/bridge/CountingMessageHandler.java @@ -15,148 +15,143 @@ package org.aspectj.bridge; import java.util.Enumeration; import java.util.Hashtable; -import java.util.Iterator; import org.aspectj.util.LangUtil; -/** - * Wrap an IMessageHandler to count messages handled. - * Messages being ignored by the delegate IMessageHandler are not counted. +/** + * Wrap an IMessageHandler to count messages handled. Messages being ignored by the delegate IMessageHandler are not counted. */ public class CountingMessageHandler implements IMessageHandler { - - public final IMessageHandler delegate; - public final CountingMessageHandler proxy; - private final Hashtable counters; - - public static CountingMessageHandler makeCountingMessageHandler(IMessageHandler handler) { - if (handler instanceof CountingMessageHandler) { - return (CountingMessageHandler)handler; - } else { - return new CountingMessageHandler(handler); - } - } - - - public CountingMessageHandler(IMessageHandler delegate) { - LangUtil.throwIaxIfNull(delegate, "delegate"); - this.delegate = delegate; - this.counters = new Hashtable(); - proxy = (delegate instanceof CountingMessageHandler - ? (CountingMessageHandler) delegate - : null); - } - - /** @return delegate.handleMessage(IMessage) */ - public boolean handleMessage(IMessage message) throws AbortException { - if (null != proxy) { - return proxy.handleMessage(message); - } - if (null != message) { - IMessage.Kind kind = message.getKind(); - if (!isIgnoring(kind)) { - increment(kind); - } - } - return delegate.handleMessage(message); - } - - /** @return delegate.isIgnoring(IMessage.Kind) */ - public boolean isIgnoring(IMessage.Kind kind) { - return delegate.isIgnoring(kind); - } - - /** - * Delegate - * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) - * @param kind - */ - public void dontIgnore(IMessage.Kind kind) { - delegate.dontIgnore(kind); - } - - /** - * Delegate - * @see org.aspectj.bridge.IMessageHandler#ignore(org.aspectj.bridge.IMessage.Kind) - * @param kind - */ + + public final IMessageHandler delegate; + public final CountingMessageHandler proxy; + private final Hashtable counters; + + public static CountingMessageHandler makeCountingMessageHandler(IMessageHandler handler) { + if (handler instanceof CountingMessageHandler) { + return (CountingMessageHandler) handler; + } else { + return new CountingMessageHandler(handler); + } + } + + public CountingMessageHandler(IMessageHandler delegate) { + LangUtil.throwIaxIfNull(delegate, "delegate"); + this.delegate = delegate; + this.counters = new Hashtable(); + proxy = (delegate instanceof CountingMessageHandler ? (CountingMessageHandler) delegate : null); + } + + /** @return delegate.handleMessage(IMessage) */ + public boolean handleMessage(IMessage message) throws AbortException { + if (null != proxy) { + return proxy.handleMessage(message); + } + if (null != message) { + IMessage.Kind kind = message.getKind(); + if (!isIgnoring(kind)) { + increment(kind); + } + } + return delegate.handleMessage(message); + } + + /** @return delegate.isIgnoring(IMessage.Kind) */ + public boolean isIgnoring(IMessage.Kind kind) { + return delegate.isIgnoring(kind); + } + + /** + * Delegate + * + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ + public void dontIgnore(IMessage.Kind kind) { + delegate.dontIgnore(kind); + } + + /** + * Delegate + * + * @see org.aspectj.bridge.IMessageHandler#ignore(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ public void ignore(IMessage.Kind kind) { delegate.ignore(kind); } - - /** @return delegate.toString() */ - public String toString() { - return delegate.toString(); - } - - /** - * Return count of messages seen through this interface. - * @param kind the IMessage.Kind of the messages to count - * (if null, count all) - * @param orGreater if true, then count this kind and any - * considered greater by the ordering of - * IMessage.Kind.COMPARATOR - * @return number of messages of this kind (optionally or greater) - * @see IMessage.Kind.COMPARATOR - */ - public int numMessages(IMessage.Kind kind, boolean orGreater) { - if (null != proxy) { - return proxy.numMessages(kind, orGreater); - } - int result = 0; - if (null == kind) { - for (Enumeration enu = counters.elements(); enu.hasMoreElements();) { - result += ((IntHolder) enu.nextElement()).count; + + /** @return delegate.toString() */ + public String toString() { + return delegate.toString(); + } + + /** + * Return count of messages seen through this interface. + * + * @param kind the IMessage.Kind of the messages to count (if null, count all) + * @param orGreater if true, then count this kind and any considered greater by the ordering of IMessage.Kind.COMPARATOR + * @return number of messages of this kind (optionally or greater) + * @see IMessage.Kind.COMPARATOR + */ + public int numMessages(IMessage.Kind kind, boolean orGreater) { + if (null != proxy) { + return proxy.numMessages(kind, orGreater); + } + int result = 0; + if (null == kind) { + for (Enumeration enu = counters.elements(); enu.hasMoreElements();) { + result += (enu.nextElement()).count; + } + } else if (!orGreater) { + result = numMessages(kind); + } else { + for (IMessage.Kind k : IMessage.KINDS) { + if (kind.isSameOrLessThan(k)) { + result += numMessages(k); + } } - } else if (!orGreater) { - result = numMessages(kind); - } else { - for (Iterator iter = IMessage.KINDS.iterator(); iter.hasNext();) { - IMessage.Kind k = (IMessage.Kind) iter.next(); - if (kind.isSameOrLessThan(k)) { - result += numMessages(k); - } - } - } - return result; - } - - /** - * @return true if 0 is less than - * numMessages(IMessage.ERROR, true) - */ - public boolean hasErrors() { - return (0 < numMessages(IMessage.ERROR, true)); - } - - private int numMessages(IMessage.Kind kind) { - if (null != proxy) { - return proxy.numMessages(kind); - } - IntHolder counter = (IntHolder) counters.get(kind); - return (null == counter ? 0 : counter.count); - } - - private void increment(IMessage.Kind kind) { - if (null != proxy) { - throw new IllegalStateException("not called when proxying"); - } - - IntHolder counter = (IntHolder) counters.get(kind); - if (null == counter) { - counter = new IntHolder(); - counters.put(kind, counter); - } - counter.count++; - } - - private static class IntHolder { - int count; - } - - public void reset() { - if (proxy != null) proxy.reset(); - counters.clear(); - } + } + return result; + } + + /** + * @return true if 0 is less than numMessages(IMessage.ERROR, true) + */ + public boolean hasErrors() { + return (0 < numMessages(IMessage.ERROR, true)); + } + + private int numMessages(IMessage.Kind kind) { + if (null != proxy) { + return proxy.numMessages(kind); + } + IntHolder counter = counters.get(kind); + return (null == counter ? 0 : counter.count); + } + + private void increment(IMessage.Kind kind) { + if (null != proxy) { + throw new IllegalStateException("not called when proxying"); + } + + IntHolder counter = counters.get(kind); + if (null == counter) { + counter = new IntHolder(); + counters.put(kind, counter); + } + counter.count++; + } + + private static class IntHolder { + int count; + } + + public void reset() { + if (proxy != null) { + proxy.reset(); + } + counters.clear(); + } } diff --git a/bridge/src/org/aspectj/bridge/IMessage.java b/bridge/src/org/aspectj/bridge/IMessage.java index 4f4728295..a32a631e6 100644 --- a/bridge/src/org/aspectj/bridge/IMessage.java +++ b/bridge/src/org/aspectj/bridge/IMessage.java @@ -90,11 +90,9 @@ public interface IMessage { /** @return source location associated with this message, or null if none */ ISourceLocation getSourceLocation(); - public static final class Kind implements Comparable { - public static final Comparator COMPARATOR = new Comparator() { - public int compare(Object o1, Object o2) { - Kind one = (Kind) o1; - Kind two = (Kind) o2; + public static final class Kind implements Comparable { + public static final Comparator COMPARATOR = new Comparator() { + public int compare(IMessage.Kind one, IMessage.Kind two) { if (null == one) { return (null == two ? 0 : -1); } else if (null == two) { @@ -115,7 +113,7 @@ public interface IMessage { return (0 >= COMPARATOR.compare(this, kind)); } - public int compareTo(Object other) { + public int compareTo(IMessage.Kind other) { return COMPARATOR.compare(this, other); } @@ -148,5 +146,5 @@ public interface IMessage { * being based on a subtype of a defining type. * @see AspectJ bug 41952 */ - public List getExtraSourceLocations(); + public List getExtraSourceLocations(); } diff --git a/bridge/src/org/aspectj/bridge/IMessageHolder.java b/bridge/src/org/aspectj/bridge/IMessageHolder.java index 324c5f039..fdf2a6779 100644 --- a/bridge/src/org/aspectj/bridge/IMessageHolder.java +++ b/bridge/src/org/aspectj/bridge/IMessageHolder.java @@ -18,53 +18,49 @@ import java.util.List; /** * Hold and query a collection of messages. */ -public interface IMessageHolder - extends IMessageHandler { // XXX do not extend - mix instead - // XXX go to LT EQ GT GE LE rather than simple orGreater +public interface IMessageHolder extends IMessageHandler { // XXX do not extend - mix instead + // XXX go to LT EQ GT GE LE rather than simple orGreater /** value for orGreater parameter */ public static final boolean ORGREATER = true; /** value for orGreater parameter */ public static final boolean EQUAL = false; - /** - * Tell whether this holder has any message of this kind - * (optionally or greater). + /** + * Tell whether this holder has any message of this kind (optionally or greater). + * * @param kind the IMessage.Kind to check for - accept any if null - * @param orGreater if true, also any greater than the target kind - * as determined by IMessage.Kind.COMPARATOR - * @return true if this holder has any message of this kind, - * or if orGreater and any message has a greater kind, - * as determined by IMessage.Kind.COMPARATOR + * @param orGreater if true, also any greater than the target kind as determined by IMessage.Kind.COMPARATOR + * @return true if this holder has any message of this kind, or if orGreater and any message has a greater kind, as determined + * by IMessage.Kind.COMPARATOR */ boolean hasAnyMessage(IMessage.Kind kind, boolean orGreater); /** - * Count the messages currently held by this holder. - * Pass null to get all kinds. + * Count the messages currently held by this holder. Pass null to get all kinds. + * * @param kind the IMessage.Kind expected, or null for all messages - * @param orGreater if true, also any greater than the target kind - * as determined by IMessage.Kind.COMPARATOR + * @param orGreater if true, also any greater than the target kind as determined by IMessage.Kind.COMPARATOR * @return number of IMessage held (now) by this holder */ int numMessages(IMessage.Kind kind, boolean orGreater); /** - * Get all messages or those of a specific kind. - * Pass null to get all kinds. + * Get all messages or those of a specific kind. Pass null to get all kinds. + * * @param kind the IMessage.Kind expected, or null for all messages - * @param orGreater if true, also get any greater than the target kind - * as determined by IMessage.Kind.COMPARATOR + * @param orGreater if true, also get any greater than the target kind as determined by IMessage.Kind.COMPARATOR * @return IMessage[] of messages of the right kind, or IMessage.NONE */ IMessage[] getMessages(IMessage.Kind kind, boolean orGreater); - - /** @return unmodifiable List view of underlying collection of IMessage */ - List getUnmodifiableListView(); - - /** - * Clear any messages. - * @throws UnsupportedOperationException if message list is read-only - */ - void clearMessages() throws UnsupportedOperationException; + + /** @return unmodifiable List view of underlying collection of IMessage */ + List getUnmodifiableListView(); + + /** + * Clear any messages. + * + * @throws UnsupportedOperationException if message list is read-only + */ + void clearMessages() throws UnsupportedOperationException; } diff --git a/bridge/src/org/aspectj/bridge/Message.java b/bridge/src/org/aspectj/bridge/Message.java index 91ccad4c1..a4f17072b 100644 --- a/bridge/src/org/aspectj/bridge/Message.java +++ b/bridge/src/org/aspectj/bridge/Message.java @@ -11,177 +11,168 @@ * Xerox/PARC initial implementation * ******************************************************************/ - package org.aspectj.bridge; import java.util.Arrays; import java.util.Collections; import java.util.List; - /** - * Implement messages. - * This implementation is immutable if ISourceLocation is immutable. + * Implement messages. This implementation is immutable if ISourceLocation is immutable. */ public class Message implements IMessage { - private final String message; - private final IMessage.Kind kind; - private final Throwable thrown; - private final ISourceLocation sourceLocation; - private final String details; - private final List/*SourceLocation*/ extraSourceLocations; - private final boolean declared; // Is it a DEOW ? - private final int id; - private final int sourceStart,sourceEnd; - - /** - * Create a (compiler) error or warning message - * @param message the String used as the underlying message - * @param location the ISourceLocation, if any, associated with this message - * @param isError if true, use IMessage.ERROR; else use IMessage.WARNING - */ - public Message(String message, ISourceLocation location, boolean isError) { - this(message, (isError ? IMessage.ERROR : IMessage.WARNING), null, - location); - } - - public Message(String message, ISourceLocation location, boolean isError, ISourceLocation[] extraSourceLocations) { - this(message, "",(isError ? IMessage.ERROR : IMessage.WARNING), location, null, - (extraSourceLocations.length > 0 ? extraSourceLocations : null)); - } - + private final String message; + private final IMessage.Kind kind; + private final Throwable thrown; + private final ISourceLocation sourceLocation; + private final String details; + private final List extraSourceLocations; + private final boolean declared; // Is it a DEOW ? + private final int id; + private final int sourceStart, sourceEnd; + /** - * Create a message, handling null values for message and kind - * if thrown is not null. + * Create a (compiler) error or warning message + * + * @param message the String used as the underlying message + * @param location the ISourceLocation, if any, associated with this message + * @param isError if true, use IMessage.ERROR; else use IMessage.WARNING + */ + public Message(String message, ISourceLocation location, boolean isError) { + this(message, (isError ? IMessage.ERROR : IMessage.WARNING), null, location); + } + + public Message(String message, ISourceLocation location, boolean isError, ISourceLocation[] extraSourceLocations) { + this(message, "", (isError ? IMessage.ERROR : IMessage.WARNING), location, null, + (extraSourceLocations.length > 0 ? extraSourceLocations : null)); + } + + /** + * Create a message, handling null values for message and kind if thrown is not null. + * * @param message the String used as the underlying message * @param kind the IMessage.Kind of message - not null * @param thrown the Throwable, if any, associated with this message * @param sourceLocation the ISourceLocation, if any, associated with this message * @param details descriptive information about the message - * @throws IllegalArgumentException if message is null and - * thrown is null or has a null message, or if kind is null - * and thrown is null. + * @throws IllegalArgumentException if message is null and thrown is null or has a null message, or if kind is null and thrown + * is null. */ - public Message(String message, String details, IMessage.Kind kind, - ISourceLocation sourceLocation, Throwable thrown, ISourceLocation[] extraSourceLocations) { - this(message,details,kind,sourceLocation,thrown,extraSourceLocations,false,0,-1,-1); - } - - public Message(String message, String details, IMessage.Kind kind, - ISourceLocation sLoc, Throwable thrown, ISourceLocation[] otherLocs, - boolean declared,int id,int sourcestart,int sourceend) { + public Message(String message, String details, IMessage.Kind kind, ISourceLocation sourceLocation, Throwable thrown, + ISourceLocation[] extraSourceLocations) { + this(message, details, kind, sourceLocation, thrown, extraSourceLocations, false, 0, -1, -1); + } + + public Message(String message, String details, IMessage.Kind kind, ISourceLocation sLoc, Throwable thrown, + ISourceLocation[] otherLocs, boolean declared, int id, int sourcestart, int sourceend) { this.details = details; this.id = id; this.sourceStart = sourcestart; this.sourceEnd = sourceend; - this.message = ((message!=null) ? message : ((thrown==null) ? null : thrown.getMessage())); + this.message = ((message != null) ? message : ((thrown == null) ? null : thrown.getMessage())); this.kind = kind; this.sourceLocation = sLoc; this.thrown = thrown; - if (otherLocs != null) { - this.extraSourceLocations - = Collections.unmodifiableList(Arrays.asList(otherLocs)); - } - else { - this.extraSourceLocations = Collections.EMPTY_LIST; + if (otherLocs != null) { + this.extraSourceLocations = Collections.unmodifiableList(Arrays.asList(otherLocs)); + } else { + this.extraSourceLocations = Collections.emptyList(); } if (null == this.kind) { - throw new IllegalArgumentException("null kind"); + throw new IllegalArgumentException("null kind"); } if (null == this.message) { throw new IllegalArgumentException("null message"); - } + } this.declared = declared; } - - /** - * Create a message, handling null values for message and kind - * if thrown is not null. - * @param message the String used as the underlying message - * @param kind the IMessage.Kind of message - not null - * @param thrown the Throwable, if any, associated with this message - * @param sourceLocation the ISourceLocation, if any, associated with this message - * @throws IllegalArgumentException if message is null and - * thrown is null or has a null message, or if kind is null - * and thrown is null. - */ - public Message(String message, IMessage.Kind kind, Throwable thrown, - ISourceLocation sourceLocation) { - this(message, "", kind, sourceLocation, thrown, null ); - } - - /** @return the kind of this message */ - public IMessage.Kind getKind() { - return kind; - } - - /** @return true if kind == IMessage.ERROR */ - public boolean isError() { - return kind == IMessage.ERROR; - } - - /** @return true if kind == IMessage.WARNING */ - public boolean isWarning() { - return kind == IMessage.WARNING; - } - - /** @return true if kind == IMessage.DEBUG */ - public boolean isDebug() { - return kind == IMessage.DEBUG; - } - + + /** + * Create a message, handling null values for message and kind if thrown is not null. + * + * @param message the String used as the underlying message + * @param kind the IMessage.Kind of message - not null + * @param thrown the Throwable, if any, associated with this message + * @param sourceLocation the ISourceLocation, if any, associated with this message + * @throws IllegalArgumentException if message is null and thrown is null or has a null message, or if kind is null and thrown + * is null. + */ + public Message(String message, IMessage.Kind kind, Throwable thrown, ISourceLocation sourceLocation) { + this(message, "", kind, sourceLocation, thrown, null); + } + + /** @return the kind of this message */ + public IMessage.Kind getKind() { + return kind; + } + + /** @return true if kind == IMessage.ERROR */ + public boolean isError() { + return kind == IMessage.ERROR; + } + + /** @return true if kind == IMessage.WARNING */ + public boolean isWarning() { + return kind == IMessage.WARNING; + } + + /** @return true if kind == IMessage.DEBUG */ + public boolean isDebug() { + return kind == IMessage.DEBUG; + } + public boolean isTaskTag() { return kind == IMessage.TASKTAG; } - /** - * @return true if kind == IMessage.INFO - */ - public boolean isInfo() { - return kind == IMessage.INFO; - } - - /** @return true if kind == IMessage.ABORT */ - public boolean isAbort() { - return kind == IMessage.ABORT; - } - - /** Caller can verify if this message came about because of a DEOW */ - public boolean getDeclared() { - return declared; - } - - /** - * @return true if kind == IMessage.FAIL - */ - public boolean isFailed() { - return kind == IMessage.FAIL; - } - - /** @return non-null String with simple message */ - final public String getMessage() { - return message; - } - - /** @return Throwable associated with this message, or null if none */ - final public Throwable getThrown() { - return thrown; - } - - /** @return ISourceLocation associated with this message, or null if none */ - final public ISourceLocation getSourceLocation() { - return sourceLocation; - } - - public String toString() { - return MessageUtil.renderMessage(this,false); - } + /** + * @return true if kind == IMessage.INFO + */ + public boolean isInfo() { + return kind == IMessage.INFO; + } + + /** @return true if kind == IMessage.ABORT */ + public boolean isAbort() { + return kind == IMessage.ABORT; + } + + /** Caller can verify if this message came about because of a DEOW */ + public boolean getDeclared() { + return declared; + } + + /** + * @return true if kind == IMessage.FAIL + */ + public boolean isFailed() { + return kind == IMessage.FAIL; + } + + /** @return non-null String with simple message */ + final public String getMessage() { + return message; + } + + /** @return Throwable associated with this message, or null if none */ + final public Throwable getThrown() { + return thrown; + } + + /** @return ISourceLocation associated with this message, or null if none */ + final public ISourceLocation getSourceLocation() { + return sourceLocation; + } + + public String toString() { + return MessageUtil.renderMessage(this, false); + } public String getDetails() { return details; } - - public List getExtraSourceLocations() { + + public List getExtraSourceLocations() { return extraSourceLocations; } @@ -192,7 +183,7 @@ public class Message implements IMessage { public int getSourceStart() { return sourceStart; } - + public int getSourceEnd() { return sourceEnd; } diff --git a/bridge/src/org/aspectj/bridge/MessageHandler.java b/bridge/src/org/aspectj/bridge/MessageHandler.java index dc6fb34ae..6fd8539cc 100644 --- a/bridge/src/org/aspectj/bridge/MessageHandler.java +++ b/bridge/src/org/aspectj/bridge/MessageHandler.java @@ -13,260 +13,253 @@ package org.aspectj.bridge; - import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; /** - * This handler accumulates messages. - * To control messages accumulated, - * clients can ignore messages of a given kind, - * or install a listener/interceptor. - * The interceptor handles all messages (even null) first, - * and can halt further processing/accumlation by returning true. - * Clients can obtain messages accumulated using the get... methods. - * XXX this does not permit messages to be removed. + * This handler accumulates messages. To control messages accumulated, clients can ignore messages of a given kind, or install a + * listener/interceptor. The interceptor handles all messages (even null) first, and can halt further processing/accumlation by + * returning true. Clients can obtain messages accumulated using the get... methods. XXX this does not permit messages to be + * removed. + * + * @author PARC + * @author Andy Clement */ public class MessageHandler implements IMessageHolder { - /** messages accumulated */ - protected final ArrayList messages; - /** kinds of messages to be ignored */ - protected final ArrayList ignoring; - /** result of handleMessage(..) for messages not accumulated (ignored) */ - protected boolean handleMessageResult; - /** listener which can halt processing by returning true */ - protected IMessageHandler interceptor; - - /** - * same as MessageHandler(false) - */ - public MessageHandler() { - this(false); - } - - /** - * @param accumulateOnly the result of handleMessage - * (i.e., if true, then only accumulate messages - stop processing - */ - public MessageHandler(boolean accumulateOnly) { - messages = new ArrayList(); - ignoring = new ArrayList(); - init(accumulateOnly); - ignore(IMessage.WEAVEINFO); // Off by default, need to explicitly be enabled (see -showWeaveInfo) - } - - /** - * Initialize this, removing any messages accumulated, - * kinds being ignored, or interceptor. - * Assume that this should return false from handleMessage(..). - */ - public void init() { init(false); } - - /** - * Initialize this, removing any messages accumulated, - * kinds being ignored, or interceptor. - * @param accumulateOnly boolean value returned from handleMessage - * after accumulating in list - */ - public void init(boolean accumulateOnly) { - handleMessageResult = accumulateOnly; - if (0 < messages.size()) { - messages.clear(); - } - if (0 < ignoring.size()) { - boolean ignoringWeaveMessages = isIgnoring(IMessage.WEAVEINFO); - ignoring.clear(); - if (ignoringWeaveMessages) ignore(IMessage.WEAVEINFO); - } - if (null != interceptor) { - interceptor = null; - } - } - - /** - * Clear the messages without changing other behavior. - */ - public void clearMessages() { - if (0 < messages.size()) { - messages.clear(); - } - } + /** messages accumulated */ + protected final ArrayList messages; + /** kinds of messages to be ignored */ + protected final ArrayList ignoring; + /** result of handleMessage(..) for messages not accumulated (ignored) */ + protected boolean handleMessageResult; + /** listener which can halt processing by returning true */ + protected IMessageHandler interceptor; + + /** + * same as MessageHandler(false) + */ + public MessageHandler() { + this(false); + } + + /** + * @param accumulateOnly the result of handleMessage (i.e., if true, then only accumulate messages - stop processing + */ + public MessageHandler(boolean accumulateOnly) { + messages = new ArrayList(); + ignoring = new ArrayList(); + init(accumulateOnly); + ignore(IMessage.WEAVEINFO); // Off by default, need to explicitly be enabled (see -showWeaveInfo) + } + + /** + * Initialize this, removing any messages accumulated, kinds being ignored, or interceptor. Assume that this should return false + * from handleMessage(..). + */ + public void init() { + init(false); + } + + /** + * Initialize this, removing any messages accumulated, kinds being ignored, or interceptor. + * + * @param accumulateOnly boolean value returned from handleMessage after accumulating in list + */ + public void init(boolean accumulateOnly) { + handleMessageResult = accumulateOnly; + if (0 < messages.size()) { + messages.clear(); + } + if (0 < ignoring.size()) { + boolean ignoringWeaveMessages = isIgnoring(IMessage.WEAVEINFO); + ignoring.clear(); + if (ignoringWeaveMessages) { + ignore(IMessage.WEAVEINFO); + } + } + if (null != interceptor) { + interceptor = null; + } + } + + /** + * Clear the messages without changing other behavior. + */ + public void clearMessages() { + if (0 < messages.size()) { + messages.clear(); + } + } - // ---------------------- IMessageHandler implementation + // ---------------------- IMessageHandler implementation /** - * This implementation accumulates message. - * If an interceptor is installed and returns true (message handled), - * then processing halts and the message is not accumulated. + * This implementation accumulates message. If an interceptor is installed and returns true (message handled), then processing + * halts and the message is not accumulated. + * * @see org.aspectj.bridge.IMessageHandler#handleMessage(IMessage) * @return true on interception or the constructor value otherwise - */ + */ public boolean handleMessage(IMessage message) { - if ((null != interceptor) && (interceptor.handleMessage(message))) { - return true; - } - if (null == message) { - throw new IllegalArgumentException("null message"); - } - if (!ignoring.contains(message.getKind())) { - messages.add(message); - } - return handleMessageResult; - } + if ((null != interceptor) && (interceptor.handleMessage(message))) { + return true; + } + if (null == message) { + throw new IllegalArgumentException("null message"); + } + if (!ignoring.contains(message.getKind())) { + messages.add(message); + } + return handleMessageResult; + } - /** - * @return true if this kind has been flagged to be ignored. - * @see #ignore(IMessage.Kind) + /** + * @return true if this kind has been flagged to be ignored. + * @see #ignore(IMessage.Kind) * @see org.aspectj.bridge.IMessageHandler#isIgnoring(Kind) */ public boolean isIgnoring(IMessage.Kind kind) { return ((null != kind) && (ignoring.contains(kind))); } - - // ---------------------- end of IMessageHandler implementation + // ---------------------- end of IMessageHandler implementation - /** - * Set a message kind to be ignored from now on - */ - public void ignore(IMessage.Kind kind) { // XXX sync - if ((null != kind) && (!ignoring.contains(kind))) { - ignoring.add(kind); - } - } + /** + * Set a message kind to be ignored from now on + */ + public void ignore(IMessage.Kind kind) { // XXX sync + if ((null != kind) && (!ignoring.contains(kind))) { + ignoring.add(kind); + } + } - /** - * Remove a message kind from the list of those ignored from now on. - */ - public void dontIgnore(IMessage.Kind kind) { - if (null != kind) { - ignoring.remove(kind); - } - } + /** + * Remove a message kind from the list of those ignored from now on. + */ + public void dontIgnore(IMessage.Kind kind) { + if (null != kind) { + ignoring.remove(kind); + } + } - /** + /** * @see org.aspectj.bridge.IMessageHolder#hasAnyMessage(Kind, boolean) */ public boolean hasAnyMessage(final IMessage.Kind kind, final boolean orGreater) { - if (null == kind) { - return (0 < messages.size()); - } - if (!orGreater) { - for (Iterator iter = messages.iterator(); iter.hasNext();) { - if (kind == ((IMessage) iter.next()).getKind()) { - return true; - } - } - } else { - for (Iterator iter = messages.iterator(); iter.hasNext();) { - IMessage m = (IMessage) iter.next(); - if (kind.isSameOrLessThan(m.getKind())) { - return true; - } - } - } - return false; + if (null == kind) { + return (0 < messages.size()); + } + if (!orGreater) { + for (IMessage m : messages) { + if (kind == m.getKind()) { + return true; + } + } + } else { + for (IMessage m : messages) { + if (kind.isSameOrLessThan(m.getKind())) { + return true; + } + } + } + return false; + } + + /** + * @return number of messages accumulated of a given kind + */ + public int numMessages(IMessage.Kind kind, final boolean orGreater) { + if (null == kind) { + return messages.size(); + } + int result = 0; + if (!orGreater) { + for (IMessage m : messages) { + if (kind == m.getKind()) { + result++; + } + } + } else { + for (IMessage m : messages) { + if (kind.isSameOrLessThan(m.getKind())) { + result++; + } + } + } + return result; } - /** - * @return number of messages accumulated of a given kind - */ - public int numMessages(IMessage.Kind kind, final boolean orGreater) { - if (null == kind) { - return messages.size(); - } - int result = 0; - if (!orGreater) { - for (Iterator iter = messages.iterator(); iter.hasNext();) { - if (kind == ((IMessage) iter.next()).getKind()) { - result++; - } - } - } else { - for (Iterator iter = messages.iterator(); iter.hasNext();) { - IMessage m = (IMessage) iter.next(); - if (kind.isSameOrLessThan(m.getKind())) { - result++; - } - } - } - return result; - } - - /** + /** * @see org.aspectj.bridge.IMessageHolder#getUnmodifiableListView() */ - public List getUnmodifiableListView() { + public List getUnmodifiableListView() { return Collections.unmodifiableList(messages); } - /** - * Get all messages or those of a specific kind. - * Pass null to get all kinds. - * @param kind the IMessage.Kind expected, or null for all messages - * @return IMessage[] of messages of the right kind - */ - public IMessage[] getMessages(IMessage.Kind kind, final boolean orGreater) { - if (null == kind) { - return (IMessage[]) messages.toArray(IMessage.RA_IMessage); - } - ArrayList result = new ArrayList(); - if (!orGreater) { - for (Iterator iter = messages.iterator(); iter.hasNext();) { - IMessage m = (IMessage) iter.next(); - if (kind == m.getKind()) { - result.add(m); - } - } - } else { - for (Iterator iter = messages.iterator(); iter.hasNext();) { - IMessage m = (IMessage) iter.next(); - if (kind.isSameOrLessThan(m.getKind())) { - result.add(m); - } - } - } - if (0 == result.size()) { - return IMessage.RA_IMessage; - } - return (IMessage[]) result.toArray(IMessage.RA_IMessage); - } - - /** - * @return array of error messages, or IMessage.NONE - */ - public IMessage[] getErrors() { - return getMessages(IMessage.ERROR, false); - } - - /** - * @return array of warning messages, or IMessage.NONE - */ - public IMessage[] getWarnings() { - return getMessages(IMessage.WARNING, false); - } - - /** - * Set the interceptor which gets any message before we process it. - * @param interceptor the IMessageHandler passed the message. - * Pass null to remove the old interceptor. - */ - public void setInterceptor(IMessageHandler interceptor) { - this.interceptor = interceptor; - } - - /** - * @return String containing list of messages - */ - public String toString() { - if (0 == messages.size()) { - return "MessageHandler: no messages"; - } else { - return "MessageHandler: " + messages; - } + /** + * Get all messages or those of a specific kind. Pass null to get all kinds. + * + * @param kind the IMessage.Kind expected, or null for all messages + * @return IMessage[] of messages of the right kind + */ + public IMessage[] getMessages(IMessage.Kind kind, final boolean orGreater) { + if (null == kind) { + return messages.toArray(IMessage.RA_IMessage); + } + ArrayList result = new ArrayList(); + if (!orGreater) { + for (IMessage m : messages) { + if (kind == m.getKind()) { + result.add(m); + } + } + } else { + for (IMessage m : messages) { + if (kind.isSameOrLessThan(m.getKind())) { + result.add(m); + } + } + } + if (0 == result.size()) { + return IMessage.RA_IMessage; + } + return result.toArray(IMessage.RA_IMessage); + } - } + /** + * @return array of error messages, or IMessage.NONE + */ + public IMessage[] getErrors() { + return getMessages(IMessage.ERROR, false); + } + + /** + * @return array of warning messages, or IMessage.NONE + */ + public IMessage[] getWarnings() { + return getMessages(IMessage.WARNING, false); + } + + /** + * Set the interceptor which gets any message before we process it. + * + * @param interceptor the IMessageHandler passed the message. Pass null to remove the old interceptor. + */ + public void setInterceptor(IMessageHandler interceptor) { + this.interceptor = interceptor; + } + + /** + * @return String containing list of messages + */ + public String toString() { + if (0 == messages.size()) { + return "MessageHandler: no messages"; + } else { + return "MessageHandler: " + messages; + } + + } } diff --git a/bridge/src/org/aspectj/bridge/MessageUtil.java b/bridge/src/org/aspectj/bridge/MessageUtil.java index e9f23031e..6d85ea6f9 100644 --- a/bridge/src/org/aspectj/bridge/MessageUtil.java +++ b/bridge/src/org/aspectj/bridge/MessageUtil.java @@ -13,1110 +13,1104 @@ package org.aspectj.bridge; -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; import org.aspectj.bridge.IMessage.Kind; -import org.aspectj.util.*; +import org.aspectj.util.LangUtil; /** * Convenience API's for constructing, printing, and sending messages. */ public class MessageUtil { - - // ------ some constant, content-less messages - // no variants for "info" or "debug", which should always have content - public static final IMessage ABORT_NOTHING_TO_RUN - = new Message("aborting - nothing to run", IMessage.ABORT, null, null); - - public static final IMessage FAIL_INCOMPLETE - = new Message("run not completed", IMessage.FAIL, null, null); - - public static final IMessage ABORT_NOMESSAGE - = new Message("", IMessage.ABORT, null, null); - - public static final IMessage FAIL_NOMESSAGE - = new Message("", IMessage.FAIL, null, null); - - public static final IMessage ERROR_NOMESSAGE - = new Message("", IMessage.ERROR, null, null); - - public static final IMessage WARNING_NOMESSAGE - = new Message("", IMessage.WARNING, null, null); - - - /** handle abort message (ignored if handler is null) */ - public static boolean abort(IMessageHandler handler, String message) { - return ((null != handler) - && handler.handleMessage(abort(message))); - } - - /** create and handle exception message (ignored if handler is null) */ - public static boolean abort(IMessageHandler handler, String message, Throwable t) { - if (handler != null) return handler.handleMessage(abort(message, t)); - return false; - } - - /** create and handle fail message (ignored if handler is null) */ - public static boolean fail(IMessageHandler handler, String message) { - return ((null != handler) - && handler.handleMessage(fail(message))); - } - -// /** create and handle fail message from reader (ignored if handler is null) */ -// public static boolean fail(IMessageHandler handler, String message, LineReader reader) { -// return ((null != handler) -// && handler.handleMessage(fail(message, reader))); -// } - - /** create and handle fail message (ignored if handler is null) */ - public static boolean fail(IMessageHandler handler, String message, Throwable thrown) { - return ((null != handler) - && handler.handleMessage(fail(message, thrown))); - } - - /** create and handle error message (ignored if handler is null) */ - public static boolean error(IMessageHandler handler, String message) { - return ((null != handler) - && handler.handleMessage(error(message))); - } - - /** create and handle warn message (ignored if handler is null) */ - public static boolean warn(IMessageHandler handler, String message) { - return ((null != handler) - && handler.handleMessage(warn(message))); - } - - /** create and handle debug message (ignored if handler is null) */ - public static boolean debug(IMessageHandler handler, String message) { - return ((null != handler) - && handler.handleMessage(debug(message))); - } - - /** create and handle info message (ignored if handler is null) */ - public static boolean info(IMessageHandler handler, String message) { - return ((null != handler) - && handler.handleMessage(info(message))); - } - - /** @return ABORT_NOMESSAGE if message is empty or IMessage otherwise */ // - public static IMessage abort(String message) { - if (LangUtil.isEmpty(message)) { - return ABORT_NOMESSAGE; - } else { - return new Message(message, IMessage.ABORT, null, null); - } - } - - /** @return abort IMessage with thrown and message o - * ABORT_NOMESSAGE if both are empty/null */ // - public static IMessage abort(String message, Throwable thrown) { - if (!LangUtil.isEmpty(message)) { - return new Message(message, IMessage.ABORT, thrown, null); - } else if (null == thrown) { - return ABORT_NOMESSAGE; - } else { - return new Message(thrown.getMessage(), IMessage.ABORT, thrown, null); - } - } - - /** @return FAIL_NOMESSAGE if message is empty or IMessage otherwise */ - public static IMessage fail(String message) { - if (LangUtil.isEmpty(message)) { - return FAIL_NOMESSAGE; - } else { - return new Message(message, IMessage.FAIL, null, ISourceLocation.EMPTY); - -// return fail(message, (LineReader) null); - } - } - - /** - * Create fail message. - * If message is empty but thrown is not, use thrown.getMessage() as the message. - * If message is empty and thrown is null, return FAIL_NOMESSAGE. - * @return FAIL_NOMESSAGE if thrown is null and message is empty - * or IMessage FAIL with message and thrown otherwise - */ - public static IMessage fail(String message, Throwable thrown) { - if (LangUtil.isEmpty(message)) { - if (null == thrown) { - return FAIL_NOMESSAGE; - } else { - return new Message(thrown.getMessage(), IMessage.FAIL, thrown, null); - } - } else { - return new Message(message, IMessage.FAIL, thrown, null); - } - } - - /** - * @return IMessage with IMessage.Kind FAIL and message as text - * and soure location from reader - */ -// public static IMessage fail(String message) {//, LineReader reader) { -// ISourceLocation loc = null; -// if (null == reader) { -// loc = ISourceLocation.EMPTY; -// } else { -// int line = reader.getLineNumber(); -// if (0 < line) { -// line = 0; -// } -// loc = new SourceLocation(reader.getFile(), line, line, 0); -// } -// return new Message(message, IMessage.FAIL, null, ISourceLocation.EMPTY); -// } - - /** @return ERROR_NOMESSAGE if message is empty or IMessage otherwise */ // - public static IMessage error(String message, ISourceLocation location) { - if (LangUtil.isEmpty(message)) { - return ERROR_NOMESSAGE; - } else { - return new Message(message, IMessage.ERROR, null, location); - } - } - - /** @return WARNING_NOMESSAGE if message is empty or IMessage otherwise */ // - public static IMessage warn(String message, ISourceLocation location) { - if (LangUtil.isEmpty(message)) { - return WARNING_NOMESSAGE; - } else { - return new Message(message, IMessage.WARNING, null, location); - } - } - /** @return ERROR_NOMESSAGE if message is empty or IMessage otherwise */ // - public static IMessage error(String message) { - if (LangUtil.isEmpty(message)) { - return ERROR_NOMESSAGE; - } else { - return new Message(message, IMessage.ERROR, null, null); - } - } - - /** @return WARNING_NOMESSAGE if message is empty or IMessage otherwise */ // - public static IMessage warn(String message) { - if (LangUtil.isEmpty(message)) { - return WARNING_NOMESSAGE; - } else { - return new Message(message, IMessage.WARNING, null, null); - } - } - - /** @return IMessage.DEBUG message with message content */ - public static IMessage debug(String message) { - return new Message(message, IMessage.DEBUG, null, null); - } - - /** @return IMessage.INFO message with message content */ - public static IMessage info(String message) { - return new Message(message, IMessage.INFO, null, null); - } - -// /** @return ISourceLocation with the current File/line of the reader */ -// public static ISourceLocation makeSourceLocation(LineReader reader) { -// LangUtil.throwIaxIfNull(reader, "reader"); -// -// int line = reader.getLineNumber(); -// if (0 < line) { -// line = 0; -// } -// return new SourceLocation(reader.getFile(), line, line, 0); -// } - - // ------------------------ printing messages - /** - * Print total counts message to the print stream, starting each on a new line - * @param messageHolder - * @param out - */ - public static void printMessageCounts(PrintStream out, IMessageHolder messageHolder) { - if ((null == out) || (null == messageHolder)) { - return; - } - printMessageCounts(out, messageHolder, ""); - } - - public static void printMessageCounts(PrintStream out, IMessageHolder holder, String prefix) { - out.println(prefix + "MessageHolder: " + MessageUtil.renderCounts(holder)); - } + + // ------ some constant, content-less messages + // no variants for "info" or "debug", which should always have content + public static final IMessage ABORT_NOTHING_TO_RUN = new Message("aborting - nothing to run", IMessage.ABORT, null, null); + + public static final IMessage FAIL_INCOMPLETE = new Message("run not completed", IMessage.FAIL, null, null); + + public static final IMessage ABORT_NOMESSAGE = new Message("", IMessage.ABORT, null, null); + + public static final IMessage FAIL_NOMESSAGE = new Message("", IMessage.FAIL, null, null); + + public static final IMessage ERROR_NOMESSAGE = new Message("", IMessage.ERROR, null, null); + + public static final IMessage WARNING_NOMESSAGE = new Message("", IMessage.WARNING, null, null); + + /** handle abort message (ignored if handler is null) */ + public static boolean abort(IMessageHandler handler, String message) { + return ((null != handler) && handler.handleMessage(abort(message))); + } + + /** create and handle exception message (ignored if handler is null) */ + public static boolean abort(IMessageHandler handler, String message, Throwable t) { + if (handler != null) { + return handler.handleMessage(abort(message, t)); + } + return false; + } + + /** create and handle fail message (ignored if handler is null) */ + public static boolean fail(IMessageHandler handler, String message) { + return ((null != handler) && handler.handleMessage(fail(message))); + } + + // /** create and handle fail message from reader (ignored if handler is null) */ + // public static boolean fail(IMessageHandler handler, String message, LineReader reader) { + // return ((null != handler) + // && handler.handleMessage(fail(message, reader))); + // } + + /** create and handle fail message (ignored if handler is null) */ + public static boolean fail(IMessageHandler handler, String message, Throwable thrown) { + return ((null != handler) && handler.handleMessage(fail(message, thrown))); + } + + /** create and handle error message (ignored if handler is null) */ + public static boolean error(IMessageHandler handler, String message) { + return ((null != handler) && handler.handleMessage(error(message))); + } + + /** create and handle warn message (ignored if handler is null) */ + public static boolean warn(IMessageHandler handler, String message) { + return ((null != handler) && handler.handleMessage(warn(message))); + } + + /** create and handle debug message (ignored if handler is null) */ + public static boolean debug(IMessageHandler handler, String message) { + return ((null != handler) && handler.handleMessage(debug(message))); + } + + /** create and handle info message (ignored if handler is null) */ + public static boolean info(IMessageHandler handler, String message) { + return ((null != handler) && handler.handleMessage(info(message))); + } + + /** @return ABORT_NOMESSAGE if message is empty or IMessage otherwise */ + // + public static IMessage abort(String message) { + if (LangUtil.isEmpty(message)) { + return ABORT_NOMESSAGE; + } else { + return new Message(message, IMessage.ABORT, null, null); + } + } + + /** + * @return abort IMessage with thrown and message o ABORT_NOMESSAGE if both are empty/null + */ + // + public static IMessage abort(String message, Throwable thrown) { + if (!LangUtil.isEmpty(message)) { + return new Message(message, IMessage.ABORT, thrown, null); + } else if (null == thrown) { + return ABORT_NOMESSAGE; + } else { + return new Message(thrown.getMessage(), IMessage.ABORT, thrown, null); + } + } + + /** @return FAIL_NOMESSAGE if message is empty or IMessage otherwise */ + public static IMessage fail(String message) { + if (LangUtil.isEmpty(message)) { + return FAIL_NOMESSAGE; + } else { + return new Message(message, IMessage.FAIL, null, ISourceLocation.EMPTY); + + // return fail(message, (LineReader) null); + } + } + + /** + * Create fail message. If message is empty but thrown is not, use thrown.getMessage() as the message. If message is empty and + * thrown is null, return FAIL_NOMESSAGE. + * + * @return FAIL_NOMESSAGE if thrown is null and message is empty or IMessage FAIL with message and thrown otherwise + */ + public static IMessage fail(String message, Throwable thrown) { + if (LangUtil.isEmpty(message)) { + if (null == thrown) { + return FAIL_NOMESSAGE; + } else { + return new Message(thrown.getMessage(), IMessage.FAIL, thrown, null); + } + } else { + return new Message(message, IMessage.FAIL, thrown, null); + } + } + + /** + * @return IMessage with IMessage.Kind FAIL and message as text and soure location from reader + */ + // public static IMessage fail(String message) {//, LineReader reader) { + // ISourceLocation loc = null; + // if (null == reader) { + // loc = ISourceLocation.EMPTY; + // } else { + // int line = reader.getLineNumber(); + // if (0 < line) { + // line = 0; + // } + // loc = new SourceLocation(reader.getFile(), line, line, 0); + // } + // return new Message(message, IMessage.FAIL, null, ISourceLocation.EMPTY); + // } + + /** @return ERROR_NOMESSAGE if message is empty or IMessage otherwise */ + // + public static IMessage error(String message, ISourceLocation location) { + if (LangUtil.isEmpty(message)) { + return ERROR_NOMESSAGE; + } else { + return new Message(message, IMessage.ERROR, null, location); + } + } + + /** @return WARNING_NOMESSAGE if message is empty or IMessage otherwise */ + // + public static IMessage warn(String message, ISourceLocation location) { + if (LangUtil.isEmpty(message)) { + return WARNING_NOMESSAGE; + } else { + return new Message(message, IMessage.WARNING, null, location); + } + } + + /** @return ERROR_NOMESSAGE if message is empty or IMessage otherwise */ + // + public static IMessage error(String message) { + if (LangUtil.isEmpty(message)) { + return ERROR_NOMESSAGE; + } else { + return new Message(message, IMessage.ERROR, null, null); + } + } + + /** @return WARNING_NOMESSAGE if message is empty or IMessage otherwise */ + // + public static IMessage warn(String message) { + if (LangUtil.isEmpty(message)) { + return WARNING_NOMESSAGE; + } else { + return new Message(message, IMessage.WARNING, null, null); + } + } + + /** @return IMessage.DEBUG message with message content */ + public static IMessage debug(String message) { + return new Message(message, IMessage.DEBUG, null, null); + } + + /** @return IMessage.INFO message with message content */ + public static IMessage info(String message) { + return new Message(message, IMessage.INFO, null, null); + } + + // /** @return ISourceLocation with the current File/line of the reader */ + // public static ISourceLocation makeSourceLocation(LineReader reader) { + // LangUtil.throwIaxIfNull(reader, "reader"); + // + // int line = reader.getLineNumber(); + // if (0 < line) { + // line = 0; + // } + // return new SourceLocation(reader.getFile(), line, line, 0); + // } + + // ------------------------ printing messages + /** + * Print total counts message to the print stream, starting each on a new line + * + * @param messageHolder + * @param out + */ + public static void printMessageCounts(PrintStream out, IMessageHolder messageHolder) { + if ((null == out) || (null == messageHolder)) { + return; + } + printMessageCounts(out, messageHolder, ""); + } + + public static void printMessageCounts(PrintStream out, IMessageHolder holder, String prefix) { + out.println(prefix + "MessageHolder: " + MessageUtil.renderCounts(holder)); + } + /** * Print all message to the print stream, starting each on a new line + * * @param messageHolder * @param out - * @see #print(PrintStream, String, IMessageHolder, IMessageRenderer, IMessageHandler) + * @see #print(PrintStream, String, IMessageHolder, IMessageRenderer, IMessageHandler) */ public static void print(PrintStream out, IMessageHolder messageHolder) { - print(out, messageHolder, (String) null, (IMessageRenderer) null, (IMessageHandler) null); - } - - /** - * Print all message to the print stream, starting each on a new line, - * with a prefix. - * @param messageHolder - * @param out - * @see #print(PrintStream, String, IMessageHolder, IMessageRenderer, IMessageHandler) - */ - public static void print(PrintStream out, IMessageHolder holder, String prefix) { - print(out, holder, prefix, (IMessageRenderer) null, (IMessageHandler) null); - } - - /** - * Print all message to the print stream, starting each on a new line, - * with a prefix and using a renderer. - * @param messageHolder - * @param out - * @param renderer IMessageRender to render result - use MESSAGE_LINE if null - * @see #print(PrintStream, String, IMessageHolder, IMessageRenderer, IMessageHandler) - */ - public static void print(PrintStream out, IMessageHolder holder, String prefix, - IMessageRenderer renderer) { - print(out, holder, prefix, renderer, (IMessageHandler) null); - } - - /** - * Print all message to the print stream, starting each on a new line, - * with a prefix and using a renderer. - * The first line renders a summary: {prefix}MessageHolder: {summary} - * Each message line has the following form: - *
{prefix}[{kind} {index}]: {rendering}
- * (where "{index}" (length 3) is the position within - * the set of like-kinded messages, ignoring selector omissions. - * Renderers are free to render multi-line output. - * @param out the PrintStream sink - return silently if null - * @param messageHolder the IMessageHolder with the messages to print - * @param renderer IMessageRender to render result - use MESSAGE_ALL if null - * @param selector IMessageHandler to select messages to render - if null, do all non-null - */ - public static void print(PrintStream out, IMessageHolder holder, String prefix, - IMessageRenderer renderer, IMessageHandler selector) { - print(out, holder, prefix, renderer, selector, true); - } - - public static void print(PrintStream out, IMessageHolder holder, String prefix, - IMessageRenderer renderer, IMessageHandler selector, boolean printSummary) { - if ((null == out) || (null == holder)) { - return; - } - if (null == renderer) { - renderer = MESSAGE_ALL; - } - if (null == selector) { - selector = PICK_ALL; - } - if (printSummary) { - out.println(prefix + "MessageHolder: " + MessageUtil.renderCounts(holder)); - } - for (Iterator iter = IMessage.KINDS.iterator(); iter.hasNext();) { - IMessage.Kind kind = (IMessage.Kind) iter.next(); - if (!selector.isIgnoring(kind)) { - IMessage[] messages = holder.getMessages(kind, IMessageHolder.EQUAL); - for (int i = 0; i < messages.length; i++) { - if (selector.handleMessage(messages[i])) { - String label = (null == prefix - ? "" - : prefix + "[" + kind + " " + LangUtil.toSizedString(i, 3) + "]: "); - out.println(label + renderer.renderToString(messages[i])); - } - } - } - } - } - - public static String toShortString(IMessage message) { - if (null == message) { - return "null"; - } - String m = message.getMessage(); - Throwable t = message.getThrown(); - - return (message.getKind() + (null == m ? "" : ": " + m) - + (null == t ? "" : ": " + LangUtil.unqualifiedClassName(t))); - } - - /** @return int number of message of this kind (optionally or greater) in list */ - public static int numMessages(List messages, Kind kind, boolean orGreater) { - if (LangUtil.isEmpty(messages)) { - return 0; - } - IMessageHandler selector = makeSelector(kind, orGreater, null); - IMessage[] result = visitMessages(messages, selector, true, false); - return result.length; - } - - - /** - * Select all messages in holder except those of the same - * kind (optionally or greater). - * If kind is null, then all messages are rejected, - * so an empty list is returned. - * @return unmodifiable list of specified IMessage - */ - public static IMessage[] getMessagesExcept(IMessageHolder holder, - final IMessage.Kind kind, final boolean orGreater) { - if ((null == holder) || (null == kind)) { - return new IMessage[0]; - } - - IMessageHandler selector = new IMessageHandler(){ - public boolean handleMessage(IMessage message) { - IMessage.Kind test = message.getKind(); - return (!(orGreater - ? kind.isSameOrLessThan(test) - : kind == test)); - } - public boolean isIgnoring(Kind kind) { - return false; - } - public void dontIgnore(IMessage.Kind kind) { - - } + print(out, messageHolder, (String) null, (IMessageRenderer) null, (IMessageHandler) null); + } + + /** + * Print all message to the print stream, starting each on a new line, with a prefix. + * + * @param messageHolder + * @param out + * @see #print(PrintStream, String, IMessageHolder, IMessageRenderer, IMessageHandler) + */ + public static void print(PrintStream out, IMessageHolder holder, String prefix) { + print(out, holder, prefix, (IMessageRenderer) null, (IMessageHandler) null); + } + + /** + * Print all message to the print stream, starting each on a new line, with a prefix and using a renderer. + * + * @param messageHolder + * @param out + * @param renderer IMessageRender to render result - use MESSAGE_LINE if null + * @see #print(PrintStream, String, IMessageHolder, IMessageRenderer, IMessageHandler) + */ + public static void print(PrintStream out, IMessageHolder holder, String prefix, IMessageRenderer renderer) { + print(out, holder, prefix, renderer, (IMessageHandler) null); + } + + /** + * Print all message to the print stream, starting each on a new line, with a prefix and using a renderer. The first line + * renders a summary: {prefix}MessageHolder: {summary} Each message line has the following form: + * + *
+	 * {prefix}[{kind} {index}]: {rendering}
+	 * 
+ * + * (where "{index}" (length 3) is the position within the set of like-kinded messages, ignoring selector omissions. Renderers + * are free to render multi-line output. + * + * @param out the PrintStream sink - return silently if null + * @param messageHolder the IMessageHolder with the messages to print + * @param renderer IMessageRender to render result - use MESSAGE_ALL if null + * @param selector IMessageHandler to select messages to render - if null, do all non-null + */ + public static void print(PrintStream out, IMessageHolder holder, String prefix, IMessageRenderer renderer, + IMessageHandler selector) { + print(out, holder, prefix, renderer, selector, true); + } + + public static void print(PrintStream out, IMessageHolder holder, String prefix, IMessageRenderer renderer, + IMessageHandler selector, boolean printSummary) { + if ((null == out) || (null == holder)) { + return; + } + if (null == renderer) { + renderer = MESSAGE_ALL; + } + if (null == selector) { + selector = PICK_ALL; + } + if (printSummary) { + out.println(prefix + "MessageHolder: " + MessageUtil.renderCounts(holder)); + } + for (IMessage.Kind kind : IMessage.KINDS) { + if (!selector.isIgnoring(kind)) { + IMessage[] messages = holder.getMessages(kind, IMessageHolder.EQUAL); + for (int i = 0; i < messages.length; i++) { + if (selector.handleMessage(messages[i])) { + String label = (null == prefix ? "" : prefix + "[" + kind + " " + LangUtil.toSizedString(i, 3) + "]: "); + out.println(label + renderer.renderToString(messages[i])); + } + } + } + } + } + + public static String toShortString(IMessage message) { + if (null == message) { + return "null"; + } + String m = message.getMessage(); + Throwable t = message.getThrown(); + + return (message.getKind() + (null == m ? "" : ": " + m) + (null == t ? "" : ": " + LangUtil.unqualifiedClassName(t))); + } + + /** @return int number of message of this kind (optionally or greater) in list */ + public static int numMessages(List messages, Kind kind, boolean orGreater) { + if (LangUtil.isEmpty(messages)) { + return 0; + } + IMessageHandler selector = makeSelector(kind, orGreater, null); + IMessage[] result = visitMessages(messages, selector, true, false); + return result.length; + } + + /** + * Select all messages in holder except those of the same kind (optionally or greater). If kind is null, then all messages are + * rejected, so an empty list is returned. + * + * @return unmodifiable list of specified IMessage + */ + public static IMessage[] getMessagesExcept(IMessageHolder holder, final IMessage.Kind kind, final boolean orGreater) { + if ((null == holder) || (null == kind)) { + return new IMessage[0]; + } + + IMessageHandler selector = new IMessageHandler() { + public boolean handleMessage(IMessage message) { + IMessage.Kind test = message.getKind(); + return (!(orGreater ? kind.isSameOrLessThan(test) : kind == test)); + } + + public boolean isIgnoring(Kind kind) { + return false; + } + + public void dontIgnore(IMessage.Kind kind) { + + } + public void ignore(Kind kind) { } - }; - return visitMessages(holder, selector, true, false); - } - - /** @return unmodifiable list of IMessage complying with parameters */ - public static List getMessages(IMessageHolder holder, - IMessage.Kind kind, boolean orGreater, String infix) { // XXX untested - if (null == holder) { - return Collections.EMPTY_LIST; - } - if ((null == kind) && LangUtil.isEmpty(infix)) { - return holder.getUnmodifiableListView(); - } - IMessageHandler selector = makeSelector(kind, orGreater, infix); - IMessage[] messages = visitMessages(holder, selector, true, false); - if (LangUtil.isEmpty(messages)) { - return Collections.EMPTY_LIST; - } - return Collections.unmodifiableList(Arrays.asList(messages)); - } + }; + return visitMessages(holder, selector, true, false); + } + + /** @return unmodifiable list of IMessage complying with parameters */ + public static List getMessages(IMessageHolder holder, IMessage.Kind kind, boolean orGreater, String infix) { + if (null == holder) { + return Collections.emptyList(); + } + if ((null == kind) && LangUtil.isEmpty(infix)) { + return holder.getUnmodifiableListView(); + } + IMessageHandler selector = makeSelector(kind, orGreater, infix); + IMessage[] messages = visitMessages(holder, selector, true, false); + if (LangUtil.isEmpty(messages)) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(Arrays.asList(messages)); + } /** * Extract messages of type kind from the input list. - * + * * @param messages if null, return EMPTY_LIST * @param kind if null, return messages - * @see MessageHandler#getMessages(Kind) + * @see MessageHandler#getMessages(Kind) */ - public static List getMessages(List messages, IMessage.Kind kind) { - if (null == messages) { - return Collections.EMPTY_LIST; - } - if (null == kind) { - return messages; - } - ArrayList result = new ArrayList(); - for (Iterator iter = messages.iterator(); iter.hasNext();) { - IMessage element = (IMessage) iter.next(); - if (kind == element.getKind()) { - result.add(element); - } - } - if (0 == result.size()) { - return Collections.EMPTY_LIST; - } - return result; + public static List getMessages(List messages, IMessage.Kind kind) { + if (null == messages) { + return Collections.emptyList(); + } + if (null == kind) { + return messages; + } + ArrayList result = new ArrayList(); + for (IMessage message : messages) { + if (kind == message.getKind()) { + result.add(message); + } + } + if (0 == result.size()) { + return Collections.emptyList(); + } + return result; } /** * Map to the kind of messages associated with this string key. + * * @param kind the String representing the kind of message (IMessage.Kind.toString()) * @return Kind the associated IMessage.Kind, or null if not found */ public static IMessage.Kind getKind(String kind) { - if (null != kind) { - kind = kind.toLowerCase(); - for (Iterator iter = IMessage.KINDS.iterator(); iter.hasNext();) { - IMessage.Kind k = (IMessage.Kind) iter.next(); - if (kind.equals(k.toString())) { - return k; - } - } - } + if (null != kind) { + kind = kind.toLowerCase(); + for (IMessage.Kind k : IMessage.KINDS) { + if (kind.equals(k.toString())) { + return k; + } + } + } return null; } - - /** - * Run visitor over the set of messages in holder, - * optionally accumulating those accepted by the visitor - */ - public static IMessage[] visitMessages(IMessageHolder holder, - IMessageHandler visitor, boolean accumulate, boolean abortOnFail) { - if (null == holder) { - return IMessage.RA_IMessage; - } else { - return visitMessages(holder.getUnmodifiableListView(), visitor, accumulate, abortOnFail); - } - } - - /** - * Run visitor over the set of messages in holder, - * optionally accumulating those accepted by the visitor - */ - public static IMessage[] visitMessages(IMessage[] messages, - IMessageHandler visitor, boolean accumulate, boolean abortOnFail) { - if (LangUtil.isEmpty(messages)) { - return IMessage.RA_IMessage; - } else { - return visitMessages(Arrays.asList(messages), visitor, accumulate, abortOnFail); - } - } - - /** - * Run visitor over a collection of messages, - * optionally accumulating those accepted by the visitor - * @param messages if null or empty, return IMessage.RA_IMessage - * @param visitor run visitor.handleMessage(message) on each - * message - if null and messages not empty, IllegalArgumentException - * @param accumulate if true, then return accepted IMessage[] - * @param abortOnFail if true and visitor returns false, stop visiting - * @return IMessage.RA_IMessage if collection is empty, if not accumulate, - * or if visitor accepted no IMessage, - * or IMessage[] of accepted messages otherwise - * @throws IllegalArgumentException if any in collection are not instanceof IMessage - */ - public static IMessage[] visitMessages(Collection /*IMessage*/ messages, - IMessageHandler visitor, final boolean accumulate, final boolean abortOnFail) { - if (LangUtil.isEmpty(messages)) { - return IMessage.RA_IMessage; - } - LangUtil.throwIaxIfNull(visitor, "visitor"); - ArrayList result = (accumulate ? new ArrayList() : null); - for (Iterator iter = messages.iterator(); iter.hasNext();) { - Object o = iter.next(); - LangUtil.throwIaxIfFalse(o instanceof IMessage, "expected IMessage, got " + o); - IMessage m = (IMessage) o; - if (visitor.handleMessage(m)) { - if (accumulate) { - result.add(m); - } - } else if (abortOnFail) { - break; - } - } - if (!accumulate || (0 == result.size())) { - return IMessage.RA_IMessage; - } else { - return (IMessage[]) result.toArray(IMessage.RA_IMessage); - } - } - - /** - * Make an IMessageHandler that handles IMessage if they have the right kind - * (or greater) and contain some infix String. - * @param kind the IMessage.Kind required of the message - * @param orGreater if true, also accept messages with greater kinds, as - * defined by IMessage.Kind.COMPARATOR - * @param infix the String text to require in the message - may be null or empty - * to accept any message with the specified kind. - * @return IMessageHandler selector that works to param specs - */ - public static IMessageHandler makeSelector(IMessage.Kind kind, boolean orGreater, String infix) { - if (!orGreater && LangUtil.isEmpty(infix)) { - if (kind == IMessage.ABORT) { - return PICK_ABORT; - } else if (kind == IMessage.DEBUG) { - return PICK_DEBUG; - } else if (kind == IMessage.DEBUG) { - return PICK_DEBUG; - } else if (kind == IMessage.ERROR) { - return PICK_ERROR; - } else if (kind == IMessage.FAIL) { - return PICK_FAIL; - } else if (kind == IMessage.INFO) { - return PICK_INFO; - } else if (kind == IMessage.WARNING) { - return PICK_WARNING; - } - } - return new KindSelector(kind, orGreater, infix); - } - - // ------------------ visitors to select messages - public static final IMessageHandler PICK_ALL = new KindSelector((IMessage.Kind) null); - public static final IMessageHandler PICK_ABORT = new KindSelector(IMessage.ABORT); - public static final IMessageHandler PICK_DEBUG = new KindSelector(IMessage.DEBUG); - public static final IMessageHandler PICK_ERROR = new KindSelector(IMessage.ERROR); - public static final IMessageHandler PICK_FAIL = new KindSelector(IMessage.FAIL); - public static final IMessageHandler PICK_INFO = new KindSelector(IMessage.INFO); - public static final IMessageHandler PICK_WARNING = new KindSelector(IMessage.WARNING); - public static final IMessageHandler PICK_ABORT_PLUS = new KindSelector(IMessage.ABORT, true); - public static final IMessageHandler PICK_DEBUG_PLUS = new KindSelector(IMessage.DEBUG, true); - public static final IMessageHandler PICK_ERROR_PLUS = new KindSelector(IMessage.ERROR, true); - public static final IMessageHandler PICK_FAIL_PLUS = new KindSelector(IMessage.FAIL, true); - public static final IMessageHandler PICK_INFO_PLUS = new KindSelector(IMessage.INFO, true); - public static final IMessageHandler PICK_WARNING_PLUS = new KindSelector(IMessage.WARNING, true); - - - /** implementation for PICK_... constants */ - private static class KindSelector implements IMessageHandler { - final IMessage.Kind sought; - final boolean floor; - final String infix; - - KindSelector(IMessage.Kind sought) { - this(sought, false); - } - - KindSelector(IMessage.Kind sought, boolean floor) { - this(sought, floor, null); - } - - KindSelector(IMessage.Kind sought, boolean floor, String infix) { - this.sought = sought; - this.floor = floor; - this.infix = (LangUtil.isEmpty(infix) ? null : infix); - } - - /** @return false if this message is null, - * of true if we seek any kind (null) - * or if this has the exact kind we seek - * and this has any text sought - */ - public boolean handleMessage(IMessage message) { - return ((null != message) && !isIgnoring(message.getKind()) - && textIn(message)); - } - - /** @return true if handleMessage would return false for a message of this kind */ - public boolean isIgnoring(IMessage.Kind kind) { - if (!floor) { - return ((null != sought) && (sought != kind)); - } else if (null == sought) { - return false; - } else { - return (0 < IMessage.Kind.COMPARATOR.compare(sought, kind)); - } - } - - public void dontIgnore(IMessage.Kind kind) { - - } - - private boolean textIn(IMessage message) { - if (null == infix) { - return true; - } - String text = message.getMessage(); - return (text.indexOf(infix)!=-1); - } + + /** + * Run visitor over the set of messages in holder, optionally accumulating those accepted by the visitor + */ + public static IMessage[] visitMessages(IMessageHolder holder, IMessageHandler visitor, boolean accumulate, boolean abortOnFail) { + if (null == holder) { + return IMessage.RA_IMessage; + } else { + return visitMessages(holder.getUnmodifiableListView(), visitor, accumulate, abortOnFail); + } + } + + /** + * Run visitor over the set of messages in holder, optionally accumulating those accepted by the visitor + */ + public static IMessage[] visitMessages(IMessage[] messages, IMessageHandler visitor, boolean accumulate, boolean abortOnFail) { + if (LangUtil.isEmpty(messages)) { + return IMessage.RA_IMessage; + } else { + return visitMessages(Arrays.asList(messages), visitor, accumulate, abortOnFail); + } + } + + /** + * Run visitor over a collection of messages, optionally accumulating those accepted by the visitor + * + * @param messages if null or empty, return IMessage.RA_IMessage + * @param visitor run visitor.handleMessage(message) on each message - if null and messages not empty, IllegalArgumentException + * @param accumulate if true, then return accepted IMessage[] + * @param abortOnFail if true and visitor returns false, stop visiting + * @return IMessage.RA_IMessage if collection is empty, if not accumulate, or if visitor accepted no IMessage, or IMessage[] of + * accepted messages otherwise + * @throws IllegalArgumentException if any in collection are not instanceof IMessage + */ + public static IMessage[] visitMessages(Collection messages, IMessageHandler visitor, final boolean accumulate, + final boolean abortOnFail) { + if (LangUtil.isEmpty(messages)) { + return IMessage.RA_IMessage; + } + LangUtil.throwIaxIfNull(visitor, "visitor"); + ArrayList result = (accumulate ? new ArrayList() : null); + for (IMessage m : messages) { + if (visitor.handleMessage(m)) { + if (accumulate) { + result.add(m); + } + } else if (abortOnFail) { + break; + } + } + if (!accumulate || (0 == result.size())) { + return IMessage.RA_IMessage; + } else { + return result.toArray(IMessage.RA_IMessage); + } + } + + /** + * Make an IMessageHandler that handles IMessage if they have the right kind (or greater) and contain some infix String. + * + * @param kind the IMessage.Kind required of the message + * @param orGreater if true, also accept messages with greater kinds, as defined by IMessage.Kind.COMPARATOR + * @param infix the String text to require in the message - may be null or empty to accept any message with the specified kind. + * @return IMessageHandler selector that works to param specs + */ + public static IMessageHandler makeSelector(IMessage.Kind kind, boolean orGreater, String infix) { + if (!orGreater && LangUtil.isEmpty(infix)) { + if (kind == IMessage.ABORT) { + return PICK_ABORT; + } else if (kind == IMessage.DEBUG) { + return PICK_DEBUG; + } else if (kind == IMessage.DEBUG) { + return PICK_DEBUG; + } else if (kind == IMessage.ERROR) { + return PICK_ERROR; + } else if (kind == IMessage.FAIL) { + return PICK_FAIL; + } else if (kind == IMessage.INFO) { + return PICK_INFO; + } else if (kind == IMessage.WARNING) { + return PICK_WARNING; + } + } + return new KindSelector(kind, orGreater, infix); + } + + // ------------------ visitors to select messages + public static final IMessageHandler PICK_ALL = new KindSelector((IMessage.Kind) null); + public static final IMessageHandler PICK_ABORT = new KindSelector(IMessage.ABORT); + public static final IMessageHandler PICK_DEBUG = new KindSelector(IMessage.DEBUG); + public static final IMessageHandler PICK_ERROR = new KindSelector(IMessage.ERROR); + public static final IMessageHandler PICK_FAIL = new KindSelector(IMessage.FAIL); + public static final IMessageHandler PICK_INFO = new KindSelector(IMessage.INFO); + public static final IMessageHandler PICK_WARNING = new KindSelector(IMessage.WARNING); + public static final IMessageHandler PICK_ABORT_PLUS = new KindSelector(IMessage.ABORT, true); + public static final IMessageHandler PICK_DEBUG_PLUS = new KindSelector(IMessage.DEBUG, true); + public static final IMessageHandler PICK_ERROR_PLUS = new KindSelector(IMessage.ERROR, true); + public static final IMessageHandler PICK_FAIL_PLUS = new KindSelector(IMessage.FAIL, true); + public static final IMessageHandler PICK_INFO_PLUS = new KindSelector(IMessage.INFO, true); + public static final IMessageHandler PICK_WARNING_PLUS = new KindSelector(IMessage.WARNING, true); + + /** implementation for PICK_... constants */ + private static class KindSelector implements IMessageHandler { + final IMessage.Kind sought; + final boolean floor; + final String infix; + + KindSelector(IMessage.Kind sought) { + this(sought, false); + } + + KindSelector(IMessage.Kind sought, boolean floor) { + this(sought, floor, null); + } + + KindSelector(IMessage.Kind sought, boolean floor, String infix) { + this.sought = sought; + this.floor = floor; + this.infix = (LangUtil.isEmpty(infix) ? null : infix); + } + + /** + * @return false if this message is null, of true if we seek any kind (null) or if this has the exact kind we seek and this + * has any text sought + */ + public boolean handleMessage(IMessage message) { + return ((null != message) && !isIgnoring(message.getKind()) && textIn(message)); + } + + /** @return true if handleMessage would return false for a message of this kind */ + public boolean isIgnoring(IMessage.Kind kind) { + if (!floor) { + return ((null != sought) && (sought != kind)); + } else if (null == sought) { + return false; + } else { + return (0 < IMessage.Kind.COMPARATOR.compare(sought, kind)); + } + } + + public void dontIgnore(IMessage.Kind kind) { + + } + + private boolean textIn(IMessage message) { + if (null == infix) { + return true; + } + String text = message.getMessage(); + return (text.indexOf(infix) != -1); + } public void ignore(Kind kind) { } - } - - // ------------------ components to render messages - /** parameterize rendering behavior for messages */ - public static interface IMessageRenderer { - String renderToString(IMessage message); - } - - - /** render message more verbosely if it is worse */ - public static final IMessageRenderer MESSAGE_SCALED = new IMessageRenderer() { - public String toString() { return "MESSAGE_SCALED"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - IMessage.Kind kind = message.getKind(); - int level = 3; - if ((kind == IMessage.ABORT) || (kind == IMessage.FAIL)) { - level = 1; - } else if ((kind == IMessage.ERROR) || (kind == IMessage.WARNING)) { - level = 2; - } else { - level = 3; - } - String result = null; - switch (level) { - case (1) : - result = MESSAGE_TOSTRING.renderToString(message); - break; - case (2) : - result = MESSAGE_LINE.renderToString(message); - break; - case (3) : - result = MESSAGE_SHORT.renderToString(message); - break; - } - Throwable thrown = message.getThrown(); - if (null != thrown) { - if (level == 3) { - result += "Thrown: \n" + LangUtil.renderExceptionShort(thrown); - } else { - result += "Thrown: \n" + LangUtil.renderException(thrown); - } - } - - return result; - } - }; - - /** render message as label, i.e., less than 33 char */ - public static final IMessageRenderer MESSAGE_LABEL = new IMessageRenderer() { - public String toString() { return "MESSAGE_LABEL"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return renderMessageLine(message, 5, 5, 32); - } - }; - - /** render message as label, i.e., less than 33 char, with no source location */ - public static final IMessageRenderer MESSAGE_LABEL_NOLOC = new IMessageRenderer() { - public String toString() { return "MESSAGE_LABEL_NOLOC"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return renderMessageLine(message, 10, 0, 32); - } - }; - - /** render message as line, i.e., less than 75 char, no internal line sep */ - public static final IMessageRenderer MESSAGE_LINE = new IMessageRenderer() { - public String toString() { return "MESSAGE_LINE"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return renderMessageLine(message, 8, 2, 74); - } - }; - - /** render message as line, i.e., less than 75 char, no internal line sep, - * trying to trim text as needed to end with a full source location */ - public static final IMessageRenderer MESSAGE_LINE_FORCE_LOC = new IMessageRenderer() { - public String toString() { return "MESSAGE_LINE_FORCE_LOC"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return renderMessageLine(message, 2, 40, 74); - } - }; - - /** render message without restriction, up to 10K, including throwable */ - public static final IMessageRenderer MESSAGE_ALL = new IMessageRenderer() { - public String toString() { return "MESSAGE_ALL"; } - public String renderToString(IMessage message) { - return renderMessage(message); - } - }; - -// /** render message without restriction, up to 10K, including (but eliding) throwable */ -// public static final IMessageRenderer MESSAGE_ALL_ELIDED= new IMessageRenderer() { -// public String toString() { return "MESSAGE_ALL_ELIDED"; } -// public String renderToString(IMessage message) { -// return renderMessage(message, true); -// } -// }; - - /** render message without restriction, except any Throwable thrown */ - public static final IMessageRenderer MESSAGE_MOST = new IMessageRenderer() { - public String toString() { return "MESSAGE_MOST"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return renderMessageLine(message, 1, 1, 10000); - } - }; - - /** render message as wide line, i.e., less than 256 char, no internal line sep, - * except any Throwable thrown - */ - public static final IMessageRenderer MESSAGE_WIDELINE = new IMessageRenderer() { - public String toString() { return "MESSAGE_WIDELINE"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return renderMessageLine(message, 8, 2, 255); // XXX revert to 256 - } - }; - /** render message using its toString() or "((IMessage) null)" */ - public static final IMessageRenderer MESSAGE_TOSTRING = new IMessageRenderer() { - public String toString() { return "MESSAGE_TOSTRING"; } - public String renderToString(IMessage message) { - if (null == message) { - return "((IMessage) null)"; - } - return message.toString(); - } - }; - - /** render message using toShortString(IMessage)" */ - public static final IMessageRenderer MESSAGE_SHORT = new IMessageRenderer() { - public String toString() { return "MESSAGE_SHORT"; } - public String renderToString(IMessage message) { - return toShortString(message); - } - }; - - /** - * This renders IMessage as String, ignoring empty elements - * and eliding any thrown stack traces. - * @return "((IMessage) null)" if null or String rendering otherwise, - * including everything (esp. throwable stack trace) - * @see renderSourceLocation(ISourceLocation loc) - */ - public static String renderMessage(IMessage message) { - return renderMessage(message, true); - } - - /** - * This renders IMessage as String, ignoring empty elements - * and eliding any thrown. - * @return "((IMessage) null)" if null or String rendering otherwise, - * including everything (esp. throwable stack trace) - * @see renderSourceLocation(ISourceLocation loc) - */ - public static String renderMessage(IMessage message, boolean elide) { - if (null == message) { - return "((IMessage) null)"; - } - - ISourceLocation loc = message.getSourceLocation(); - String locString = (null == loc ? "" : " at " + loc); - - String result = message.getKind() + locString + " " + message.getMessage(); - - Throwable thrown = message.getThrown(); - if (thrown != null) { - result += " -- " + LangUtil.renderExceptionShort(thrown); - result += "\n" + LangUtil.renderException(thrown, elide); - } - - if (message.getExtraSourceLocations().isEmpty()) { - return result; - } - else { - return addExtraSourceLocations(message, result); - } - } - - public static String addExtraSourceLocations( - IMessage message, - String baseMessage) - { + } + + // ------------------ components to render messages + /** parameterize rendering behavior for messages */ + public static interface IMessageRenderer { + String renderToString(IMessage message); + } + + /** render message more verbosely if it is worse */ + public static final IMessageRenderer MESSAGE_SCALED = new IMessageRenderer() { + public String toString() { + return "MESSAGE_SCALED"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + IMessage.Kind kind = message.getKind(); + int level = 3; + if ((kind == IMessage.ABORT) || (kind == IMessage.FAIL)) { + level = 1; + } else if ((kind == IMessage.ERROR) || (kind == IMessage.WARNING)) { + level = 2; + } else { + level = 3; + } + String result = null; + switch (level) { + case (1): + result = MESSAGE_TOSTRING.renderToString(message); + break; + case (2): + result = MESSAGE_LINE.renderToString(message); + break; + case (3): + result = MESSAGE_SHORT.renderToString(message); + break; + } + Throwable thrown = message.getThrown(); + if (null != thrown) { + if (level == 3) { + result += "Thrown: \n" + LangUtil.renderExceptionShort(thrown); + } else { + result += "Thrown: \n" + LangUtil.renderException(thrown); + } + } + + return result; + } + }; + + /** render message as label, i.e., less than 33 char */ + public static final IMessageRenderer MESSAGE_LABEL = new IMessageRenderer() { + public String toString() { + return "MESSAGE_LABEL"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return renderMessageLine(message, 5, 5, 32); + } + }; + + /** render message as label, i.e., less than 33 char, with no source location */ + public static final IMessageRenderer MESSAGE_LABEL_NOLOC = new IMessageRenderer() { + public String toString() { + return "MESSAGE_LABEL_NOLOC"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return renderMessageLine(message, 10, 0, 32); + } + }; + + /** render message as line, i.e., less than 75 char, no internal line sep */ + public static final IMessageRenderer MESSAGE_LINE = new IMessageRenderer() { + public String toString() { + return "MESSAGE_LINE"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return renderMessageLine(message, 8, 2, 74); + } + }; + + /** + * render message as line, i.e., less than 75 char, no internal line sep, trying to trim text as needed to end with a full + * source location + */ + public static final IMessageRenderer MESSAGE_LINE_FORCE_LOC = new IMessageRenderer() { + public String toString() { + return "MESSAGE_LINE_FORCE_LOC"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return renderMessageLine(message, 2, 40, 74); + } + }; + + /** render message without restriction, up to 10K, including throwable */ + public static final IMessageRenderer MESSAGE_ALL = new IMessageRenderer() { + public String toString() { + return "MESSAGE_ALL"; + } + + public String renderToString(IMessage message) { + return renderMessage(message); + } + }; + + // /** render message without restriction, up to 10K, including (but eliding) throwable */ + // public static final IMessageRenderer MESSAGE_ALL_ELIDED= new IMessageRenderer() { + // public String toString() { return "MESSAGE_ALL_ELIDED"; } + // public String renderToString(IMessage message) { + // return renderMessage(message, true); + // } + // }; + + /** render message without restriction, except any Throwable thrown */ + public static final IMessageRenderer MESSAGE_MOST = new IMessageRenderer() { + public String toString() { + return "MESSAGE_MOST"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return renderMessageLine(message, 1, 1, 10000); + } + }; + + /** + * render message as wide line, i.e., less than 256 char, no internal line sep, except any Throwable thrown + */ + public static final IMessageRenderer MESSAGE_WIDELINE = new IMessageRenderer() { + public String toString() { + return "MESSAGE_WIDELINE"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return renderMessageLine(message, 8, 2, 255); // XXX revert to 256 + } + }; + /** render message using its toString() or "((IMessage) null)" */ + public static final IMessageRenderer MESSAGE_TOSTRING = new IMessageRenderer() { + public String toString() { + return "MESSAGE_TOSTRING"; + } + + public String renderToString(IMessage message) { + if (null == message) { + return "((IMessage) null)"; + } + return message.toString(); + } + }; + + /** render message using toShortString(IMessage)" */ + public static final IMessageRenderer MESSAGE_SHORT = new IMessageRenderer() { + public String toString() { + return "MESSAGE_SHORT"; + } + + public String renderToString(IMessage message) { + return toShortString(message); + } + }; + + /** + * This renders IMessage as String, ignoring empty elements and eliding any thrown stack traces. + * + * @return "((IMessage) null)" if null or String rendering otherwise, including everything (esp. throwable stack trace) + * @see renderSourceLocation(ISourceLocation loc) + */ + public static String renderMessage(IMessage message) { + return renderMessage(message, true); + } + + /** + * This renders IMessage as String, ignoring empty elements and eliding any thrown. + * + * @return "((IMessage) null)" if null or String rendering otherwise, including everything (esp. throwable stack trace) + * @see renderSourceLocation(ISourceLocation loc) + */ + public static String renderMessage(IMessage message, boolean elide) { + if (null == message) { + return "((IMessage) null)"; + } + + ISourceLocation loc = message.getSourceLocation(); + String locString = (null == loc ? "" : " at " + loc); + + String result = message.getKind() + locString + " " + message.getMessage(); + + Throwable thrown = message.getThrown(); + if (thrown != null) { + result += " -- " + LangUtil.renderExceptionShort(thrown); + result += "\n" + LangUtil.renderException(thrown, elide); + } + + if (message.getExtraSourceLocations().isEmpty()) { + return result; + } else { + return addExtraSourceLocations(message, result); + } + } + + public static String addExtraSourceLocations(IMessage message, String baseMessage) { StringWriter buf = new StringWriter(); PrintWriter writer = new PrintWriter(buf); writer.println(baseMessage); - for (Iterator iter = message.getExtraSourceLocations().iterator(); iter.hasNext();) { - ISourceLocation element = (ISourceLocation) iter.next(); - if (element!=null) { - writer.print("\tsee also: " + element.toString()); - if (iter.hasNext()) { - writer.println(); - } - } - } - try { buf.close(); } - catch (IOException ioe) {} - return buf.getBuffer().toString(); + for (Iterator iter = message.getExtraSourceLocations().iterator(); iter.hasNext();) { + ISourceLocation element = iter.next(); + if (element != null) { + writer.print("\tsee also: " + element.toString()); + if (iter.hasNext()) { + writer.println(); + } + } + } + try { + buf.close(); + } catch (IOException ioe) { + } + return buf.getBuffer().toString(); + } + + /** + * Render ISourceLocation to String, ignoring empty elements (null or ISourceLocation.NO_FILE or ISourceLocation.NO_COLUMN + * (though implementations may return 0 from getColumn() when passed NO_COLUMN as input)). + * + * @return "((ISourceLocation) null)" if null or String rendering + * + *
+	 * {file:}line{:column}
+	 * 
+ * + */ + public static String renderSourceLocation(ISourceLocation loc) { + if (null == loc) { + return "((ISourceLocation) null)"; + } + StringBuffer sb = new StringBuffer(); + + File sourceFile = loc.getSourceFile(); + if (sourceFile != ISourceLocation.NO_FILE) { + sb.append(sourceFile.getPath()); + sb.append(":"); + } + int line = loc.getLine(); + sb.append("" + line); + + int column = loc.getColumn(); + if (column != ISourceLocation.NO_COLUMN) { + sb.append(":" + column); + } + + return sb.toString(); + } + + /** + * Render message in a line. IMessage.Kind is always printed, then any unqualified exception class, then the remainder of text + * and location according to their relative scale, all to fit in max characters or less. This does not render thrown except for + * the unqualified class name + * + * @param max the number of characters - forced to 32..10000 + * @param textScale relative proportion to spend on message and/or exception message, relative to source location - if 0, + * message is suppressed + * @param locScale relative proportion to spend on source location suppressed if 0 + * @return "((IMessage) null)" or message per spec + */ + public static String renderMessageLine(IMessage message, int textScale, int locScale, int max) { + + if (null == message) { + return "((IMessage) null)"; + } + if (max < 32) { + max = 32; + } else if (max > 10000) { + max = 10000; + } + if (0 > textScale) { + textScale = -textScale; + } + if (0 > locScale) { + locScale = -locScale; + } + + String text = message.getMessage(); + Throwable thrown = message.getThrown(); + ISourceLocation sl = message.getSourceLocation(); + IMessage.Kind kind = message.getKind(); + StringBuffer result = new StringBuffer(); + result.append(kind.toString()); + result.append(": "); + if (null != thrown) { + result.append(LangUtil.unqualifiedClassName(thrown) + " "); + if ((null == text) || ("".equals(text))) { + text = thrown.getMessage(); + } + } + + if (0 == textScale) { + text = ""; + } else if ((null != text) && (null != thrown)) { + // decide between message and exception text? + String s = thrown.getMessage(); + if ((null != s) && (0 < s.length())) { + text += " - " + s; + } + } + String loc = ""; + if ((0 != locScale) && (null != sl)) { + File f = sl.getSourceFile(); + if (f == ISourceLocation.NO_FILE) { + f = null; + } + if (null != f) { + loc = f.getName(); + } + int line = sl.getLine(); + int col = sl.getColumn(); + int end = sl.getEndLine(); + if ((0 == line) && (0 == col) && (0 == end)) { + // ignore numbers if default + } else { + loc += ":" + line + (col == 0 ? "" : ":" + col); + if (line != end) { // XXX consider suppressing nonstandard... + loc += ":" + end; + } + } + if (!LangUtil.isEmpty(loc)) { + loc = "@[" + loc; // matching "]" added below after clipping + } + } + + // now budget between text and loc + float totalScale = locScale + textScale; + float remainder = max - result.length() - 4; + if ((remainder > 0) && (0 < totalScale)) { + int textSize = (int) (remainder * textScale / totalScale); + int locSize = (int) (remainder * locScale / totalScale); + // adjust for underutilization + int extra = locSize - loc.length(); + if (0 < extra) { + locSize = loc.length(); + textSize += extra; + } + extra = textSize - text.length(); + if (0 < extra) { + textSize = text.length(); + if (locSize < loc.length()) { + locSize += extra; + } + } + if (locSize > loc.length()) { + locSize = loc.length(); + } + if (textSize > text.length()) { + textSize = text.length(); + } + if (0 < textSize) { + result.append(text.substring(0, textSize)); + } + if (0 < locSize) { + if (0 < textSize) { + result.append(" "); + } + result.append(loc.substring(0, locSize) + "]"); + } + } + return result.toString(); } - - - - - - - /** - * Render ISourceLocation to String, ignoring empty elements - * (null or ISourceLocation.NO_FILE or ISourceLocation.NO_COLUMN - * (though implementations may return 0 from getColumn() when - * passed NO_COLUMN as input)). - * @return "((ISourceLocation) null)" if null or String rendering - *
{file:}line{:column}
- * - */ - public static String renderSourceLocation(ISourceLocation loc) { - if (null == loc) { - return "((ISourceLocation) null)"; - } - StringBuffer sb = new StringBuffer(); - - File sourceFile = loc.getSourceFile(); - if (sourceFile != ISourceLocation.NO_FILE) { - sb.append(sourceFile.getPath()); - sb.append(":"); - } - int line = loc.getLine(); - sb.append("" + line); - - int column = loc.getColumn(); - if (column != ISourceLocation.NO_COLUMN) { - sb.append(":" + column); - } - - return sb.toString(); - } - - /** - * Render message in a line. - * IMessage.Kind is always printed, then any unqualified exception class, - * then the remainder of text and location according to their relative scale, - * all to fit in max characters or less. - * This does not render thrown except for the unqualified class name - * @param max the number of characters - forced to 32..10000 - * @param textScale relative proportion to spend on message and/or exception - * message, relative to source location - if 0, message is suppressed - * @param locScale relative proportion to spend on source location - * suppressed if 0 - * @return "((IMessage) null)" or message per spec - */ - public static String renderMessageLine( - IMessage message, - int textScale, - int locScale, - int max) { - - if (null == message) { - return "((IMessage) null)"; - } - if (max < 32) { - max = 32; - } else if (max > 10000) { - max = 10000; - } - if (0 > textScale) { - textScale = -textScale; - } - if (0 > locScale) { - locScale = -locScale; - } - - String text = message.getMessage(); - Throwable thrown = message.getThrown(); - ISourceLocation sl = message.getSourceLocation(); - IMessage.Kind kind = message.getKind(); - StringBuffer result = new StringBuffer(); - result.append(kind.toString()); - result.append(": "); - if (null != thrown) { - result.append(LangUtil.unqualifiedClassName(thrown) + " "); - if ((null == text) || ("".equals(text))) { - text = thrown.getMessage(); - } - } - - if (0 == textScale) { - text = ""; - } else if ((null != text) && (null != thrown)) { - // decide between message and exception text? - String s = thrown.getMessage(); - if ((null != s) && (0 < s.length())) { - text += " - " + s; - } - } - String loc = ""; - if ((0 != locScale) && (null != sl)) { - File f = sl.getSourceFile(); - if (f == ISourceLocation.NO_FILE) { - f = null; - } - if (null != f) { - loc = f.getName(); - } - int line = sl.getLine(); - int col = sl.getColumn(); - int end = sl.getEndLine(); - if ((0 == line) && (0 == col) && (0 == end)) { - // ignore numbers if default - } else { - loc += ":" + line + (col == 0 ? "" : ":" + col); - if (line != end) { // XXX consider suppressing nonstandard... - loc += ":" + end; - } - } - if (!LangUtil.isEmpty(loc)) { - loc = "@[" + loc; // matching "]" added below after clipping - } - } - - // now budget between text and loc - float totalScale = locScale + textScale; - float remainder = max - result.length() - 4; - if ((remainder > 0) && (0 < totalScale)) { - int textSize = (int) (remainder * textScale/totalScale); - int locSize = (int) (remainder * locScale/totalScale); - // adjust for underutilization - int extra = locSize - loc.length(); - if (0 < extra) { - locSize = loc.length(); - textSize += extra; - } - extra = textSize - text.length(); - if (0 < extra) { - textSize = text.length(); - if (locSize < loc.length()) { - locSize += extra; - } - } - if (locSize > loc.length()) { - locSize = loc.length(); - } - if (textSize > text.length()) { - textSize = text.length(); - } - if (0 < textSize) { - result.append(text.substring(0, textSize)); - } - if (0 < locSize) { - if (0 < textSize) { - result.append(" "); - } - result.append(loc.substring(0, locSize) + "]"); - } - } - return result.toString(); - } /** @return String of the form "{(# {type}) }.." for message kinds, skipping 0 */ - public static String renderCounts(IMessageHolder holder) { - if (0 == holder.numMessages(null, false)) { - return "(0 messages)"; - } - StringBuffer sb = new StringBuffer(); - for (Iterator iter = IMessage.KINDS.iterator(); iter.hasNext();) { - IMessage.Kind kind = (IMessage.Kind) iter.next(); + public static String renderCounts(IMessageHolder holder) { + if (0 == holder.numMessages(null, false)) { + return "(0 messages)"; + } + StringBuffer sb = new StringBuffer(); + for (IMessage.Kind kind : IMessage.KINDS) { int num = holder.numMessages(kind, false); - if (0 < num) { - sb.append(" (" + num + " " + kind + ") "); - } - } - return sb.toString(); - } - - /** - * Factory for handler adapted to PrintStream - * XXX weak - only handles println(String) - * @param handler the IMessageHandler sink for the messages generated - * @param kind the IMessage.Kind of message to create - * @param overage the OuputStream for text not captured by the handler - * (if null, System.out used) - * @throws IllegalArgumentException if kind or handler is null - */ - public static PrintStream handlerPrintStream(final IMessageHandler handler, - final IMessage.Kind kind, final OutputStream overage, final String prefix) { - LangUtil.throwIaxIfNull(handler, "handler"); - LangUtil.throwIaxIfNull(kind, "kind"); - class HandlerPrintStream extends PrintStream { - HandlerPrintStream() { - super(null == overage ? System.out : overage); - } - public void println() { - println(""); - } - public void println(Object o) { - println(null == o ? "null" : o.toString()); - } + if (0 < num) { + sb.append(" (" + num + " " + kind + ") "); + } + } + return sb.toString(); + } + + /** + * Factory for handler adapted to PrintStream XXX weak - only handles println(String) + * + * @param handler the IMessageHandler sink for the messages generated + * @param kind the IMessage.Kind of message to create + * @param overage the OuputStream for text not captured by the handler (if null, System.out used) + * @throws IllegalArgumentException if kind or handler is null + */ + public static PrintStream handlerPrintStream(final IMessageHandler handler, final IMessage.Kind kind, + final OutputStream overage, final String prefix) { + LangUtil.throwIaxIfNull(handler, "handler"); + LangUtil.throwIaxIfNull(kind, "kind"); + class HandlerPrintStream extends PrintStream { + HandlerPrintStream() { + super(null == overage ? System.out : overage); + } + + public void println() { + println(""); + } + + public void println(Object o) { + println(null == o ? "null" : o.toString()); + } + public void println(String input) { - String textMessage = (null == prefix ? input : prefix + input); - IMessage m = new Message(textMessage, kind, null, null); - handler.handleMessage(m); + String textMessage = (null == prefix ? input : prefix + input); + IMessage m = new Message(textMessage, kind, null, null); + handler.handleMessage(m); + } + } + return new HandlerPrintStream(); + } + + /** utility class */ + private MessageUtil() { + } + + /** + * Handle all messages in the second handler using the first + * + * @param handler the IMessageHandler sink for all messages in source + * @param holder the IMessageHolder source for all messages to handle + * @param fastFail if true, stop on first failure + * @return false if any sink.handleMessage(..) failed + */ + public static boolean handleAll(IMessageHandler sink, IMessageHolder source, boolean fastFail) { + return handleAll(sink, source, null, true, fastFail); + } + + /** + * Handle messages in the second handler using the first + * + * @param handler the IMessageHandler sink for all messages in source + * @param holder the IMessageHolder source for all messages to handle + * @param kind the IMessage.Kind to select, if not null + * @param orGreater if true, also accept greater kinds + * @param fastFail if true, stop on first failure + * @return false if any sink.handleMessage(..) failed + */ + public static boolean handleAll(IMessageHandler sink, IMessageHolder source, IMessage.Kind kind, boolean orGreater, + boolean fastFail) { + LangUtil.throwIaxIfNull(sink, "sink"); + LangUtil.throwIaxIfNull(source, "source"); + return handleAll(sink, source.getMessages(kind, orGreater), fastFail); + } + + /** + * Handle messages in the second handler using the first if they are NOT of this kind (optionally, or greater). If you pass null + * as the kind, then all messages are ignored and this returns true. + * + * @param handler the IMessageHandler sink for all messages in source + * @param holder the IMessageHolder source for all messages to handle + * @param kind the IMessage.Kind to reject, if not null + * @param orGreater if true, also reject greater kinds + * @param fastFail if true, stop on first failure + * @return false if any sink.handleMessage(..) failed + */ + public static boolean handleAllExcept(IMessageHandler sink, IMessageHolder source, IMessage.Kind kind, boolean orGreater, + boolean fastFail) { + LangUtil.throwIaxIfNull(sink, "sink"); + LangUtil.throwIaxIfNull(source, "source"); + if (null == kind) { + return true; + } + IMessage[] messages = getMessagesExcept(source, kind, orGreater); + return handleAll(sink, messages, fastFail); + } + + /** + * Handle messages in the sink. + * + * @param handler the IMessageHandler sink for all messages in source + * @param sources the IMessage[] messages to handle + * @param fastFail if true, stop on first failure + * @return false if any sink.handleMessage(..) failed + * @throws IllegalArgumentException if sink is null + */ + public static boolean handleAll(IMessageHandler sink, IMessage[] sources, boolean fastFail) { + LangUtil.throwIaxIfNull(sink, "sink"); + if (LangUtil.isEmpty(sources)) { + return true; + } + boolean result = true; + for (int i = 0; i < sources.length; i++) { + if (!sink.handleMessage(sources[i])) { + if (fastFail) { + return false; + } + if (result) { + result = false; + } } - } - return new HandlerPrintStream(); - } - - /** utility class */ - private MessageUtil() {} - - /** - * Handle all messages in the second handler using the first - * @param handler the IMessageHandler sink for all messages in source - * @param holder the IMessageHolder source for all messages to handle - * @param fastFail if true, stop on first failure - * @return false if any sink.handleMessage(..) failed - */ - public static boolean handleAll( - IMessageHandler sink, - IMessageHolder source, - boolean fastFail) { - return handleAll(sink, source, null, true, fastFail); - } - - /** - * Handle messages in the second handler using the first - * @param handler the IMessageHandler sink for all messages in source - * @param holder the IMessageHolder source for all messages to handle - * @param kind the IMessage.Kind to select, if not null - * @param orGreater if true, also accept greater kinds - * @param fastFail if true, stop on first failure - * @return false if any sink.handleMessage(..) failed - */ - public static boolean handleAll( - IMessageHandler sink, - IMessageHolder source, - IMessage.Kind kind, - boolean orGreater, - boolean fastFail) { - LangUtil.throwIaxIfNull(sink, "sink"); - LangUtil.throwIaxIfNull(source, "source"); - return handleAll(sink, source.getMessages(kind, orGreater), fastFail); - } - - /** - * Handle messages in the second handler using the first - * if they are NOT of this kind (optionally, or greater). - * If you pass null as the kind, then all messages are - * ignored and this returns true. - * @param handler the IMessageHandler sink for all messages in source - * @param holder the IMessageHolder source for all messages to handle - * @param kind the IMessage.Kind to reject, if not null - * @param orGreater if true, also reject greater kinds - * @param fastFail if true, stop on first failure - * @return false if any sink.handleMessage(..) failed - */ - public static boolean handleAllExcept( - IMessageHandler sink, - IMessageHolder source, - IMessage.Kind kind, - boolean orGreater, - boolean fastFail) { - LangUtil.throwIaxIfNull(sink, "sink"); - LangUtil.throwIaxIfNull(source, "source"); - if (null == kind) { - return true; - } - IMessage[] messages = getMessagesExcept(source, kind, orGreater); - return handleAll(sink, messages, fastFail); - } - - /** - * Handle messages in the sink. - * @param handler the IMessageHandler sink for all messages in source - * @param sources the IMessage[] messages to handle - * @param fastFail if true, stop on first failure - * @return false if any sink.handleMessage(..) failed - * @throws IllegalArgumentException if sink is null - */ - public static boolean handleAll( - IMessageHandler sink, - IMessage[] sources, - boolean fastFail) { - LangUtil.throwIaxIfNull(sink, "sink"); - if (LangUtil.isEmpty(sources)) { - return true; - } - boolean result = true; - for (int i = 0; i < sources.length; i++) { - if (!sink.handleMessage(sources[i])) { - if (fastFail) { - return false; - } - if (result) { - result = false; - } - } - } - return result; - } + } + return result; + } } diff --git a/bridge/src/org/aspectj/bridge/ReflectionFactory.java b/bridge/src/org/aspectj/bridge/ReflectionFactory.java index 78a716c3a..8eb65b3a0 100644 --- a/bridge/src/org/aspectj/bridge/ReflectionFactory.java +++ b/bridge/src/org/aspectj/bridge/ReflectionFactory.java @@ -20,87 +20,84 @@ import java.util.Arrays; * */ public class ReflectionFactory { // XXX lease, pool - public static final String OLD_AJC = "bridge.tools.impl.OldAjc"; - public static final String ECLIPSE = "org.aspectj.ajdt.ajc.AjdtCommand"; - - private static final Object[] NONE = new Object[0]; - - /** - * Produce a compiler as an ICommand. - * @param cname the fully-qualified class name of the command - * to create by reflection (assuming a public no-argument constructor). - * @return ICommand compiler or null - */ - public static ICommand makeCommand(String cname, - IMessageHandler errorSink) { - return (ICommand) make(ICommand.class, cname, NONE, errorSink); - } - - /** - * Make an object of type c by reflectively loading the class - * cname and creating an instance using args (if any), - * signalling errors (if any) to any errorSink. - */ - private static Object make(Class c, String cname, Object[] args, - IMessageHandler errorSink) { - final boolean makeErrors = (null != errorSink); - Object result = null; - try { - final Class cfn = Class.forName(cname); - String error = null; - if (args == NONE) { - result = cfn.newInstance(); - } else { - Class[] types = getTypes(args); - Constructor constructor = cfn.getConstructor(types); - if (null != constructor) { - result = constructor.newInstance(args); - } else { - if (makeErrors) { - error = "no constructor for " + c + " using " - + Arrays.asList(types); - } - } - } - if (null != result) { - if (!c.isAssignableFrom(result.getClass())) { - if (makeErrors) { - error = "expecting type " + c + " got " + result.getClass(); - } - result = null; - } - } - if (null != error) { - IMessage mssg = new Message(error, IMessage.FAIL, null, null); - errorSink.handleMessage(mssg); - } - } catch (Throwable t) { - if (makeErrors) { - String mssg = "ReflectionFactory unable to load " - + cname + " as " + c.getName(); - IMessage m = new Message(mssg, IMessage.FAIL, t, null); - errorSink.handleMessage(m); - } - } - return result; - } + public static final String OLD_AJC = "bridge.tools.impl.OldAjc"; + public static final String ECLIPSE = "org.aspectj.ajdt.ajc.AjdtCommand"; - /** - * @return Class[] with types of args or matching null elements - */ - private static Class[] getTypes(Object[] args) { - if ((null == args) || (0 < args.length)) { - return new Class[0]; - } else { - Class[] result = new Class[args.length]; - for (int i = 0; i < result.length; i++) { - if (null != args[i]) { - result[i] = args[i].getClass(); - } - } - return result; - } - } - - private ReflectionFactory(){} + private static final Object[] NONE = new Object[0]; + + /** + * Produce a compiler as an ICommand. + * + * @param cname the fully-qualified class name of the command to create by reflection (assuming a public no-argument + * constructor). + * @return ICommand compiler or null + */ + public static ICommand makeCommand(String cname, IMessageHandler errorSink) { + return (ICommand) make(ICommand.class, cname, NONE, errorSink); + } + + /** + * Make an object of type c by reflectively loading the class cname and creating an instance using args (if any), signalling + * errors (if any) to any errorSink. + */ + private static Object make(Class c, String cname, Object[] args, IMessageHandler errorSink) { + final boolean makeErrors = (null != errorSink); + Object result = null; + try { + final Class cfn = Class.forName(cname); + String error = null; + if (args == NONE) { + result = cfn.newInstance(); + } else { + Class[] types = getTypes(args); + Constructor constructor = cfn.getConstructor(types); + if (null != constructor) { + result = constructor.newInstance(args); + } else { + if (makeErrors) { + error = "no constructor for " + c + " using " + Arrays.asList(types); + } + } + } + if (null != result) { + if (!c.isAssignableFrom(result.getClass())) { + if (makeErrors) { + error = "expecting type " + c + " got " + result.getClass(); + } + result = null; + } + } + if (null != error) { + IMessage mssg = new Message(error, IMessage.FAIL, null, null); + errorSink.handleMessage(mssg); + } + } catch (Throwable t) { + if (makeErrors) { + String mssg = "ReflectionFactory unable to load " + cname + " as " + c.getName(); + IMessage m = new Message(mssg, IMessage.FAIL, t, null); + errorSink.handleMessage(m); + } + } + return result; + } + + /** + * @return Class[] with types of args or matching null elements + */ + private static Class[] getTypes(Object[] args) { + if ((null == args) || (0 < args.length)) { + return new Class[0]; + } else { + Class[] result = new Class[args.length]; + for (int i = 0; i < result.length; i++) { + if (null != args[i]) { + result[i] = args[i].getClass(); + } + } + return result; + } + } + + private ReflectionFactory() { + } } diff --git a/bridge/src/org/aspectj/bridge/SourceLocation.java b/bridge/src/org/aspectj/bridge/SourceLocation.java index e72673fde..739dd52ab 100644 --- a/bridge/src/org/aspectj/bridge/SourceLocation.java +++ b/bridge/src/org/aspectj/bridge/SourceLocation.java @@ -26,7 +26,7 @@ import org.aspectj.util.LangUtil; * @see org.aspectj.tools.ide.SourceLine * @see org.aspectj.testing.harness.ErrorLine */ -public class SourceLocation implements ISourceLocation, java.io.Serializable { +public class SourceLocation implements ISourceLocation { private static final long serialVersionUID = -5434765814401009794L;