Code tweaks and new EqualsExpression
diff --git a/bundles/org.eclipse.core.expressions/buildnotes_core-expressions.html b/bundles/org.eclipse.core.expressions/buildnotes_core-expressions.html
index 2c1be16..38461b1 100644
--- a/bundles/org.eclipse.core.expressions/buildnotes_core-expressions.html
+++ b/bundles/org.eclipse.core.expressions/buildnotes_core-expressions.html
@@ -12,9 +12,32 @@
 <h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Core Expressions</h1>
-March 16, 2004
-<h3>Problem Reports Fixed</h3>
-<h3>Implemenation Changes</h3>
+<h3>March 23, 2004</h3>
+<h4>Problem Reports Fixed</h4>
+<h4>Implemenation Changes</h4>
+<ul>
+  <li>removed the constructor public EvaluationContext(IEvaluationContext parent, Object defaultVariable, 
+  Object selection). Instead of calling this constructor, the following code has to be written:
+  <pre>
+     EvaluationContext evalContext= new EvaluationContext(null, cunit);
+     evalContext.addVariable("selection", cunit); //$NON-NLS-1$
+  </pre>
+  </li>
+  <li> removed the two string constants:
+  <pre>
+     public static final String SYSTEM= "System";  //$NON-NLS-1$
+     public static final String SELECTION= "selection";  //$NON-NLS-1$
+  </pre>
+  </li>
+  <li>added support for custom variable resolver (see new class IVariableResolver). So there is no need
+      to subclass EvaluationContext anymore to add your own resolving strategy.
+  </li>
+  <li>added support for an equals expression. </li>
+</ul>
+
+<h3>March 16, 2004</h3>
+<h4>Problem Reports Fixed</h4>
+<h4>Implemenation Changes</h4>
 The adapt expression now uses the new IAdapterManager API hasAdapter(Object, String) and 
 getAdapter(Object, String). This ensures that the right class loader is used to convert
 the string representing a type into a corresponding Class. However, this change now requires
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/EvaluationContext.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/EvaluationContext.java
index fd7b5d6..4c78456 100644
--- a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/EvaluationContext.java
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/EvaluationContext.java
@@ -32,6 +32,7 @@
 	private IEvaluationContext fParent;
 	private Object fDefaultVariable;
 	private Map/*<String, Object>*/ fVariables;
+	private IVariableResolver[] fVariableResolvers;
 	
 	/**
 	 * Create a new evaluation context with the given parent and default
@@ -47,20 +48,22 @@
 	}
 	
 	/**
-	 * Create a new evaluation context with the given parent, default
-	 * variable and the variable stored under the name selection.
+	 * Create a new evaluation context with the given parent and default
+	 * variable.
 	 * 
 	 * @param parent the parent context. Can be <code>null</code>.
 	 * @param defaultVariable the default variable
-	 * @param selection the variable stored under the name selection. Can
-	 *  be <code>null</code>
+	 * @param resolvers an array of <code>IVariableResolvers</code> to
+	 *  resolve additional variables.
+	 * 
+	 * @see #resolveVariable(String, Object[])
 	 */
-	public EvaluationContext(IEvaluationContext parent, Object defaultVariable, Object selection) {
+	public EvaluationContext(IEvaluationContext parent, Object defaultVariable, IVariableResolver[] resolvers) {
 		Assert.isNotNull(defaultVariable);
+		Assert.isNotNull(resolvers);
 		fParent= parent;
 		fDefaultVariable= defaultVariable;
-		if (selection != null)
-			addVariable(SELECTION, selection);
+		fVariableResolvers= resolvers;
 	}
 	
 	/**
@@ -125,8 +128,6 @@
 	
 	/**
 	 * {@inheritDoc}
-	 * 
-	 * Subclasses may extend this method to resolve specific variables.
 	 */
 	public Object resolveVariable(String name, Object[] args) throws CoreException {
 		if (PLUGIN_DESCRIPTOR.equals(name)) {
@@ -142,6 +143,14 @@
 					ExpressionMessages.getString("VariablePool.resolveVariable.arguments.not_a_string"))); //$NON-NLS-1$
 			return Platform.getPluginRegistry().getPluginDescriptor((String)(args[0]));
 		}
+		if (fVariableResolvers != null && fVariableResolvers.length > 0) {
+			for (int i= 0; i < fVariableResolvers.length; i++) {
+				IVariableResolver resolver= fVariableResolvers[i];
+				Object variable= resolver.resolve(name, args);
+				if (variable != null)
+					return variable;
+			}
+		}
 		if (fParent != null)
 			return fParent.resolveVariable(name, args);
 		return null;
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionTagNames.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionTagNames.java
index 1568067..7a33fb9 100644
--- a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionTagNames.java
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionTagNames.java
@@ -52,5 +52,8 @@
 	public static final String RESOLVE= "resolve"; //$NON-NLS-1$
 
 	/** The tag name of the systemTest expression (value: <code>systemTest</code>) */
-	public static final String SYSTEM_TEST= "systemTest"; //$NON-NLS-1$	
+	public static final String SYSTEM_TEST= "systemTest"; //$NON-NLS-1$
+	
+	/** The tag name of the equals expression (value: <code>equals</code>) */
+	public static final String EQUALS= "equals"; //$NON-NLS-1$
 }
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IEvaluationContext.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IEvaluationContext.java
index 617077f..9ca49de 100644
--- a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IEvaluationContext.java
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IEvaluationContext.java
@@ -30,12 +30,6 @@
 	/** Variable name to denote a plug-in descriptor */
 	public static final String PLUGIN_DESCRIPTOR= "pluginDescriptor";  //$NON-NLS-1$
 	
-	/** Variable name to denote the current selection of elements */
-	public static final String SELECTION= "selection";  //$NON-NLS-1$
-	
-	/** Variable name to denote the java.lang.System class */
-	public static final String SYSTEM= "System";  //$NON-NLS-1$
-	
 	/**
 	 * Returns the parent context or <code>null</code> if 
 	 * this is the root of the evaluation context hierarchy.
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IVariableResolver.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IVariableResolver.java
new file mode 100644
index 0000000..7eb727c
--- /dev/null
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/IVariableResolver.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.expressions;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * A variable resolver can be used to add additional variable resolving
+ * stategies to a {@link EvaluationContext}.
+ * 
+ * @since 3.0
+ * 
+ * @see org.eclipse.core.expressions.EvaluationContext#resolveVariable(String, Object[])
+ */
+public interface IVariableResolver {
+
+	/**
+	 * Resolves a variable for the given name and arguments. The
+	 * handler is allowed to return <code>null</code> to indicate
+	 * that it is not able to resolve the requested variable.
+	 * 
+	 * @param name the variable to resolve
+	 * @param args an object array of arguments used to resolve the
+	 *  variable
+	 * @return the variable's value or <code>null</code> if no variable
+	 *  could be resolved
+	 * @exception CoreException if an errors occurs while resolving
+	 *  the variable
+	 */
+	public Object resolve(String name, Object[] args) throws CoreException;
+}
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/EqualsExpression.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/EqualsExpression.java
new file mode 100644
index 0000000..32e5a5e
--- /dev/null
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/EqualsExpression.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.internal.expressions;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.IEvaluationContext;
+
+public class EqualsExpression extends Expression {
+
+	private Object fExpectedValue; 
+	
+	public EqualsExpression(Object expectedValue) {
+		Assert.isNotNull(expectedValue);
+		fExpectedValue= expectedValue;
+	}
+	
+	public EqualsExpression(IConfigurationElement element) throws CoreException {
+		String value= element.getAttribute(ATT_VALUE);
+		Expressions.checkAttribute(ATT_VALUE, value);
+		fExpectedValue= Expressions.convertArgument(value);
+	}
+	
+	public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
+		Object element= context.getDefaultVariable();
+		return EvaluationResult.valueOf(element.equals(fExpectedValue));
+	}
+}
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/StandardElementHandler.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/StandardElementHandler.java
index bb733df..2c34fc5 100644
--- a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/StandardElementHandler.java
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/StandardElementHandler.java
@@ -63,6 +63,8 @@
 			EnablementExpression result= new EnablementExpression(element);
 			processChildren(converter, element, result);
 			return result;
