From 757cc0f2be1c0972f9b74a91ed873fe8a892f27f Mon Sep 17 00:00:00 2001
From: Tobrun
Date: Tue, 19 Dec 2017 08:55:48 +0100
Subject: [android] - add binding integration for expressions (#10654)
---
.../MapboxGLAndroidSDK/gradle-checkstyle.gradle | 1 +
.../mapboxsdk/style/expressions/Expression.java | 1761 ++++++++++++++++++++
.../com/mapbox/mapboxsdk/style/layers/Layer.java | 13 +-
.../mapbox/mapboxsdk/style/layers/Property.java | 24 +-
.../mapboxsdk/style/layers/PropertyFactory.java | 1055 +++++++++++-
.../style/layers/property_factory.java.ejs | 23 +
.../style/expressions/ExpressionTest.java | 1010 +++++++++++
.../activity/style/DataDrivenStyleActivity.java | 279 +++-
.../activity/style/RuntimeStyleActivity.java | 44 +-
.../activity/style/SymbolGeneratorActivity.java | 96 +-
.../main/res/layout/activity_data_driven_style.xml | 12 +
.../src/main/res/menu/menu_generator_symbol.xml | 4 +
.../src/main/res/values/actions.xml | 1 +
13 files changed, 4147 insertions(+), 176 deletions(-)
create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
index e0bc076d3d..420ccb473a 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
+++ b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
@@ -16,6 +16,7 @@ task checkstyle(type: Checkstyle) {
exclude '**/style/layers/PropertyFactory.java'
exclude '**/style/layers/*Layer.java'
exclude '**/style/light/Light.java'
+ exclude '**/Expression.java' // allowing single character signature as e()
classpath = files()
ignoreFailures = false
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
new file mode 100644
index 0000000000..4d09fcaac6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
@@ -0,0 +1,1761 @@
+package com.mapbox.mapboxsdk.style.expressions;
+
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.Size;
+
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The value for any layout property, paint property, or filter may be specified as an expression.
+ * An expression defines a formula for computing the value of the property using the operators described below.
+ * The set of expression operators provided by Mapbox GL includes:
+ *
+ *
+ * Element
+ * Mathematical operators for performing arithmetic and other operations on numeric values
+ * Logical operators for manipulating boolean values and making conditional decisions
+ * String operators for manipulating strings
+ * Data operators, providing access to the properties of source features
+ * Camera operators, providing access to the parameters defining the current map view
+ *
+ *
+ *
+ * Expressions are represented as JSON arrays.
+ * The first element of an expression array is a string naming the expression operator,
+ * e.g. "*"or "case". Subsequent elements (if any) are the arguments to the expression.
+ * Each argument is either a literal value (a string, number, boolean, or null), or another expression array.
+ *
+ *
+ * Data expression: a data expression is any expression that access feature data -- that is,
+ * any expression that uses one of the data operators:get,has,id,geometry-type, or properties.
+ * Data expressions allow a feature's properties to determine its appearance.
+ * They can be used to differentiate features within the same layer and to create data visualizations.
+ *
+ *
+ * Camera expression: a camera expression is any expression that uses the zoom operator.
+ * Such expressions allow the the appearance of a layer to change with the map's zoom level.
+ * Camera expressions can be used to create the appearance of depth and to control data density.
+ *
+ *
+ * Composition: a single expression may use a mix of data operators, camera operators, and other operators.
+ * Such composite expressions allows a layer's appearance to be determined by
+ * a combination of the zoom level and individual feature properties.
+ *
+ *
+ * @param the type of the expression
+ */
+public class Expression {
+
+ private final String operator;
+ private final Expression[] arguments;
+
+ /**
+ * Creates an empty expression for expression literals
+ */
+ Expression() {
+ operator = null;
+ arguments = null;
+ }
+
+ /**
+ * Creates an expression from its operator and varargs expressions.
+ *
+ * @param operator the expression operator
+ * @param arguments expressions input
+ */
+ public Expression(@NonNull String operator, @Nullable Expression... arguments) {
+ this.operator = operator;
+ this.arguments = arguments;
+ }
+
+ /**
+ * Converts the expression to Object array representation.
+ *
+ * The output will later be converted to a JSON Object array.
+ *
+ *
+ * @return the converted object array expression
+ */
+ @NonNull
+ public Object[] toArray() {
+ List array = new ArrayList<>();
+ array.add(operator);
+ if (arguments != null) {
+ for (Expression argument : arguments) {
+ if (argument instanceof Expression.ExpressionLiteral) {
+ array.add(toValue((ExpressionLiteral) argument));
+ } else {
+ array.add(argument.toArray());
+ }
+ }
+ }
+ return array.toArray();
+ }
+
+ /**
+ * Converts the expression value to an Object.
+ *
+ * @param expressionValue the expression value to convert
+ * @return the converted object expression
+ */
+ private Object toValue(ExpressionLiteral expressionValue) {
+ Object value = expressionValue.toValue();
+ if (value instanceof Expression.Color) {
+ return ((Expression.Color) value).convertColor();
+ } else if (value instanceof Expression.ExpressionLiteral) {
+ return toValue((ExpressionLiteral) value);
+ } else if (value instanceof Expression) {
+ return ((Expression) value).toArray();
+ }
+ return value;
+ }
+
+ /**
+ * ExpressionLiteral wraps an object to be used as a literal in an expression.
+ *
+ * ExpressionLiteral is created with {@link #literal(Number)}, {@link #literal(boolean)},
+ * {@link #literal(String)} and {@link #literal(Object)}.
+ *
+ *
+ * @param
+ */
+ private static class ExpressionLiteral extends Expression {
+
+ protected T object;
+
+ /**
+ * Create an ExpressionValue wrapper.
+ *
+ * @param object the object to be wrapped
+ */
+ ExpressionLiteral(@NonNull T object) {
+ this.object = object;
+ }
+
+ /**
+ * Get the wrapped object.
+ *
+ * @return the wrapped object
+ */
+ Object toValue() {
+ return object;
+ }
+ }
+
+ //
+ // Types
+ //
+
+ /**
+ * Expression interpolator type.
+ *
+ * Is used for first parameter of {@link #interpolate(Expression, Expression, Stop...)}.
+ *
+ */
+ private static class Interpolator {
+ }
+
+ /**
+ * Expression color type.
+ */
+ public static class Color {
+
+ private int color;
+
+ /**
+ * Creates a color color type from a color int.
+ *
+ * @param color the int color
+ */
+ public Color(@ColorInt int color) {
+ this.color = color;
+ }
+
+ /**
+ * Converts the int color to rgba(d, d, d, d) string representation
+ *
+ * @return
+ */
+ public String convertColor() {
+ return PropertyFactory.colorToRgbaString(color);
+ }
+ }
+
+ /**
+ * Expression array type.
+ */
+ public static class Array {
+ }
+
+ /**
+ * Expression stop type.
+ *
+ * Can be used for {@link #stop(Object, Object)} as part of varargs parameter in
+ * {@link #step(Number, Expression, Stop...)} or {@link #interpolate(Expression, Expression, Stop...)}.
+ *
+ */
+ public static class Stop {
+
+ private Object value;
+ private Object output;
+
+ public Stop(Object value, Object output) {
+ this.value = value;
+ this.output = output;
+ }
+ }
+
+ //
+ // Literals
+ //
+
+ /**
+ * Create a literal number expression.
+ *
+ * @param number the number
+ * @return the expression
+ */
+ public static Expression literal(@NonNull Number number) {
+ return new ExpressionLiteral<>(number);
+ }
+
+ /**
+ * Create a literal string expression.
+ *
+ * @param string the string
+ * @return the expression
+ */
+ public static Expression literal(@NonNull String string) {
+ return new ExpressionLiteral<>(string);
+ }
+
+ /**
+ * Create a literal boolean expression.
+ *
+ * @param bool the boolean
+ * @return the expression
+ */
+ public static Expression literal(boolean bool) {
+ return new ExpressionLiteral<>(bool);
+ }
+
+ /**
+ * Create a literal object expression
+ *
+ * @param object the object
+ * @return the expression
+ */
+ public static Expression literal(@NonNull Object object) {
+ return new ExpressionLiteral<>(object);
+ }
+
+ //
+ // Color
+ //
+
+ /**
+ * Expression literal utility method to convert a color int to an color expression
+ *
+ * @param color the int color
+ * @return the color expression
+ */
+ public static Expression color(@ColorInt int color) {
+ return new ExpressionLiteral<>(new Color(color));
+ }
+
+ /**
+ * Creates a color value from red, green, and blue components, which must range between 0 and 255,
+ * and an alpha component of 1.
+ *
+ * If any component is out of range, the expression is an error.
+ *
+ *
+ * @param red red color expression
+ * @param green green color expression
+ * @param blue blue color expression
+ * @return expression
+ */
+ public static Expression rgb(@NonNull Expression red, @NonNull Expression green,
+ @NonNull Expression blue) {
+ return new Expression<>("rgb", red, green, blue);
+ }
+
+ /**
+ * Creates a color value from red, green, and blue components, which must range between 0 and 255,
+ * and an alpha component of 1.
+ *
+ * If any component is out of range, the expression is an error.
+ *
+ *
+ * @param red red color value
+ * @param green green color value
+ * @param blue blue color value
+ * @return expression
+ */
+ public static Expression rgb(@NonNull Number red, @NonNull Number green, @NonNull Number blue) {
+ return rgb(literal(red), literal(green), literal(blue));
+ }
+
+ /**
+ * Creates a color value from red, green, blue components, which must range between 0 and 255,
+ * and an alpha component which must range between 0 and 1.
+ *
+ * If any component is out of range, the expression is an error.
+ *
+ *
+ * @param red red color value
+ * @param green green color value
+ * @param blue blue color value
+ * @param alpha alpha color value
+ * @return expression
+ */
+ public static Expression rgba(@NonNull Expression red, @NonNull Expression green,
+ @NonNull Expression blue, @NonNull Expression alpha) {
+ return new Expression<>("rgba", red, green, blue, alpha);
+ }
+
+ /**
+ * Creates a color value from red, green, blue components, which must range between 0 and 255,
+ * and an alpha component which must range between 0 and 1.
+ *
+ * If any component is out of range, the expression is an error.
+ *
+ *
+ * @param red red color value
+ * @param green green color value
+ * @param blue blue color value
+ * @param alpha alpha color value
+ * @return expression
+ */
+ public static Expression rgba(@NonNull Number red, @NonNull Number green, @NonNull Number blue, @NonNull Number alpha) {
+ return rgba(literal(red), literal(green), literal(blue), literal(alpha));
+ }
+
+ /**
+ * Returns a four-element array containing the input color's red, green, blue, and alpha components, in that order.
+ *
+ * @param expression an expression to convert to a color
+ * @return expression
+ */
+ public static Expression toRgba(@NonNull Expression expression) {
+ return new Expression<>("to-rgba", expression);
+ }
+
+ //
+ // Decision
+ //
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ * The inputs must be numbers, strings, or booleans, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression eq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("==", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first boolean
+ * @param compareTwo the second boolean
+ * @return expression
+ */
+ public static Expression eq(boolean compareOne, boolean compareTwo) {
+ return eq(literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression eq(@NonNull String compareOne, @NonNull String compareTwo) {
+ return eq(literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression eq(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return eq(literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the input values are not equal, false otherwise.
+ * The inputs must be numbers, strings, or booleans, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression neq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("!=", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first boolean
+ * @param compareTwo the second boolean
+ * @return expression
+ */
+ public static Expression neq(boolean compareOne, boolean compareTwo) {
+ return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns `true` if the input values are not equal, `false` otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression neq(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns `true` if the input values are not equal, `false` otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression neq(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly greater than the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression gt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>(">", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is strictly greater than the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression gt(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>(">", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly greater than the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression gt(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>(">", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly less than the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression lt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("<", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is strictly less than the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression lt(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>("<", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly less than the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression lt(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>("<", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is greater than or equal to the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression gte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>(">=", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is greater than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression gte(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>(">=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is greater than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression gte(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>(">=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is less than or equal to the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression lte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("<=", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is less than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression lte(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>("<=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is less than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression lte(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>("<=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns `true` if all the inputs are `true`, `false` otherwise.
+ *
+ * The inputs are evaluated in order, and evaluation is short-circuiting:
+ * once an input expression evaluates to `false`,
+ * the result is `false` and no further input expressions are evaluated.
+ *
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression all(@NonNull Expression... input) {
+ return new Expression<>("all", input);
+ }
+
+ /**
+ * Returns `true` if any of the inputs are `true`, `false` otherwise.
+ *
+ * The inputs are evaluated in order, and evaluation is short-circuiting:
+ * once an input expression evaluates to `true`,
+ * the result is `true` and no further input expressions are evaluated.
+ *
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression any(@NonNull Expression... input) {
+ return new Expression<>("any", input);
+ }
+
+ /**
+ * Logical negation. Returns `true` if the input is `false`, and `false` if the input is `true`.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression not(@NonNull Expression input) {
+ return new Expression<>("!", input);
+ }
+
+ /**
+ * Logical negation. Returns `true` if the input is `false`, and `false` if the input is `true`.
+ *
+ * @param input boolean input
+ * @return expression
+ */
+ public static Expression not(boolean input) {
+ return not(literal(input));
+ }
+
+ /**
+ * Selects the first output whose corresponding test condition evaluates to true.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression switchCase(@NonNull @Size(min = 1) Expression... input) {
+ return new Expression("case", input);
+ }
+
+ /**
+ * Selects the output whose label value matches the input value, or the fallback value if no match is found.
+ * The `input` can be any string or number expression.
+ * Each label can either be a single literal value or an array of values.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression match(@NonNull @Size(min = 2) Expression... input) {
+ return new Expression("match", input);
+ }
+
+ /**
+ * Selects the output whose label value matches the input value, or the fallback value if no match is found.
+ * The `input` can be any string or number expression.
+ * Each label can either be a single literal value or an array of values.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression match(@NonNull Expression input, @NonNull Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return match(join(new Expression[] {input}, expressions));
+ }
+
+ /**
+ * Evaluates each expression in turn until the first non-null value is obtained, and returns that value.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression coalesce(@NonNull Expression... input) {
+ return new Expression("coalesce", input);
+ }
+
+ //
+ // FeatureData
+ //
+
+ /**
+ * Gets the feature properties object.
+ *
+ * Note that in some cases, it may be more efficient to use {@link #get(Expression)}} instead.
+ *
+ *
+ * @return expression
+ */
+ public static Expression properties() {
+ return new Expression<>("properties");
+ }
+
+ /**
+ * Gets the feature's geometry type: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon.
+ *
+ * @return expression
+ */
+ public static Expression geometryType() {
+ return new Expression<>("geometry-type");
+ }
+
+ /**
+ * Gets the feature's id, if it has one.
+ *
+ * @return expression
+ */
+ public static Expression id() {
+ return new Expression<>("id");
+ }
+
+ //
+ // Heatmap
+ //
+
+ /**
+ * Gets the kernel density estimation of a pixel in a heatmap layer,
+ * which is a relative measure of how many data points are crowded around a particular pixel.
+ * Can only be used in the `heatmap-color` property.
+ *
+ * @return expression
+ */
+ public static Expression heatmapDensity() {
+ return new Expression<>("heatmap-density");
+ }
+
+ //
+ // Lookup
+ //
+
+ /**
+ * Retrieves an item from an array.
+ *
+ * @param number the index expression
+ * @param expression the array expression
+ * @return expression
+ */
+ public static Expression at(@NonNull Expression number, @NonNull Expression expression) {
+ return new Expression<>("at", number, expression);
+ }
+
+ /**
+ * Retrieves an item from an array.
+ *
+ * @param number the index expression
+ * @param expression the array expression
+ * @return expression
+ */
+ public static Expression at(@NonNull Number number, @NonNull Expression expression) {
+ return at(literal(number), expression);
+ }
+
+ /**
+ * Retrieves a property value from the current feature's properties,
+ * or from another object if a second argument is provided.
+ * Returns null if the requested property is missing.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression get(@NonNull Expression input) {
+ return new Expression<>("get", input);
+ }
+
+ /**
+ * Retrieves a property value from the current feature's properties,
+ * or from another object if a second argument is provided.
+ * Returns null if the requested property is missing.
+ *
+ * @param input string input
+ * @return expression
+ */
+ public static Expression get(@NonNull String input) {
+ return get(literal(input));
+ }
+
+ /**
+ * Retrieves a property value from another object.
+ * Returns null if the requested property is missing.
+ *
+ * @param key a property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression get(@NonNull Expression key, @NonNull Expression object) {
+ return new Expression<>("get", key, object);
+ }
+
+ /**
+ * Retrieves a property value from another object.
+ * Returns null if the requested property is missing.
+ *
+ * @param key a property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression get(@NonNull String key, @NonNull Expression object) {
+ return get(literal(key), object);
+ }
+
+ /**
+ * Tests for the presence of an property value in the current feature's properties.
+ *
+ * @param key the expression property value key
+ * @return expression
+ */
+ public static Expression has(@NonNull Expression key) {
+ return new Expression<>("has", key);
+ }
+
+ /**
+ * Tests for the presence of an property value in the current feature's properties.
+ *
+ * @param key the property value key
+ * @return expression
+ */
+ public static Expression has(@NonNull String key) {
+ return has(literal(key));
+ }
+
+ /**
+ * Tests for the presence of an property value from another object.
+ *
+ * @param key the expression property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression has(@NonNull Expression key, @NonNull Expression object) {
+ return new Expression<>("has", key, object);
+ }
+
+ /**
+ * Tests for the presence of an property value from another object.
+ *
+ * @param key the property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression has(@NonNull String key, @NonNull Expression object) {
+ return has(literal(key), object);
+ }
+
+ /**
+ * Gets the length of an array or string.
+ *
+ * @param expression an expression object or expression string
+ * @return expression
+ */
+ public static Expression length(@NonNull Expression> expression) {
+ return new Expression<>("length", expression);
+ }
+
+ /**
+ * Gets the length of an array or string.
+ *
+ * @param input a string
+ * @return expression
+ */
+ public static Expression length(@NonNull String input) {
+ return length(literal(input));
+ }
+
+ //
+ // Math
+ //
+
+ /**
+ * Returns mathematical constant ln(2).
+ *
+ * @return expression
+ */
+ public static Expression ln2() {
+ return new Expression<>("ln2");
+ }
+
+ /**
+ * Returns the mathematical constant pi.
+ *
+ * @return expression
+ */
+ public static Expression pi() {
+ return new Expression<>("pi");
+ }
+
+ /**
+ * Returns the mathematical constant e.
+ *
+ * @return expression
+ */
+ public static Expression e() {
+ return new Expression<>("e");
+ }
+
+ /**
+ * Returns the sum of the inputs.
+ *
+ * @param numbers the numbers to calculate the sum for
+ * @return expression
+ */
+ public static Expression sum(@Size(min = 2) Expression... numbers) {
+ return new Expression<>("+", numbers);
+ }
+
+ /**
+ * Returns the sum of the inputs.
+ *
+ * @param numbers the numbers to calculate the sum for
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression sum(@Size(min = 2) Number... numbers) {
+ Expression[] numberExpression = (Expression[]) new Expression>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return sum(numberExpression);
+ }
+
+ /**
+ * Returns the product of the inputs.
+ *
+ * @param numbers the numbers to calculate the product for
+ * @return expression
+ */
+ public static Expression product(@Size(min = 2) Expression... numbers) {
+ return new Expression<>("*", numbers);
+ }
+
+ /**
+ * Returns the product of the inputs.
+ *
+ * @param numbers the numbers to calculate the product for
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression product(@Size(min = 2) Number... numbers) {
+ Expression[] numberExpression = (Expression[]) new Expression>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return product(numberExpression);
+ }
+
+ /**
+ * Returns the result of subtracting a number from 0.
+ *
+ * @param number the number subtract from 0
+ * @return expression
+ */
+ public static Expression subtract(@NonNull Expression number) {
+ return new Expression<>("-", number);
+ }
+
+ /**
+ * Returns the result of subtracting a number from 0.
+ *
+ * @param number the number subtract from 0
+ * @return expression
+ */
+ public static Expression subtract(@NonNull Number number) {
+ return subtract(literal(number));
+ }
+
+ /**
+ * Returns the result of subtracting the second input from the first.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression subtract(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression<>("-", first, second);
+ }
+
+ /**
+ * Returns the result of subtracting the second input from the first.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression subtract(@NonNull Number first, @NonNull Number second) {
+ return subtract(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the result of floating point division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression division(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression<>("/", first, second);
+ }
+
+ /**
+ * Returns the result of floating point division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression division(@NonNull Number first, @NonNull Number second) {
+ return division(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the remainder after integer division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression mod(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression<>("%", first, second);
+ }
+
+ /**
+ * Returns the remainder after integer division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression mod(@NonNull Number first, @NonNull Number second) {
+ return mod(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the result of raising the first input to the power specified by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression pow(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression<>("^", first, second);
+ }
+
+ /**
+ * Returns the result of raising the first input to the power specified by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression pow(@NonNull Number first, @NonNull Number second) {
+ return pow(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the square root of the input
+ *
+ * @param number the number to take the square root from
+ * @return expression
+ */
+ public static Expression sqrt(@NonNull Expression number) {
+ return new Expression<>("sqrt", number);
+ }
+
+ /**
+ * Returns the square root of the input
+ *
+ * @param number the number to take the square root from
+ * @return expression
+ */
+ public static Expression sqrt(@NonNull Number number) {
+ return sqrt(literal(number));
+ }
+
+ /**
+ * Returns the base-ten logarithm of the input.
+ *
+ * @param number the number to take base-ten logarithm from
+ * @return expression
+ */
+ public static Expression log10(@NonNull Expression number) {
+ return new Expression<>("log10", number);
+ }
+
+ /**
+ * Returns the base-ten logarithm of the input.
+ *
+ * @param number the number to take base-ten logarithm from
+ * @return expression
+ */
+ public static Expression log10(@NonNull Number number) {
+ return log10(literal(number));
+ }
+
+ /**
+ * Returns the natural logarithm of the input.
+ *
+ * @param number the number to take natural logarithm from
+ * @return expression
+ */
+ public static Expression ln(Expression number) {
+ return new Expression<>("ln", number);
+ }
+
+ /**
+ * Returns the natural logarithm of the input.
+ *
+ * @param number the number to take natural logarithm from
+ * @return expression
+ */
+ public static Expression ln(Number number) {
+ return ln(literal(number));
+ }
+
+ /**
+ * Returns the base-two logarithm of the input.
+ *
+ * @param number the number to take base-two logarithm from
+ * @return expression
+ */
+ public static Expression log2(@NonNull Expression number) {
+ return new Expression<>("log2", number);
+ }
+
+ /**
+ * Returns the base-two logarithm of the input.
+ *
+ * @param number the number to take base-two logarithm from
+ * @return expression
+ */
+ public static Expression log2(@NonNull Number number) {
+ return log2(literal(number));
+ }
+
+ /**
+ * Returns the sine of the input.
+ *
+ * @param number the number to calculate the sine for
+ * @return expression
+ */
+ public static Expression sin(@NonNull Expression number) {
+ return new Expression<>("sin", number);
+ }
+
+ /**
+ * Returns the sine of the input.
+ *
+ * @param number the number to calculate the sine for
+ * @return expression
+ */
+ public static Expression sin(@NonNull Number number) {
+ return sin(literal(number));
+ }
+
+ /**
+ * Returns the cosine of the input.
+ *
+ * @param number the number to calculate the cosine for
+ * @return expression
+ */
+ public static Expression cos(@NonNull Expression number) {
+ return new Expression<>("cos", number);
+ }
+
+ /**
+ * Returns the cosine of the input.
+ *
+ * @param number the number to calculate the cosine for
+ * @return expression
+ */
+ public static Expression cos(@NonNull Number number) {
+ return new Expression<>("cos", literal(number));
+ }
+
+ /**
+ * Returns the tangent of the input.
+ *
+ * @param number the number to calculate the tangent for
+ * @return expression
+ */
+ public static Expression tan(@NonNull Expression number) {
+ return new Expression<>("tan", number);
+ }
+
+ /**
+ * Returns the tangent of the input.
+ *
+ * @param number the number to calculate the tangent for
+ * @return expression
+ */
+ public static Expression tan(@NonNull Number number) {
+ return new Expression<>("tan", literal(number));
+ }
+
+ /**
+ * Returns the arcsine of the input.
+ *
+ * @param number the number to calculate the arcsine for
+ * @return expression
+ */
+ public static Expression asin(@NonNull Expression number) {
+ return new Expression<>("asin", number);
+ }
+
+ /**
+ * Returns the arcsine of the input.
+ *
+ * @param number the number to calculate the arcsine for
+ * @return expression
+ */
+ public static Expression asin(@NonNull Number number) {
+ return asin(literal(number));
+ }
+
+ /**
+ * Returns the arccosine of the input.
+ *
+ * @param number the number to calculate the arccosine for
+ * @return expression
+ */
+ public static Expression acos(@NonNull Expression number) {
+ return new Expression<>("acos", number);
+ }
+
+ /**
+ * Returns the arccosine of the input.
+ *
+ * @param number the number to calculate the arccosine for
+ * @return expression
+ */
+ public static Expression acos(@NonNull Number number) {
+ return acos(literal(number));
+ }
+
+ /**
+ * Returns the arctangent of the input.
+ *
+ * @param number the number to calculate the arctangent for
+ * @return expression
+ */
+ public static Expression atan(@NonNull Expression number) {
+ return new Expression("atan", number);
+ }
+
+ /**
+ * Returns the arctangent of the input.
+ *
+ * @param number the number to calculate the arctangent for
+ * @return expression
+ */
+ public static Expression atan(@NonNull Number number) {
+ return atan(literal(number));
+ }
+
+ /**
+ * Returns the minimum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the minimum from
+ * @return expression
+ */
+ public static Expression min(@Size(min = 1) Expression... numbers) {
+ return new Expression<>("min", numbers);
+ }
+
+ /**
+ * Returns the minimum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the minimum from
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression min(@Size(min = 1) Number... numbers) {
+ Expression[] numberExpression = (Expression[]) new Expression>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return min(numberExpression);
+ }
+
+ /**
+ * Returns the maximum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the maximum from
+ * @return expression
+ */
+ public static Expression max(@Size(min = 1) Expression... numbers) {
+ return new Expression<>("max", numbers);
+ }
+
+ /**
+ * Returns the maximum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the maximum from
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression max(@Size(min = 1) Number... numbers) {
+ Expression[] numberExpression = (Expression[]) new Expression>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return max(numberExpression);
+ }
+
+ //
+ // String
+ //
+
+ /**
+ * Returns the input string converted to uppercase.
+ *
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ *
+ *
+ * @param string the string to upcase
+ * @return expression
+ */
+ public static Expression upcase(@NonNull Expression string) {
+ return new Expression<>("upcase", string);
+ }
+
+ /**
+ * Returns the input string converted to uppercase.
+ *
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ *
+ *
+ * @param string string to upcase
+ * @return expression
+ */
+ public static Expression upcase(@NonNull String string) {
+ return upcase(literal(string));
+ }
+
+ /**
+ * Returns the input string converted to lowercase.
+ *
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ *
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression downcase(@NonNull Expression input) {
+ return new Expression<>("downcase", input);
+ }
+
+ /**
+ * Returns the input string converted to lowercase.
+ *
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ *
+ *
+ * @param input string to downcase
+ * @return expression
+ */
+ public static Expression downcase(@NonNull String input) {
+ return downcase(literal(input));
+ }
+
+ /**
+ * Returns a string consisting of the concatenation of the inputs.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression concat(@NonNull Expression... input) {
+ return new Expression<>("concat", input);
+ }
+
+ /**
+ * Returns a string consisting of the concatenation of the inputs.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression concat(@NonNull String... input) {
+ Expression[] stringExpression = (Expression[]) new Expression>[input.length];
+ for (int i = 0; i < input.length; i++) {
+ stringExpression[i] = literal(input[i]);
+ }
+ return concat(stringExpression);
+ }
+
+ //
+ // Types
+ //
+
+ /**
+ * Asserts that the input is an array (optionally with a specific item type and length).
+ * If, when the input expression is evaluated, it is not of the asserted type,
+ * then this assertion will cause the whole expression to be aborted.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression array(@NonNull Expression input) {
+ return new Expression<>("array", input);
+ }
+
+ /**
+ * Returns a string describing the type of the given value.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression typeOf(@NonNull Expression input) {
+ return new Expression<>("typeof", input);
+ }
+
+ /**
+ * Asserts that the input value is a string.
+ * If multiple values are provided, each one is evaluated in order until a string value is obtained.
+ * If none of the inputs are strings, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression string(@NonNull Expression input) {
+ return new Expression<>("string", input);
+ }
+
+ /**
+ * Asserts that the input value is a number.
+ * If multiple values are provided, each one is evaluated in order until a number value is obtained.
+ * If none of the inputs are numbers, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression number(@NonNull Expression input) {
+ return new Expression<>("number", input);
+ }
+
+ /**
+ * Asserts that the input value is a boolean.
+ * If multiple values are provided, each one is evaluated in order until a boolean value is obtained.
+ * If none of the inputs are booleans, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression bool(@NonNull Expression input) {
+ return new Expression<>("boolean", input);
+ }
+
+ /**
+ * Asserts that the input value is an object. If it is not, the expression is an error
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression object(@NonNull Expression input) {
+ return new Expression<>("object", input);
+ }
+
+ /**
+ * Converts the input value to a string.
+ * If the input is null, the result is null.
+ * If the input is a boolean, the result is true or false.
+ * If the input is a number, it is converted to a string by NumberToString in the ECMAScript Language Specification.
+ * If the input is a color, it is converted to a string of the form "rgba(r,g,b,a)",
+ * where `r`, `g`, and `b` are numerals ranging from 0 to 255, and `a` ranges from 0 to 1.
+ * Otherwise, the input is converted to a string in the format specified by the JSON.stringify in the ECMAScript
+ * Language Specification.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression toString(@NonNull Expression input) {
+ return new Expression<>("to-string", input);
+ }
+
+ /**
+ * Converts the input value to a number, if possible.
+ * If the input is null or false, the result is 0.
+ * If the input is true, the result is 1.
+ * If the input is a string, it is converted to a number as specified by the ECMAScript Language Specification.
+ * If multiple values are provided, each one is evaluated in order until the first successful conversion is obtained.
+ * If none of the inputs can be converted, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression toNumber(@NonNull Expression input) {
+ return new Expression<>("to-number", input);
+ }
+
+ /**
+ * "Converts the input value to a boolean. The result is `false` when then input is an empty string, 0, false,
+ * null, or NaN; otherwise it is true.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression toBool(@NonNull Expression input) {
+ return new Expression<>("to-boolean", input);
+ }
+
+ /**
+ * Converts the input value to a color. If multiple values are provided,
+ * each one is evaluated in order until the first successful conversion is obtained.
+ * If none of the inputs can be converted, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression toColor(@NonNull Expression input) {
+ return new Expression<>("to-color", input);
+ }
+
+ //
+ // Variable binding
+ //
+
+ /**
+ * Binds input to named variables,
+ * which can then be referenced in the result expression using {@link #var(String)} or {@link #var(Expression)}.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression let(@Size(min = 1) Expression... input) {
+ return new Expression<>("let", input);
+ }
+
+ /**
+ * References variable bound using let.
+ *
+ * @param expression the variable naming expression that was bound with using let
+ * @return expression
+ */
+ public static Expression var(@NonNull Expression expression) {
+ return new Expression<>("var", expression);
+ }
+
+ /**
+ * References variable bound using let.
+ *
+ * @param variableName the variable naming that was bound with using let
+ * @return expression
+ */
+ public static Expression var(@NonNull String variableName) {
+ return var(literal(variableName));
+ }
+
+ //
+ // Zoom
+ //
+
+ /**
+ * Gets the current zoom level.
+ *
+ * Note that in style layout and paint properties,
+ * zoom may only appear as the input to a top-level step or interpolate expression.
+ *
+ *
+ * @return expression
+ */
+ public static Expression zoom() {
+ return new Expression<>("zoom");
+ }
+
+ //
+ // Ramps, scales, curves
+ //
+
+ public static Stop stop(@NonNull Object stop, @NonNull Object value) {
+ return new Stop(stop, value);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param input the input value
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Number input, @NonNull Expression expression, Expression... stops) {
+ return step(literal(input), expression, stops);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param expression the input expression
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Expression input, @NonNull Expression expression, Expression... stops) {
+ return new Expression("step", join(new Expression[] {input, expression}, stops));
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param input the input value
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Number input, @NonNull Expression expression, Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return step(literal(input), expression, expressions);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param input the input value
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Expression input, @NonNull Expression expression, Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return step(input, expression, expressions);
+ }
+
+ /**
+ * Produces continuous, smooth results by interpolating between pairs of input and output values (\"stops\").
+ * The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * The output type must be `number`, `array<number>`, or `color`.
+ *
+ * @param interpolation type of interpolation
+ * @param number the input expression
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression interpolate(@NonNull Expression interpolation,
+ @NonNull Expression number, Expression... stops) {
+ return new Expression("interpolate", join(new Expression[] {interpolation, number}, stops));
+ }
+
+ /**
+ * Produces continuous, smooth results by interpolating between pairs of input and output values (\"stops\").
+ * The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * The output type must be `number`, `array<number>`, or `color`.
+ *
+ * @param interpolation type of interpolation
+ * @param number the input expression
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression interpolate(@NonNull Expression interpolation,
+ @NonNull Expression number, Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return interpolate(interpolation, number, expressions);
+ }
+
+ /**
+ * interpolates linearly between the pair of stops just less than and just greater than the input.
+ *
+ * @return expression
+ */
+ public static Expression linear() {
+ return new Expression<>("linear");
+ }
+
+ /**
+ * Interpolates exponentially between the stops just less than and just greater than the input.
+ * `base` controls the rate at which the output increases:
+ * higher values make the output increase more towards the high end of the range.
+ * With values close to 1 the output increases linearly.
+ *
+ * @param base value controlling the route at which the output increases
+ * @return expression
+ */
+ public static Expression exponential(@NonNull Number base) {
+ return exponential(literal(base));
+ }
+
+ /**
+ * Interpolates exponentially between the stops just less than and just greater than the input.
+ * The parameter controls the rate at which the output increases:
+ * higher values make the output increase more towards the high end of the range.
+ * With values close to 1 the output increases linearly.
+ *
+ * @param expression base number expression
+ * @return expression
+ */
+ public static Expression exponential(@NonNull Expression expression) {
+ return new Expression<>("exponential", expression);
+ }
+
+ /**
+ * Interpolates using the cubic bezier curve defined by the given control points.
+ *
+ * @param x1 x value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param y1 y value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param x2 x value of the second point of a cubic bezier, ranges from 0 to 1
+ * @param y2 y value fo the second point of a cubic bezier, ranges from 0 to 1
+ * @return expression
+ */
+ public static Expression cubicBezier(@NonNull Expression x1, @NonNull Expression y1,
+ @NonNull Expression x2, @NonNull Expression y2) {
+ return new Expression<>("cubic-bezier", x1, y1, x2, y2);
+ }
+
+ /**
+ * Interpolates using the cubic bezier curve defined by the given control points.
+ *
+ * @param x1 x value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param y1 y value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param x2 x value of the second point of a cubic bezier, ranges from 0 to 1
+ * @param y2 y value fo the second point of a cubic bezier, ranges from 0 to 1
+ * @return expression
+ */
+ public static Expression cubicBezier(@NonNull Number x1, @NonNull Number y1,
+ @NonNull Number x2, @NonNull Number y2) {
+ return cubicBezier(literal(x1), literal(y1), literal(x2), literal(y2));
+ }
+
+ /**
+ * Joins two expressions arrays.
+ *
+ * This flattens the object array output of an expression from a nested expression hierarchy.
+ *
+ *
+ * @param left the left part of an expression
+ * @param right the right part of an expression
+ * @return the joined expression
+ */
+ private static Expression[] join(Expression[] left, Expression[] right) {
+ Expression[] output = new Expression[left.length + right.length];
+ System.arraycopy(left, 0, output, 0, left.length);
+ System.arraycopy(right, 0, output, left.length, right.length);
+ return output;
+ }
+
+}
\ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
index 5015dd009d..5400e04589 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.NonNull;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.functions.Function;
/**
@@ -88,6 +89,14 @@ public abstract class Layer {
}
private Object convertValue(Object value) {
- return value != null && value instanceof Function ? ((Function) value).toValueObject() : value;
+ if (value != null) {
+ if (value instanceof Function) {
+ return ((Function) value).toValueObject();
+ } else if (value instanceof Expression) {
+ return ((Expression) value).toArray();
+ }
+ }
+ return value;
}
-}
+
+}
\ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
index 8d5858217b..8d6c7dd055 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
@@ -402,7 +402,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_TRANSFORM {}
- // FILL_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // FILL_TRANSLATE_ANCHOR: Controls the frame of reference for `fill-translate`.
/**
* The fill is translated relative to the map.
@@ -414,7 +414,7 @@ public final class Property {
public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `fill-translate`.
*/
@StringDef({
FILL_TRANSLATE_ANCHOR_MAP,
@@ -423,7 +423,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface FILL_TRANSLATE_ANCHOR {}
- // LINE_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // LINE_TRANSLATE_ANCHOR: Controls the frame of reference for `line-translate`.
/**
* The line is translated relative to the map.
@@ -435,7 +435,7 @@ public final class Property {
public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `line-translate`.
*/
@StringDef({
LINE_TRANSLATE_ANCHOR_MAP,
@@ -444,7 +444,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface LINE_TRANSLATE_ANCHOR {}
- // ICON_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // ICON_TRANSLATE_ANCHOR: Controls the frame of reference for `icon-translate`.
/**
* Icons are translated relative to the map.
@@ -456,7 +456,7 @@ public final class Property {
public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `icon-translate`.
*/
@StringDef({
ICON_TRANSLATE_ANCHOR_MAP,
@@ -465,7 +465,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface ICON_TRANSLATE_ANCHOR {}
- // TEXT_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // TEXT_TRANSLATE_ANCHOR: Controls the frame of reference for `text-translate`.
/**
* The text is translated relative to the map.
@@ -477,7 +477,7 @@ public final class Property {
public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `text-translate`.
*/
@StringDef({
TEXT_TRANSLATE_ANCHOR_MAP,
@@ -486,7 +486,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_TRANSLATE_ANCHOR {}
- // CIRCLE_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // CIRCLE_TRANSLATE_ANCHOR: Controls the frame of reference for `circle-translate`.
/**
* The circle is translated relative to the map.
@@ -498,7 +498,7 @@ public final class Property {
public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `circle-translate`.
*/
@StringDef({
CIRCLE_TRANSLATE_ANCHOR_MAP,
@@ -549,7 +549,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface CIRCLE_PITCH_ALIGNMENT {}
- // FILL_EXTRUSION_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // FILL_EXTRUSION_TRANSLATE_ANCHOR: Controls the frame of reference for `fill-extrusion-translate`.
/**
* The fill extrusion is translated relative to the map.
@@ -561,7 +561,7 @@ public final class Property {
public static final String FILL_EXTRUSION_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `fill-extrusion-translate`.
*/
@StringDef({
FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP,
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
index d4ddbe48ef..e159acac35 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
@@ -7,6 +7,7 @@ import android.support.annotation.ColorInt;
import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
/**
* Constructs paint/layout properties for Layers
@@ -32,6 +33,7 @@ public class PropertyFactory {
* @param function the visibility function
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> visibility(Function function) {
return new LayoutPropertyValue<>("visibility", function);
}
@@ -46,6 +48,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-antialias", value);
}
+ /**
+ * Whether or not the fill should be antialiased.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillAntialias(Expression expression) {
+ return new PaintPropertyValue<>("fill-antialias", expression);
+ }
+
/**
* Whether or not the fill should be antialiased.
@@ -54,6 +66,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Boolean
* @return property wrapper around a Boolean function
*/
+ @Deprecated
public static PropertyValue> fillAntialias(CameraFunction function) {
return new PaintPropertyValue<>("fill-antialias", function);
}
@@ -68,6 +81,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-opacity", value);
}
+ /**
+ * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillOpacity(Expression expression) {
+ return new PaintPropertyValue<>("fill-opacity", expression);
+ }
+
/**
* The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used.
@@ -76,6 +99,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static PropertyValue> fillOpacity(Function function) {
return new PaintPropertyValue<>("fill-opacity", function);
}
@@ -100,6 +124,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-color", value);
}
+ /**
+ * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillColor(Expression expression) {
+ return new PaintPropertyValue<>("fill-color", expression);
+ }
+
/**
* The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
@@ -108,6 +142,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> fillColor(Function function) {
return new PaintPropertyValue<>("fill-color", function);
}
@@ -132,6 +167,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-outline-color", value);
}
+ /**
+ * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillOutlineColor(Expression expression) {
+ return new PaintPropertyValue<>("fill-outline-color", expression);
+ }
+
/**
* The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
@@ -140,6 +185,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> fillOutlineColor(Function function) {
return new PaintPropertyValue<>("fill-outline-color", function);
}
@@ -154,6 +200,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-translate", value);
}
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillTranslate(Expression expression) {
+ return new PaintPropertyValue<>("fill-translate", expression);
+ }
+
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
@@ -162,12 +218,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static PropertyValue> fillTranslate(CameraFunction function) {
return new PaintPropertyValue<>("fill-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -176,14 +233,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("fill-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
*
* @param the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> fillTranslateAnchor(CameraFunction function) {
return new PaintPropertyValue<>("fill-translate-anchor", function);
}
@@ -198,6 +266,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-pattern", value);
}
+ /**
+ * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue fillPattern(Expression expression) {
+ return new PaintPropertyValue<>("fill-pattern", expression);
+ }
+
/**
* Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
@@ -206,6 +284,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> fillPattern(CameraFunction function) {
return new PaintPropertyValue<>("fill-pattern", function);
}
@@ -220,6 +299,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-opacity", value);
}
+ /**
+ * The opacity at which the line will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineOpacity(Expression expression) {
+ return new PaintPropertyValue<>("line-opacity", expression);
+ }
+
/**
* The opacity at which the line will be drawn.
@@ -228,6 +317,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static PropertyValue> lineOpacity(Function function) {
return new PaintPropertyValue<>("line-opacity", function);
}
@@ -252,6 +342,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-color", value);
}
+ /**
+ * The color with which the line will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineColor(Expression expression) {
+ return new PaintPropertyValue<>("line-color", expression);
+ }
+
/**
* The color with which the line will be drawn.
@@ -260,6 +360,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> lineColor(Function function) {
return new PaintPropertyValue<>("line-color", function);
}
@@ -274,6 +375,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-translate", value);
}
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineTranslate(Expression expression) {
+ return new PaintPropertyValue<>("line-translate", expression);
+ }
+
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
@@ -282,12 +393,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static PropertyValue> lineTranslate(CameraFunction function) {
return new PaintPropertyValue<>("line-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -296,14 +408,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("line-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
*
* @param the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static PropertyValue> lineTranslateAnchor(CameraFunction function) {
return new PaintPropertyValue<>("line-translate-anchor", function);
}
@@ -318,6 +441,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-width", value);
}
+ /**
+ * Stroke thickness.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineWidth(Expression expression) {
+ return new PaintPropertyValue<>("line-width", expression);
+ }
+
/**
* Stroke thickness.
@@ -326,6 +459,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static PropertyValue> lineWidth(Function function) {
return new PaintPropertyValue<>("line-width", function);
}
@@ -340,6 +474,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-gap-width", value);
}
+ /**
+ * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineGapWidth(Expression expression) {
+ return new PaintPropertyValue<>("line-gap-width", expression);
+ }
+
/**
* Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
@@ -348,6 +492,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static PropertyValue> lineGapWidth(Function function) {
return new PaintPropertyValue<>("line-gap-width", function);
}
@@ -362,6 +507,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-offset", value);
}
+ /**
+ * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineOffset(Expression expression) {
+ return new PaintPropertyValue<>("line-offset", expression);
+ }
+
/**
* The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset.
@@ -370,6 +525,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static PropertyValue> lineOffset(Function function) {
return new PaintPropertyValue<>("line-offset", function);
}
@@ -384,6 +540,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-blur", value);
}
+ /**
+ * Blur applied to the line, in density-independent pixels.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineBlur(Expression expression) {
+ return new PaintPropertyValue<>("line-blur", expression);
+ }
+
/**
* Blur applied to the line, in density-independent pixels.
@@ -392,6 +558,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static PropertyValue> lineBlur(Function function) {
return new PaintPropertyValue<>("line-blur", function);
}
@@ -406,6 +573,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-dasharray", value);
}
+ /**
+ * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue lineDasharray(Expression expression) {
+ return new PaintPropertyValue<>("line-dasharray", expression);
+ }
+
/**
* Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width.
@@ -414,6 +591,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static PropertyValue> lineDasharray(CameraFunction function) {
return new PaintPropertyValue<>("line-dasharray", function);
}
@@ -428,6 +606,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-pattern", value);
}
+ /**
+ * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue