1 /*******************************************************************************
2  * Copyright (c) 2009, 2010 Cloudsmith Inc. and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Cloudsmith Inc. - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.equinox.p2.metadata.expression;
15 
16 import java.util.List;
17 import java.util.Map;
18 import org.eclipse.equinox.p2.metadata.IVersionedId;
19 import org.eclipse.equinox.p2.query.IQuery;
20 
21 /**
22  * This interface provides all the factory methods needed to create the
23  * nodes of the expression tree.
24  * @since 2.0
25  * @noimplement This interface is not intended to be implemented directly by clients.
26  * @noextend This interface is not intended to be extended directly by clients.
27  */
28 public interface IExpressionFactory {
29 	String FUNC_BOOLEAN = "boolean"; //$NON-NLS-1$
30 	String FUNC_VERSION = "version"; //$NON-NLS-1$
31 	String FUNC_CLASS = "class"; //$NON-NLS-1$
32 	String FUNC_RANGE = "range"; //$NON-NLS-1$
33 	String FUNC_FILTER = "filter"; //$NON-NLS-1$
34 
35 	IExpression[] NO_ARGS = new IExpression[0];
36 
37 	/**
38 	 * Create a collection filter that yields true if the <code>lambda</code> yields true for
39 	 * all of the elements of the <code>collection</code>
40 	 * @param collection The collection providing the elements to test
41 	 * @param lambda The lambda that performs the test
42 	 * @return A boolean expression
43 	 */
all(IExpression collection, IExpression lambda)44 	IExpression all(IExpression collection, IExpression lambda);
45 
46 	/**
47 	 * Create a logical <i>and</i> of its <code>operands</code>.
48 	 * @param operands The boolean operands
49 	 * @return A boolean expression
50 	 */
and(IExpression... operands)51 	IExpression and(IExpression... operands);
52 
53 	/**
54 	 * Creates an expression that represents a variable assignment
55 	 * @param variable The variable
56 	 * @param expression The expression that yields the value to assign to the variable
57 	 * @return An assignment expression
58 	 */
assignment(IExpression variable, IExpression expression)59 	IExpression assignment(IExpression variable, IExpression expression);
60 
61 	/**
62 	 * Create an expression that collects the result of evaluating each element in a new collection.
63 	 * @param collection The collection providing the elements to evaluate
64 	 * @param lambda The lambda that creates each new element
65 	 * @return A collection expression
66 	 */
collect(IExpression collection, IExpression lambda)67 	IExpression collect(IExpression collection, IExpression lambda);
68 
69 	/**
70 	 * Create an expression that first evaluates a <code>test</code> and then, depending on the outcome,
71 	 * evaluates either <code>ifTrue</code> or <code>ifFalse</code>. The expression yields the result
72 	 * of the <code>ifTrue</code> or <code>ifFalse</code> evaluation.
73 	 * @param test The test
74 	 * @param ifTrue The code to evaluate when the test evaluates to <code>true</code>
75 	 * @param ifFalse The code to evaluate when the test evaluates to <code>false</code>
76 	 * @return The conditional expression
77 	 */
condition(IExpression test, IExpression ifTrue, IExpression ifFalse)78 	IExpression condition(IExpression test, IExpression ifTrue, IExpression ifFalse);
79 
80 	/**
81 	 * Create an expression that yields the first element of the
82 	 * <code>collection</code> for which the <code>lambda</code> yields <code>true</code>.
83 	 * @param collection The collection providing the elements to test
84 	 * @param lambda The lambda that performs the test
85 	 * @return An element expression
86 	 */
first(IExpression collection, IExpression lambda)87 	IExpression first(IExpression collection, IExpression lambda);
88 
89 	/**
90 	 * Intended to be applied on collections of collections. Yields a single collection with
91 	 * all elements from the source collections, in the order they are evaluated.
92 	 * @param collection The collection providing the collections that provides all elements
93 	 * @return A collection expression
94 	 */
flatten(IExpression collection)95 	IExpression flatten(IExpression collection);
96 
97 	/**
98 	 * Creates a lambda expression that takes more then one variable (currying). Suitable for use
99 	 * in most collection expressions.
100 	 * @param variable The element variable that the lambda uses
101 	 * @param body The body of the lambda
102 	 * @param initialAssignments Assignments to evaluate once before calling the body for each element.
103 	 * @return A lambda expression with currying
104 	 */
lambda(IExpression variable, IExpression[] initialAssignments, IExpression body)105 	IExpression lambda(IExpression variable, IExpression[] initialAssignments, IExpression body);
106 
107 	/**
108 	 * Creates a member call expression.
109 	 * @param target The target for the member call
110 	 * @param name The name of the member
111 	 * @param args The arguments to use for the call
112 	 * @return A member expression
113 	 */
memberCall(IExpression target, String name, IExpression... args)114 	IExpression memberCall(IExpression target, String name, IExpression... args);
115 
116 	/**
117 	 * <p>Recursively traverse and collect elements based on a condition</p>
118 	 * <p>A common scenario in p2 is that you want to start with a set of roots and then find
119 	 * all items that fulfill the root requirements. Those items in turn introduce new
120 	 * requirements so you want to find them too. The process continues until no more
121 	 * requirements can be satisfied. This type of query can be performed using the traverse
122 	 * function.</p>
123 	 * <p>The function will evaluate an expression, once for each element, collect
124 	 * elements for which the evaluation returned true, then then re-evaluate using the
125 	 * collected result as source of elements. No element is evaluated twice. This continues
126 	 * until no more elements are found.</p>
127 	 * @param collection The collection providing the elements to test
128 	 * @param lambda The lambda that collects the children for the next iteration
129 	 * @return A collection expression
130 	 */
traverse(IExpression collection, IExpression lambda)131 	IExpression traverse(IExpression collection, IExpression lambda);
132 
133 	/**
134 	 * Create an expression that yields a new collection where each element is unique. An
135 	 * optional <code>cache</code> can be provided if the uniqueness should span a larger
136 	 * scope then just the source collection.
137 	 * @param collection The source collection
138 	 * @param cache Optional cache to use when uniqueness should span over several invocations
139 	 * @return A collection expression
140 	 */
unique(IExpression collection, IExpression cache)141 	IExpression unique(IExpression collection, IExpression cache);
142 
143 	/**
144 	 * Create an array of elements.
145 	 * @param elements The elements of the array
146 	 * @return An array expression
147 	 */
array(IExpression... elements)148 	IExpression array(IExpression... elements);
149 
150 	/**
151 	 * Create an lookup of <code>key</code> in the <code>target</code>.
152 	 * The key expression should evaluate to a string or an integer.
153 	 * @param target The target for the lookup
154 	 * @param key The key to use for the lookup
155 	 * @return A lookup expression
156 	 */
at(IExpression target, IExpression key)157 	IExpression at(IExpression target, IExpression key);
158 
159 	/**
160 	 * Create an evaluation context with one single variable
161 	 * @param params Indexed parameters to use in the expression
162 	 * @return the context
163 	 */
createContext(Object... params)164 	IEvaluationContext createContext(Object... params);
165 
166 	/**
167 	 * Create an evaluation context with one single variable
168 	 * @param params Indexed parameters to use in the expression
169 	 * @param variables The variables that will be maintained by the context
170 	 * @return the context
171 	 */
createContext(IExpression[] variables, Object... params)172 	IEvaluationContext createContext(IExpression[] variables, Object... params);
173 
174 	/**
175 	 * Creates an expression that evaluates to the constant <code>value</code>.
176 	 * @param value The constant
177 	 * @return A constant expression
178 	 */
constant(Object value)179 	IExpression constant(Object value);
180 
181 	/**
182 	 * Creates a top level expression that represents a full query.
183 	 * @param expr The query
184 	 * @param parameters The parameters of the query
185 	 * @return A top level query expression
186 	 */
contextExpression(IExpression expr, Object... parameters)187 	<T> IContextExpression<T> contextExpression(IExpression expr, Object... parameters);
188 
189 	/**
190 	 * Create an expression that tests if <code>lhs</code> is equal to <code>rhs</code>.
191 	 * @param lhs The left hand side value.
192 	 * @param rhs The right hand side value.
193 	 * @return A boolean expression
194 	 */
equals(IExpression lhs, IExpression rhs)195 	IExpression equals(IExpression lhs, IExpression rhs);
196 
197 	/**
198 	 * Create a collection filter that yields true if the <code>lambda</code> yields true for
199 	 * at least one of the elements of the <code>collection</code>
200 	 * @param collection The collection providing the elements to test
201 	 * @param lambda The lambda that performs the test
202 	 * @return A boolean expression
203 	 */
exists(IExpression collection, IExpression lambda)204 	IExpression exists(IExpression collection, IExpression lambda);
205 
206 	/**
207 	 * Creates a top level expression suitable for predicate matching
208 	 * @param expression The boolean expression
209 	 * @return A top level predicate expression
210 	 */
filterExpression(IExpression expression)211 	IFilterExpression filterExpression(IExpression expression);
212 
213 	/**
214 	 * Given one of the values in the map returned by {@link #getFunctionMap()}, this method
215 	 * returns a function expression.
216 	 * @param function The value obtained from the map.
217 	 * @param args The arguments to evaluate and pass when evaluating the function.
218 	 * @return A function expression
219 	 */
function(Object function, IExpression... args)220 	IExpression function(Object function, IExpression... args);
221 
222 	/**
223 	 * Returns a map of functions supported by this factory. The map is keyed by
224 	 * function names and the value is an object suitable to pass to the {@link #function(Object, IExpression[])}
225 	 * method.
226 	 * @return A key/function map.
227 	 */
getFunctionMap()228 	Map<String, ? extends Object> getFunctionMap();
229 
230 	/**
231 	 * Create an expression that tests if <code>lhs</code> is greater than <code>rhs</code>.
232 	 * @param lhs The left hand side value.
233 	 * @param rhs The right hand side value.
234 	 * @return A boolean expression
235 	 */
greater(IExpression lhs, IExpression rhs)236 	IExpression greater(IExpression lhs, IExpression rhs);
237 
238 	/**
239 	 * Create an expression that tests if <code>lhs</code> is greater than or equal to <code>rhs</code>.
240 	 * @param lhs The left hand side value.
241 	 * @param rhs The right hand side value.
242 	 * @return A boolean expression
243 	 */
greaterEqual(IExpression lhs, IExpression rhs)244 	IExpression greaterEqual(IExpression lhs, IExpression rhs);
245 
246 	/**
247 	 * Creates an indexed parameter expression
248 	 * @param index The index to use
249 	 * @return a parameter expression
250 	 */
indexedParameter(int index)251 	IExpression indexedParameter(int index);
252 
253 	/**
254 	 * Create an <i>intersection</i> of <code>c1</code> and <code>c2</code>
255 	 * @param c1 first collection
256 	 * @param c2 second collection
257 	 * @return An intersect expression
258 	 */
intersect(IExpression c1, IExpression c2)259 	IExpression intersect(IExpression c1, IExpression c2);
260 
261 	/**
262 	 * Creates a lambda expression that takes exactly one variable. Suitable for use
263 	 * in most collection expressions.
264 	 * @param variable The element variable that the lambda uses
265 	 * @param body The body of the lambda
266 	 * @return A lambda expression
267 	 */
lambda(IExpression variable, IExpression body)268 	IExpression lambda(IExpression variable, IExpression body);
269 
270 	/**
271 	 * Create an expression that yields a new collection consisting of the latest version of
272 	 * the elements of the <code>collection</code>. Each element in <code>collection</code>
273 	 * must implement the {@link IVersionedId} interface.
274 	 * @param collection The collection providing the versioned elements
275 	 * @return A collection expression
276 	 */
latest(IExpression collection)277 	IExpression latest(IExpression collection);
278 
279 	/**
280 	 * Create an expression that tests if <code>lhs</code> is less than <code>rhs</code>.
281 	 * @param lhs The left hand side value.
282 	 * @param rhs The right hand side value.
283 	 * @return A boolean expression
284 	 */
less(IExpression lhs, IExpression rhs)285 	IExpression less(IExpression lhs, IExpression rhs);
286 
287 	/**
288 	 * Create an expression that tests if <code>lhs</code> is less than or equal to <code>rhs</code>.
289 	 * @param lhs The left hand side value.
290 	 * @param rhs The right hand side value.
291 	 * @return A boolean expression
292 	 */
lessEqual(IExpression lhs, IExpression rhs)293 	IExpression lessEqual(IExpression lhs, IExpression rhs);
294 
295 	/**
296 	 * Create an expression that yields a new collection consisting of the <i>count</i>
297 	 * first elements of the source collection.
298 	 * @param collection The source collection
299 	 * @param count The element count limit
300 	 * @return A collection expression
301 	 */
limit(IExpression collection, int count)302 	IExpression limit(IExpression collection, int count);
303 
304 	/**
305 	 * Create an expression that yields a new collection consisting of the <i>n</i> first
306 	 * elements of the source collection where <i>n</i> is determined by <code>limit</code>.
307 	 * @param collection The source collection
308 	 * @param limit The expression that evaluates to the element count limit
309 	 * @return A collection expression
310 	 */
limit(IExpression collection, IExpression limit)311 	IExpression limit(IExpression collection, IExpression limit);
312 
313 	/**
314 	 * Performs boolean normalization on the expression to create a canonical form.
315 	 * @param operands The operands to normalize
316 	 * @param expressionType The type (must be either {@link IExpression#TYPE_AND}
317 	 * or {@link IExpression#TYPE_OR}.
318 	 * @return The normalized expression
319 	 */
normalize(List<? extends IExpression> operands, int expressionType)320 	IExpression normalize(List<? extends IExpression> operands, int expressionType);
321 
322 	/**
323 	 * Create an expression that tests if <code>lhs</code> matches <code>rhs</code>.
324 	 * @param lhs The left hand side value.
325 	 * @param rhs The right hand side value.
326 	 * @return A boolean expression
327 	 */
matches(IExpression lhs, IExpression rhs)328 	IExpression matches(IExpression lhs, IExpression rhs);
329 
330 	/**
331 	 * Creates a parameterized top level expression suitable for predicate matching
332 	 * @param expression The boolean expression
333 	 * @param parameters The parameters to use in the call
334 	 * @return A top level predicate expression
335 	 */
matchExpression(IExpression expression, Object... parameters)336 	<T> IMatchExpression<T> matchExpression(IExpression expression, Object... parameters);
337 
338 	/**
339 	 * Creates a member accessor expression.
340 	 * @param target The target for the member access
341 	 * @param name The name of the member
342 	 * @return A member expression
343 	 */
member(IExpression target, String name)344 	IExpression member(IExpression target, String name);
345 
346 	/**
347 	 * Creates an expression that negates the result of evaluating its <code>operand</code>.
348 	 * @param operand The boolean expression to negate
349 	 * @return A boolean expression
350 	 */
not(IExpression operand)351 	IExpression not(IExpression operand);
352 
353 	/**
354 	 * Create a logical <i>or</i> of its <code>operands</code>.
355 	 * @param operands The boolean operands
356 	 * @return A boolean expression
357 	 */
or(IExpression... operands)358 	IExpression or(IExpression... operands);
359 
360 	/**
361 	 * Create a pipe of expressions.
362 	 * @param expressions The expressions that make out the pipe
363 	 * @return A pipe expression
364 	 */
pipe(IExpression... expressions)365 	IExpression pipe(IExpression... expressions);
366 
367 	/**
368 	 * Create an expression that yields a new collection consisting of all elements of the
369 	 * <code>collection</code> for which the <code>lambda</code> yields <code>true</code>.
370 	 * @param collection The collection providing the elements to test
371 	 * @param lambda The lambda that performs the test
372 	 * @return A collection expression
373 	 */
select(IExpression collection, IExpression lambda)374 	IExpression select(IExpression collection, IExpression lambda);
375 
376 	/**
377 	 * Returns the variable that represents <code>this</code> in an expression
378 	 * @return The <code>this</code> variable.
379 	 */
thisVariable()380 	IExpression thisVariable();
381 
382 	/**
383 	 * Wrap an {@link IQuery} as an expression.
384 	 * @param query The query to wrap.
385 	 * @return An expression that wraps the query
386 	 */
toExpression(IQuery<?> query)387 	IExpression toExpression(IQuery<?> query);
388 
389 	/**
390 	 * Create a <i>union</i> of <code>c1</code> and <code>c2</code>
391 	 * @param c1 first collection
392 	 * @param c2 second collection
393 	 * @return A union expression
394 	 */
union(IExpression c1, IExpression c2)395 	IExpression union(IExpression c1, IExpression c2);
396 
397 	/**
398 	 * Creates an expression that represents a variable
399 	 * @param name The name of the variable
400 	 * @return A variable expression
401 	 */
variable(String name)402 	IExpression variable(String name);
403 }
404