blob: 7afe5ef446b1bad3f5a68e989ca5f8daf0c1f8b1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2007 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 Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.navigator.actions;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.expressions.ElementHandler;
import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionConverter;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.internal.navigator.CustomAndExpression;
import org.eclipse.ui.internal.navigator.NavigatorPlugin;
import org.eclipse.ui.internal.navigator.extensions.INavigatorContentExtPtConstants;
import org.eclipse.ui.internal.navigator.extensions.SkeletonActionProvider;
import org.eclipse.ui.navigator.CommonActionProvider;
import org.eclipse.ui.navigator.Priority;
/**
*
*
* @since 3.2
*/
public class CommonActionProviderDescriptor implements
INavigatorContentExtPtConstants {
private static final String DEFAULT_ID = "org.eclipse.ui.navigator.actionProvider"; //$NON-NLS-1$
private static int count = 0;
private final IConfigurationElement configurationElement;
private final boolean isNested;
private Set dependentDescriptors;
private Set overridingDescriptors;
private IConfigurationElement enablementElement;
private Expression enablement;
private boolean hasLoadingFailed;
private String definedId;
private String visibilityId;
private String dependsOnId;
private String overridesId;
private String toString;
private Priority priority;
/**
* @param aConfigElement
* A configuration element with the name "actionProvider" and a
* "class" attribute which subclasses
* {@link CommonActionProvider}.
*/
public CommonActionProviderDescriptor(IConfigurationElement aConfigElement) {
super();
Assert.isTrue(TAG_ACTION_PROVIDER.equals(aConfigElement.getName()));
configurationElement = aConfigElement;
isNested = false;
init();
}
/**
* @param aConfigElement
* A configuration element with the name "actionProvider" and a
* "class" attribute which subclasses
* {@link CommonActionProvider}.
* @param anEnablementExpression
* A configuration element with the name 'enablement' or
* 'triggerPoints' and containing an Eclipse Core Expression
* @param defaultPriority
* @param anOverrideId
* A unique identifier for this descriptor. Ids can be used as a
* filtering device for activities or viewer***Bindings.
* @param nestedUnderNavigatorContent
* A value of <b>true</b> indicates that this
* CommonActionProvider was declared as a nested
* &lt;actionProvider /&gt; element under a &lt;navigatorContent
* /&gt; element.
*/
public CommonActionProviderDescriptor(IConfigurationElement aConfigElement,
IConfigurationElement anEnablementExpression, Priority defaultPriority, String anOverrideId,
boolean nestedUnderNavigatorContent) {
super();
Assert.isTrue(TAG_ACTION_PROVIDER.equals(aConfigElement.getName()));
Assert.isTrue(TAG_POSSIBLE_CHILDREN.equals(anEnablementExpression
.getName())
|| TAG_ENABLEMENT.equals(anEnablementExpression.getName()));
configurationElement = aConfigElement;
enablementElement = anEnablementExpression;
visibilityId = anOverrideId;
isNested = nestedUnderNavigatorContent;
priority = defaultPriority;
init();
}
private void init() {
try {
definedId = configurationElement.getAttribute(ATT_ID);
// if there was no id attribute, use the default id.
if (definedId == null) {
definedId = DEFAULT_ID + "." + count++; //$NON-NLS-1$
}
// we try the id attribute if no override id was supplied.
if (visibilityId == null) {
visibilityId = definedId;
}
dependsOnId = configurationElement.getAttribute(ATT_DEPENDS_ON);
overridesId = configurationElement.getAttribute(ATT_OVERRIDES);
if(priority == null) {
String prio = configurationElement.getAttribute(ATT_PRIORITY);
if(prio != null)
priority = Priority.get(prio);
else
priority = Priority.NORMAL;
}
IConfigurationElement[] children = configurationElement
.getChildren(TAG_ENABLEMENT);
// if no child enablement is specified, and we have an override, use
// it
if (children.length == 0 && enablementElement != null) {
enablement = new CustomAndExpression(enablementElement);
// otherwise the child enablement takes priority
} else if (children.length == 1) {
enablement = ElementHandler.getDefault().create(
ExpressionConverter.getDefault(), children[0]);
} else {
System.err.println("Incorrect number of expressions: " + //$NON-NLS-1$
TAG_ENABLEMENT
+ " in navigator extension: " + //$NON-NLS-1$
configurationElement.getDeclaringExtension()
.getUniqueIdentifier() + " in plugin " + //$NON-NLS-1$
configurationElement.getDeclaringExtension().getNamespaceIdentifier());
}
} catch (CoreException e) {
NavigatorPlugin.log(IStatus.ERROR, 0, e.getMessage(), e);
}
}
/**
*
* @return The instantiated CommonActionProvider for this descriptor as
* declared in the ATT_CLASS attribute or
* {@link SkeletonActionProvider} if a problem occurs while loading
* the instance.
*/
public CommonActionProvider createActionProvider() {
if (hasLoadingFailed) {
return SkeletonActionProvider.INSTANCE;
}
CommonActionProvider provider = null;
try {
provider = (CommonActionProvider) configurationElement
.createExecutableExtension(ATT_CLASS);
} catch (CoreException exception) {
NavigatorPlugin.log(exception.getStatus());
hasLoadingFailed = true;
provider = SkeletonActionProvider.INSTANCE;
} catch (Exception e) {
NavigatorPlugin.log(new Status(IStatus.ERROR,
NavigatorPlugin.PLUGIN_ID, 0, e.getMessage(), e));
hasLoadingFailed = true;
provider = SkeletonActionProvider.INSTANCE;
}
return provider;
}
/**
* Determine if this content extension is enabled for the given selection.
* The content extension is enabled for the selection if and only if it is
* enabled for each element in the selection.
*
* @param aStructuredSelection
* The selection from the viewer
* @return True if and only if the extension is enabled for each element in
* the selection.
*/
public boolean isEnabledFor(IStructuredSelection aStructuredSelection) {
if (enablement == null) {
return false;
}
if(aStructuredSelection.isEmpty()) {
IEvaluationContext context = null;
context = new EvaluationContext(null, Collections.EMPTY_LIST);
context.setAllowPluginActivation(true);
try {
if (enablement.evaluate(context) != EvaluationResult.TRUE) {
return false;
}
} catch (CoreException e) {
NavigatorPlugin.log(IStatus.ERROR, 0, e.getMessage(), e);
return false;
}
} else {
IEvaluationContext context = null;
Iterator elements = aStructuredSelection.iterator();
while (elements.hasNext()) {
context = new EvaluationContext(null, elements.next());
context.setAllowPluginActivation(true);
try {
if (enablement.evaluate(context) != EvaluationResult.TRUE) {
return false;
}
} catch (CoreException e) {
NavigatorPlugin.log(IStatus.ERROR, 0, e.getMessage(), e);
return false;
}
}
}
return true;
}
/**
* Determine if this content extension is enabled for the given element.
*
* @param anElement
* The element that should be used for the evaluation.
* @return True if and only if the extension is enabled for the element.
*/
public boolean isEnabledFor(Object anElement) {
if (enablement == null || anElement == null) {
return false;
}
try {
EvaluationContext context = new EvaluationContext(null, anElement);
context.setAllowPluginActivation(true);
return (enablement.evaluate(context) == EvaluationResult.TRUE);
} catch (CoreException e) {
NavigatorPlugin.log(IStatus.ERROR, 0, e.getMessage(), e);
}
return false;
}
/**
*
* @return An identifier for this ICommonActionProvider. Defaults to
* "org.eclipse.ui.navigator.actionProvider". May not be unique.
* Used to filter the actionProvider using the visibility state
* information.
*/
public String getId() {
return visibilityId;
}
/**
*
* @return An identifier for this ICommonActionProvider. Defaults to
* 'org.eclipse.ui.navigator.actionProvider'. May not be unique.
* Used to determine override or depends on cases.
*/
public String getDefinedId() {
return definedId;
}
/**
*
* @return True if this is a nested &lt;actionProvider /&gt; element.
*/
public boolean isNested() {
return isNested;
}
/**
*
* @return The value specified by the <i>dependsOn</i> attribute of the
* &lt;actionProvider /&gt; element.
*/
public String getDependsOnId() {
return dependsOnId;
}
/**
*
* @return The value specified by the <i>overridesId</i> attribute of the
* &lt;actionProvider /&gt; element.
*/
public String getOverridesId() {
return overridesId;
}
/**
* Only nested Action Providers have priority (as of 3.2.1).
*
* @return The priority associated with this Action Provider Descriptor.
*/
public Priority getPriority() {
return priority;
}
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((definedId == null) ? 0 : definedId.hashCode());
result = PRIME * result + ((visibilityId == null) ? 0 : visibilityId.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
final CommonActionProviderDescriptor other = (CommonActionProviderDescriptor) obj;
if (definedId == null) {
if (other.definedId != null)
return false;
} else if (!definedId.equals(other.definedId))
return false;
if (visibilityId == null) {
if (other.visibilityId != null)
return false;
} else if (!visibilityId.equals(other.visibilityId))
return false;
return true;
}
protected void addDependentDescriptor(
CommonActionProviderDescriptor dependentDescriptor) {
Assert.isTrue(this != dependentDescriptor);
if (dependentDescriptors == null) {
dependentDescriptors = new LinkedHashSet();
}
dependentDescriptors.add(dependentDescriptor);
}
protected void addOverridingDescriptor(
CommonActionProviderDescriptor overridingDescriptor) {
Assert.isTrue(this != overridingDescriptor);
if (overridingDescriptors == null) {
overridingDescriptors = new TreeSet(CommonActionProviderDescriptorCompator.INSTANCE);
}
overridingDescriptors.add(overridingDescriptor);
}
protected boolean hasDependentDescriptors() {
return dependentDescriptors != null && !dependentDescriptors.isEmpty();
}
protected boolean hasOverridingDescriptors() {
return overridingDescriptors != null
&& !overridingDescriptors.isEmpty();
}
protected Iterator dependentDescriptors() {
return dependentDescriptors.iterator();
}
protected Iterator overridingDescriptors() {
return overridingDescriptors.iterator();
}
public String toString() {
if (toString == null) {
toString = "CommonActionProviderDescriptor[definedId=" + getDefinedId() + ", visibilityId=" + getId() + ", dependsOn=" + getDependsOnId() + ", overrides=" + getOverridesId() + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
return toString;
}
/**
* Sorts CommonActionProviderDescriptors by priority, and then by defined id.
* @since 3.2
*
*/
public static class CommonActionProviderDescriptorCompator implements Comparator {
/**
* The singleton instance.
*/
public static final CommonActionProviderDescriptorCompator INSTANCE = new CommonActionProviderDescriptorCompator();
private static final int LESS_THAN = -1;
private static final int EQUALS = 0;
/* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object o1, Object o2) {
CommonActionProviderDescriptor lvalue= null, rvalue= null;
if(o1 instanceof CommonActionProviderDescriptor)
lvalue = (CommonActionProviderDescriptor) o1;
if(o2 instanceof CommonActionProviderDescriptor)
rvalue = (CommonActionProviderDescriptor) o2;
if(lvalue == null || rvalue == null)
return LESS_THAN;
if(lvalue.equals(rvalue))
return EQUALS;
int comparison = lvalue.getPriority().getValue() - rvalue.getPriority().getValue();
if(comparison == 0)
return lvalue.getDefinedId().compareTo(rvalue.getDefinedId());
return comparison;
}
}
}