blob: 479904784da2f6231cc530a574893296b4c446e2 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2000, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.jcommons.status.eplatform;
import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.ARRAY_CONTENTS;
import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.FIELD;
import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.PARAMETER;
import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.RETURN_TYPE;
import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.TYPE_ARGUMENT;
import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.TYPE_BOUND;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.BasicProgressMonitor;
import org.eclipse.statet.jcommons.status.BasicProgressMonitor.ProgressData;
import org.eclipse.statet.jcommons.status.InfoStatus;
import org.eclipse.statet.jcommons.status.MultiStatus;
import org.eclipse.statet.jcommons.status.NullProgressMonitor;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.Status;
import org.eclipse.statet.jcommons.status.StatusException;
/**
* A utility class to work with IStatus.
*/
@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
public class EStatusUtils {
private final static IStatus[] NO_ECHILDREN= new IStatus[0];
private static class EStatus implements IStatus {
private final Status status;
public EStatus(final Status status) {
this.status= status;
}
@Override
public int getSeverity() {
return this.status.getSeverity() & 0xFF;
}
@Override
public boolean isOK() {
return (this.status.getSeverity() == Status.OK);
}
@Override
public boolean matches(final int severityMask) {
return ((this.status.getSeverity() & severityMask) != 0);
}
@Override
public String getPlugin() {
return this.status.getBundleId();
}
@Override
public int getCode() {
return this.status.getCode();
}
@Override
public String getMessage() {
return this.status.getMessage();
}
@Override
public @Nullable Throwable getException() {
return this.status.getException();
}
@Override
public boolean isMultiStatus() {
return false;
}
@Override
public IStatus[] getChildren() {
return NO_ECHILDREN;
}
@Override
public String toString() {
return this.status.toString();
}
}
private static class EMultiStatus extends EStatus {
private final IStatus [] children;
public EMultiStatus(final Status status, final IStatus[] children) {
super(status);
this.children= children;
}
@Override
public boolean isMultiStatus() {
return true;
}
@Override
public IStatus [] getChildren() {
return this.children;
}
}
public static IStatus convert(final Status status) {
if (status.isMultiStatus()) {
final var children= status.getChildren();
final var convertedChildren= new @NonNull IStatus[children.size()];
for (int i= 0; i < convertedChildren.length; i++) {
convertedChildren[i]= convert(children.get(i));
}
return new EMultiStatus(status, convertedChildren);
}
else {
if (status == Status.OK_STATUS) {
return org.eclipse.core.runtime.Status.OK_STATUS;
}
if (status == Status.CANCEL_STATUS) {
return org.eclipse.core.runtime.Status.CANCEL_STATUS;
}
return new EStatus(status);
}
}
public static Status convert(final IStatus status) {
if (status.isMultiStatus()) {
final var children= status.getChildren();
final var convertedChildren= new @NonNull Status[children.length];
for (int i= 0; i < convertedChildren.length; i++) {
convertedChildren[i]= convert(children[i]);
}
return new MultiStatus(status.getPlugin(), status.getCode(),
status.getMessage(), status.getException(),
ImCollections.newList(convertedChildren) );
}
else {
if (status == org.eclipse.core.runtime.Status.OK_STATUS) {
return Status.OK_STATUS;
}
if (status == org.eclipse.core.runtime.Status.CANCEL_STATUS) {
return Status.CANCEL_STATUS;
}
if (status instanceof EStatus) {
return ((EStatus) status).status;
}
return Status.newStatus(status.getSeverity(),
status.getPlugin(), status.getCode(),
status.getMessage(), status.getException() );
}
}
public static CoreException convert(final StatusException e) {
final CoreException convertedException= new CoreException(convert(e.getStatus()));
e.setStackTrace(e.getStackTrace());
return convertedException;
}
public static StatusException convert(final CoreException e) {
final StatusException convertedException= new StatusException(convert(e.getStatus()));
convertedException.setStackTrace(e.getStackTrace());
return convertedException;
}
private static class EProgressData extends ProgressData {
private static final int TOTAL= 1 << 30;
private final IProgressMonitor monitor;
private int workRemaining= TOTAL;
public EProgressData(final IProgressMonitor monitor) {
this.monitor= monitor;
}
@Override
public boolean isCanceled() {
return this.monitor.isCanceled();
}
@Override
protected void setCanceled(final boolean state) {
this.monitor.setCanceled(state);
}
@Override
protected void onDataChanged(final byte data) {
switch (data) {
case MAIN_TASK_NAME:
this.monitor.subTask(""); //$NON-NLS-1$
this.monitor.setTaskName(getMainTaskName());
break;
case SUB_TASK_NAME:
this.monitor.subTask(getSubTaskName());
break;
case PROGRESS_RATE:
if (this.workRemaining >= 0) {
final int workRemaining= (int) (getProgress() * TOTAL);
if (workRemaining < this.workRemaining) {
this.monitor.worked(this.workRemaining - workRemaining);
}
this.workRemaining= workRemaining;
}
break;
case BLOCKED:
{ final Status blocked= getBlocked();
if (blocked != null) {
this.monitor.setBlocked(EStatusUtils.convert(blocked));
}
else {
this.monitor.clearBlocked();
}
}
}
}
}
public static ProgressMonitor convert(final @Nullable IProgressMonitor eMonitor,
final String name, final int totalWork, final int flags) {
if (eMonitor == null) {
return new NullProgressMonitor().newSubMonitor(flags);
}
final EProgressData data= new EProgressData(eMonitor);
final BasicProgressMonitor convertedMonitor= new BasicProgressMonitor(data, flags);
if (totalWork > 0) {
eMonitor.beginTask(name, EProgressData.TOTAL);
convertedMonitor.beginTask(name, totalWork);
}
else {
eMonitor.beginTask(name, IProgressMonitor.UNKNOWN);
convertedMonitor.beginTask(name, ProgressMonitor.UNKNOWN);
data.workRemaining= -1;
}
return convertedMonitor;
}
public static ProgressMonitor convert(final @Nullable IProgressMonitor eMonitor,
final String name, final int totalWork) {
return convert(eMonitor, name, totalWork, ProgressMonitor.SUPPRESS_NONE);
}
public static ProgressMonitor convert(final @Nullable IProgressMonitor eMonitor,
final int totalWork) {
return convert(eMonitor, "", totalWork, ProgressMonitor.SUPPRESS_NONE); //$NON-NLS-1$
}
public static ProgressMonitor convert(final @Nullable IProgressMonitor eMonitor) {
return convert(eMonitor, "", 1, ProgressMonitor.SUPPRESS_NONE); //$NON-NLS-1$
}
public static ProgressMonitor convertChild(final @Nullable IProgressMonitor eMonitor) {
return convert(eMonitor, "", 1, ProgressMonitor.SUPPRESS_BEGINTASK_NAME); //$NON-NLS-1$
}
private static class EProgressMonitor implements IProgressMonitorWithBlocking {
private static final Status BLOCKED_NO_DETAIL= new InfoStatus("unknown", //$NON-NLS-1$
"blocked" );
private final ProgressMonitor m;
private int workRemaining;
public EProgressMonitor(final ProgressMonitor m) {
this.m= m;
}
@Override
public void beginTask(final String name, final int totalWork) {
this.workRemaining= totalWork;
this.m.beginTask(name, totalWork);
}
@Override
public void setTaskName(final String name) {
this.m.beginTask(name, this.workRemaining);
}
@Override
public void subTask(final String name) {
this.m.beginSubTask(name);
}
@Override
public boolean isCanceled() {
return this.m.isCanceled();
}
@Override
public void setCanceled(final boolean value) {
this.m.setCanceled(value);
}
@Override
public void worked(int work) {
if (this.workRemaining > 0 && work > 0) {
if (work > this.workRemaining) {
work= this.workRemaining;
}
this.workRemaining-= work;
this.m.addWorked(work);
}
}
@Override
public void done() {
this.workRemaining= 0;
this.m.setWorkRemaining(0);
}
@Override
public void internalWorked(final double work) {
}
@Override
public void setBlocked(final @Nullable IStatus reason) {
this.m.setBlocked((reason != null) ? convert(reason) : BLOCKED_NO_DETAIL);
}
@Override
public void clearBlocked() {
this.m.clearBlocked();
}
}
public static IProgressMonitor convert(final @Nullable ProgressMonitor m,
final String name, final int totalWork) {
if (m == null) {
return new org.eclipse.core.runtime.NullProgressMonitor();
}
final EProgressMonitor convertedMonitor= new EProgressMonitor(m);
convertedMonitor.beginTask(name, totalWork);
return convertedMonitor;
}
public static IProgressMonitor convert(final @Nullable ProgressMonitor m,
final int totalWork) {
return convert(m, "", totalWork); //$NON-NLS-1$
}
public static IProgressMonitor convert(final @Nullable ProgressMonitor m) {
if (m == null) {
return new org.eclipse.core.runtime.NullProgressMonitor();
}
return new EProgressMonitor(m);
}
}