+		} else if (ExpressionTagNames.EQUALS.equals(name)) {
+			return new EqualsExpression(element);
 		}
 		return null;
 	}
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/TestExpression.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/TestExpression.java
index a501319..118f7b2 100644
--- a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/TestExpression.java
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/internal/expressions/TestExpression.java
@@ -40,7 +40,7 @@
 		fNamespace= property.substring(0, pos);
 		fProperty= property.substring(pos + 1);
 		fArgs= Expressions.getArguments(element, ATT_ARGS);
-		fExpectedValue= element.getAttribute(ATT_VALUE);
+		fExpectedValue= Expressions.convertArgument(element.getAttribute(ATT_VALUE));
 	}
 	
 	public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
diff --git a/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionTests.java b/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionTests.java
index 75a0ae2..bef619b 100644
--- a/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionTests.java
+++ b/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionTests.java
@@ -14,12 +14,15 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPluginDescriptor;
 
 import org.eclipse.core.expressions.EvaluationContext;
 import org.eclipse.core.expressions.EvaluationResult;
 import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.core.expressions.IVariableResolver;
 import org.eclipse.core.internal.expressions.AdaptExpression;
+import org.eclipse.core.internal.expressions.EqualsExpression;
 import org.eclipse.core.internal.expressions.Expressions;
 import org.eclipse.core.internal.expressions.InstanceofExpression;
 import org.eclipse.core.internal.expressions.SystemTestExpression;
@@ -36,6 +39,7 @@
 		assertEquals("", Expressions.convertArgument(""));
 		assertEquals("", Expressions.convertArgument("''"));
 		assertEquals("eclipse", Expressions.convertArgument("eclipse"));
+		assertEquals("eclipse", Expressions.convertArgument("'eclipse'"));
 		assertEquals("true", Expressions.convertArgument("'true'"));
 		assertEquals("1.7", Expressions.convertArgument("'1.7'"));
 		assertEquals("007", Expressions.convertArgument("'007'"));
@@ -114,4 +118,32 @@
 		EvaluationResult result= expression.evaluate(new EvaluationContext(null, new Adaptee()));
 		assertTrue(result == EvaluationResult.FALSE);
 	}
+	
+	public void testVariableResolver() throws Exception {
+		final Object result= new Object();
+		IVariableResolver resolver= new IVariableResolver() {
+			public Object resolve(String name, Object[] args) throws CoreException {
+				assertEquals("variable", name);
+				assertEquals("arg1", args[0]);
+				assertEquals(Boolean.TRUE, args[1]);
+				return result;
+			}
+		};
+		EvaluationContext context= new EvaluationContext(null, new Object(), new IVariableResolver[] { resolver });
+		assertTrue(result == context.resolveVariable("variable", new Object[] {"arg1", Boolean.TRUE}));
+	}
+	
+	public void testEqualsExpression() throws Exception {
+		EqualsExpression exp= new EqualsExpression("name");
+		EvaluationContext context= new EvaluationContext(null, "name");
+		assertTrue(EvaluationResult.TRUE == exp.evaluate(context));
+		
+		exp= new EqualsExpression(Boolean.TRUE);
+		context= new EvaluationContext(null, Boolean.TRUE);
+		assertTrue(EvaluationResult.TRUE == exp.evaluate(context));		
+		
+		exp= new EqualsExpression("name");
+		context= new EvaluationContext(null, Boolean.TRUE);
+		assertTrue(EvaluationResult.FALSE == exp.evaluate(context));		
+	}
 }