/**
* <copyright>
*
* Copyright (c) 2004, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*
* </copyright>
*
* $Id: BasicDiagnostic.java,v 1.14 2007/10/02 13:20:26 emerks Exp $
*/
package net.enilink.komma.common.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.enilink.komma.common.AbstractKommaPlugin;
import net.enilink.komma.common.CommonPlugin;
import org.eclipse.core.runtime.IStatus;
/**
* A basic implementation of a diagnostic that that also acts as a chain.
*/
public class BasicDiagnostic implements Diagnostic, DiagnosticChain {
/**
* The severity.
*
* @see #getSeverity
*/
protected int severity;
/**
* The message.
*
* @see #getMessage
*/
protected String message;
/**
* The message.
*
* @see #getMessage
*/
protected List<Diagnostic> children;
/**
* The data.
*
* @see #getData
*/
protected List<?> data;
/**
* The source.
*
* @see #getSource
*/
protected String source;
/**
* The code.
*
* @see #getCode
*/
protected int code;
/**
* Default Constructor (no initialization for local parameters)
*/
public BasicDiagnostic() {
super();
}
public BasicDiagnostic(String source, int code, String message,
Object[] data) {
this.source = source;
this.code = code;
this.message = message;
this.data = dataAsList(data);
}
public BasicDiagnostic(int severity, String source, int code,
String message, Object[] data) {
this(source, code, message, data);
this.severity = severity;
}
public BasicDiagnostic(String source, int code,
List<? extends Diagnostic> children, String message, Object[] data) {
this(source, code, message, data);
if (children != null) {
for (Diagnostic diagnostic : children) {
add(diagnostic);
}
}
}
protected List<?> dataAsList(Object[] data) {
if (data == null) {
return Collections.emptyList();
} else {
Object[] copy = new Object[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return Arrays.asList(copy);
}
}
protected void setSeverity(int severity) {
this.severity = severity;
}
public int getSeverity() {
return severity;
}
public String getMessage() {
return message;
}
public List<?> getData() {
return data;
}
public List<Diagnostic> getChildren() {
if (children == null) {
return Collections.emptyList();
} else {
return Collections.unmodifiableList(children);
}
}
protected void setSource(String source) {
this.source = source;
}
public String getSource() {
return source;
}
protected void setCode(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void add(Diagnostic diagnostic) {
if (children == null) {
children = new ArrayList<Diagnostic>();
}
children.add(diagnostic);
int childSeverity = diagnostic.getSeverity();
if (childSeverity > getSeverity()) {
severity = childSeverity;
}
}
public void addAll(Diagnostic diagnostic) {
for (Diagnostic child : diagnostic.getChildren()) {
add(child);
}
}
public void merge(Diagnostic diagnostic) {
if (diagnostic.getChildren().isEmpty()) {
add(diagnostic);
} else {
addAll(diagnostic);
}
}
public int recomputeSeverity() {
if (children != null) {
severity = OK;
for (Diagnostic child : children) {
int childSeverity = child instanceof BasicDiagnostic ? ((BasicDiagnostic) child)
.recomputeSeverity() : child.getSeverity();
if (childSeverity > severity) {
severity = childSeverity;
}
}
}
return severity;
}
/**
* Returns the first throwable object available in the {@link #data} list,
* which is set when this diagnostic is instantiated.
*/
public Throwable getException() {
List<?> data = getData();
if (data != null) {
for (Object datum : data) {
if (datum instanceof Throwable) {
return (Throwable) datum;
}
}
}
return null;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Diagnostic ");
switch (severity) {
case OK: {
result.append("OK");
break;
}
case INFO: {
result.append("INFO");
break;
}
case WARNING: {
result.append("WARNING");
break;
}
case ERROR: {
result.append("ERROR");
break;
}
case CANCEL: {
result.append("CANCEL");
break;
}
default: {
result.append(Integer.toHexString(severity));
break;
}
}
result.append(" source=");
result.append(source);
result.append(" code=");
result.append(code);
result.append(' ');
result.append(message);
if (data != null) {
result.append(" data=");
result.append(data);
}
if (children != null) {
result.append(' ');
result.append(children);
}
return result.toString();
}
private static class StatusWrapper implements IStatus {
protected static final IStatus[] EMPTY_CHILDREN = new IStatus[0];
protected Throwable throwable;
protected Diagnostic diagnostic;
protected IStatus[] wrappedChildren;
public StatusWrapper(Diagnostic diagnostic) {
this.diagnostic = diagnostic;
}
public StatusWrapper(DiagnosticException diagnosticException) {
throwable = diagnosticException;
diagnostic = diagnosticException.getDiagnostic();
}
public IStatus[] getChildren() {
if (wrappedChildren == null) {
List<Diagnostic> children = diagnostic.getChildren();
if (children.isEmpty()) {
wrappedChildren = EMPTY_CHILDREN;
} else {
wrappedChildren = new IStatus[children.size()];
for (int i = 0; i < wrappedChildren.length; ++i) {
wrappedChildren[i] = toIStatus(children.get(i));
}
}
}
return wrappedChildren;
}
public int getCode() {
return diagnostic.getCode();
}
public Throwable getException() {
return throwable != null ? throwable : diagnostic.getException();
}
public String getMessage() {
return diagnostic.getMessage();
}
public String getPlugin() {
return diagnostic.getSource();
}
public int getSeverity() {
return diagnostic.getSeverity();
}
public boolean isMultiStatus() {
return !diagnostic.getChildren().isEmpty();
}
public boolean isOK() {
return diagnostic.getSeverity() == OK;
}
public boolean matches(int severityMask) {
return (diagnostic.getSeverity() & severityMask) != 0;
}
@Override
public String toString() {
return diagnostic.toString();
}
public static IStatus convert(Diagnostic diagnostic) {
return diagnostic instanceof DiagnosticWrapper ? ((DiagnosticWrapper) diagnostic).status
: new StatusWrapper(diagnostic);
}
public static IStatus create(DiagnosticException diagnosticException) {
return new StatusWrapper(diagnosticException);
}
}
/**
* Returns the diagnostic viewed as an {@link IStatus}.
*/
public static IStatus toIStatus(Diagnostic diagnostic) {
return StatusWrapper.convert(diagnostic);
}
/**
* Returns the diagnostic exception viewed as an {@link IStatus}.
*/
public static IStatus toIStatus(DiagnosticException diagnosticException) {
return StatusWrapper.create(diagnosticException);
}
private static class DiagnosticWrapper implements Diagnostic {
protected Throwable throwable;
protected IStatus status;
protected List<Diagnostic> wrappedChildren;
protected List<Diagnostic> unmodifiableWrappedChildren;
protected List<Object> data;
public DiagnosticWrapper(IStatus status) {
this.status = status;
}
public int getCode() {
return status.getCode();
}
public String getMessage() {
return status.getMessage();
}
public int getSeverity() {
return status.getSeverity();
}
public String getSource() {
return status.getPlugin();
}
public Throwable getException() {
return status.getException();
}
public List<Diagnostic> basicGetChildren() {
if (wrappedChildren == null) {
IStatus[] children = status.getChildren();
if (children.length == 0) {
wrappedChildren = new ArrayList<Diagnostic>();
} else {
wrappedChildren = new ArrayList<Diagnostic>(children.length);
for (IStatus child : children) {
wrappedChildren.add(toDiagnostic(child));
}
}
}
return wrappedChildren;
}
public List<Diagnostic> getChildren() {
if (unmodifiableWrappedChildren == null) {
unmodifiableWrappedChildren = Collections
.unmodifiableList(basicGetChildren());
}
return unmodifiableWrappedChildren;
}
public List<?> getData() {
if (data == null) {
List<Object> list = new ArrayList<Object>(2);
Throwable exception = getException();
if (exception != null) {
list.add(exception);
}
list.add(status);
data = Collections.unmodifiableList(list);
}
return data;
}
public static Diagnostic convert(IStatus status) {
return status instanceof StatusWrapper ? ((StatusWrapper) status).diagnostic
: new DiagnosticWrapper(status);
}
}
public static Diagnostic toDiagnostic(IStatus status) {
return DiagnosticWrapper.convert(status);
}
/**
* Returns the throwable viewed as a {@link Diagnostic}.
*
* @param throwable
* @return {@link Diagnostic}
*/
public static Diagnostic toDiagnostic(Throwable throwable, Object... data) {
if (throwable instanceof DiagnosticException) {
return ((DiagnosticException) throwable).getDiagnostic();
} else if (throwable instanceof WrappedException) {
return toDiagnostic(throwable.getCause(), data);
}
if (AbstractKommaPlugin.IS_ECLIPSE_RUNNING) {
Diagnostic diagnostic = EclipseHelper.toDiagnostic(throwable, data);
if (diagnostic != null) {
return diagnostic;
}
}
String message = throwable.getClass().getName();
int index = message.lastIndexOf('.');
if (index >= 0) {
message = message.substring(index + 1);
}
if (throwable.getLocalizedMessage() != null) {
message = message + ": " + throwable.getLocalizedMessage();
}
Object[] diagnosticData = Arrays.copyOf(data, data.length + 1);
diagnosticData[diagnosticData.length - 1] = throwable;
BasicDiagnostic basicDiagnostic = new BasicDiagnostic(Diagnostic.ERROR,
CommonPlugin.PLUGIN_ID, 0, message, diagnosticData);
if (throwable.getCause() != null && throwable.getCause() != throwable) {
throwable = throwable.getCause();
basicDiagnostic.add(toDiagnostic(throwable, data));
}
return basicDiagnostic;
}
private static class EclipseHelper {
public static Diagnostic toDiagnostic(Throwable throwable,
Object... data) {
if (throwable instanceof org.eclipse.core.runtime.CoreException) {
IStatus status = ((org.eclipse.core.runtime.CoreException) throwable)
.getStatus();
DiagnosticWrapper wrapperDiagnostic = new DiagnosticWrapper(
status);
Throwable cause = throwable.getCause();
if (cause != null && cause != throwable) {
wrapperDiagnostic.basicGetChildren().add(
BasicDiagnostic.toDiagnostic(cause, data));
}
return wrapperDiagnostic;
}
return null;
}
}
}