Bug 116921 - [expressions] Provide AndExpression and others as API

Moved AndExpression, OrExpressionm WithExpression and
CompositeExpression to API package.

Change-Id: I9f899b69e75920b433cb4b8fc1713b7a93a4891b
Signed-off-by: Lars Vogel <Lars.Vogel@vogella.com>
diff --git a/bundles/org.eclipse.core.expressions/META-INF/MANIFEST.MF b/bundles/org.eclipse.core.expressions/META-INF/MANIFEST.MF
index f2484a6..cf58bf4 100644
--- a/bundles/org.eclipse.core.expressions/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.core.expressions/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.core.expressions; singleton:=true
-Bundle-Version: 3.6.900.qualifier
+Bundle-Version: 3.7.0.qualifier
 Bundle-ClassPath: .
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.core.expressions/pom.xml b/bundles/org.eclipse.core.expressions/pom.xml
index 0f1df47..abcb119 100644
--- a/bundles/org.eclipse.core.expressions/pom.xml
+++ b/bundles/org.eclipse.core.expressions/pom.xml
@@ -19,6 +19,6 @@
   </parent>
   <groupId>org.eclipse.core</groupId>
   <artifactId>org.eclipse.core.expressions</artifactId>
-  <version>3.6.900-SNAPSHOT</version>
+  <version>3.7.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/AndExpression.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/AndExpression.java
new file mode 100644
index 0000000..a3c57cc
--- /dev/null
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/AndExpression.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.expressions;
+
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * @since 3.7
+ */
+
+public class AndExpression extends CompositeExpression {
+
+	@Override
+	public boolean equals(final Object object) {
+		if (!(object instanceof AndExpression))
+			return false;
+
+		final AndExpression that= (AndExpression)object;
+		return equals(this.fExpressions, that.fExpressions);
+	}
+
+	@Override
+	public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
+		return evaluateAnd(context);
+	}
+}
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/CompositeExpression.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/CompositeExpression.java
new file mode 100644
index 0000000..b8c26e9
--- /dev/null
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/CompositeExpression.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.expressions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * @since 3.7
+ */
+
+public abstract class CompositeExpression extends Expression {
+
+	private static final Expression[] EMPTY_ARRAY = new Expression[0];
+
+	/**
+	 * The seed for the hash code for all composite expressions.
+	 */
+	private static final int HASH_INITIAL= CompositeExpression.class.getName().hashCode();
+
+	protected List<Expression> fExpressions;
+
+	public void add(Expression expression) {
+		if (fExpressions == null)
+			fExpressions= new ArrayList<>(2);
+		fExpressions.add(expression);
+	}
+
+	public Expression[] getChildren() {
+		if (fExpressions == null)
+			return EMPTY_ARRAY;
+		return fExpressions.toArray(new Expression[fExpressions.size()]);
+	}
+
+	protected EvaluationResult evaluateAnd(IEvaluationContext scope) throws CoreException {
+		if (fExpressions == null)
+			return EvaluationResult.TRUE;
+		EvaluationResult result= EvaluationResult.TRUE;
+		for (Expression expression : fExpressions) {
+			result= result.and(expression.evaluate(scope));
+			// keep iterating even if we have a not loaded found. It can be
+			// that we find a false which will result in a better result.
+			if (result == EvaluationResult.FALSE)
+				return result;
+		}
+		return result;
+	}
+
+	protected EvaluationResult evaluateOr(IEvaluationContext scope) throws CoreException {
+		if (fExpressions == null)
+			return EvaluationResult.TRUE;
+		EvaluationResult result= EvaluationResult.FALSE;
+		for (Expression expression : fExpressions) {
+			result= result.or(expression.evaluate(scope));
+			if (result == EvaluationResult.TRUE)
+				return result;
+		}
+		return result;
+	}
+
+	@Override
+	public void collectExpressionInfo(ExpressionInfo info) {
+		if (fExpressions == null)
+			return;
+		for (Expression expression : fExpressions) {
+			expression.collectExpressionInfo(info);
+		}
+	}
+
+	@Override
+	protected int computeHashCode() {
+		return HASH_INITIAL * HASH_FACTOR + hashCode(fExpressions);
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder(getClass().getSimpleName());
+		Expression[] children = getChildren();
+		if (children.length > 0) {
+			builder.append(" [children="); //$NON-NLS-1$
+			builder.append(Arrays.toString(children));
+			builder.append("]"); //$NON-NLS-1$
+		}
+		return builder.toString();
+	}
+
+}
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/OrExpression.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/OrExpression.java
new file mode 100644
index 0000000..6d0ecc2
--- /dev/null
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/OrExpression.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.expressions;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * @since 3.7
+ */
+
+public class OrExpression extends CompositeExpression {
+
+	@Override
+	public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
+		return evaluateOr(context);
+	}
+
+	@Override
+	public boolean equals(final Object object) {
+		if (!(object instanceof OrExpression))
+			return false;
+
+		final OrExpression that= (OrExpression)object;
+		return equals(this.fExpressions, that.fExpressions);
+	}
+}
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/WithExpression.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/WithExpression.java
new file mode 100644
index 0000000..2fb4e28
--- /dev/null
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/WithExpression.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.expressions;
+
+import java.util.Arrays;
+
+import org.w3c.dom.Element;
+
+import org.eclipse.core.internal.expressions.ExpressionMessages;
+import org.eclipse.core.internal.expressions.ExpressionStatus;
+import org.eclipse.core.internal.expressions.Expressions;
+import org.eclipse.core.internal.expressions.Messages;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * @since 3.7
+ */
+
+public class WithExpression extends CompositeExpression {
+
+	private String fVariable;
+	private static final String ATT_VARIABLE= "variable";  //$NON-NLS-1$
+
+	/**
+	 * The seed for the hash code for all with expressions.
+	 */
+	private static final int HASH_INITIAL= WithExpression.class.getName().hashCode();
+
+	public WithExpression(IConfigurationElement configElement) throws CoreException {
+		fVariable= configElement.getAttribute(ATT_VARIABLE);
+		Expressions.checkAttribute(ATT_VARIABLE, fVariable);
+	}
+
+	public WithExpression(Element element) throws CoreException {
+		fVariable= element.getAttribute(ATT_VARIABLE);
+		Expressions.checkAttribute(ATT_VARIABLE, fVariable.isEmpty() ? null : fVariable);
+	}
+
+	public WithExpression(String variable) {
+		Assert.isNotNull(variable);
+		fVariable= variable;
+	}
+
+	@Override
+	public boolean equals(final Object object) {
+		if (!(object instanceof WithExpression))
+			return false;
+
+		final WithExpression that= (WithExpression)object;
+		return this.fVariable.equals(that.fVariable) && equals(this.fExpressions, that.fExpressions);
+	}
+
+	@Override
+	protected int computeHashCode() {
+		return HASH_INITIAL * HASH_FACTOR + hashCode(fExpressions)
+			* HASH_FACTOR + fVariable.hashCode();
+	}
+
+	@Override
+	public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
+		Object variable= context.getVariable(fVariable);
+		if (variable == null) {
+			throw new CoreException(new ExpressionStatus(
+				ExpressionStatus.VARIABLE_NOT_DEFINED,
+				Messages.format(ExpressionMessages.WithExpression_variable_not_defined, fVariable)));
+		}
+		if (variable == IEvaluationContext.UNDEFINED_VARIABLE) {
+			return EvaluationResult.FALSE;
+		}
+		return evaluateAnd(new EvaluationContext(context, variable));
+	}
+
+	@Override
+	public void collectExpressionInfo(ExpressionInfo info) {
+		ExpressionInfo other= new ExpressionInfo();
+		super.collectExpressionInfo(other);
+		if (other.hasDefaultVariableAccess()) {
+			info.addVariableNameAccess(fVariable);
+		}
+		info.mergeExceptDefaultVariable(other);
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder(getClass().getSimpleName());
+		builder.append(" [variable=").append(fVariable); //$NON-NLS-1$
+		Expression[] children = getChildren();
+		if (children.length > 0) {
+			builder.append(", children="); //$NON-NLS-1$
+			builder.append(Arrays.toString(children));
+		}
+		builder.append("]"); //$NON-NLS-1$
+		return builder.toString();
+	}
+}
\ No newline at end of file