[android] - add expression conversion, add getters (#11352)

This commit is contained in:
Tobrun
2018-03-08 16:27:02 +01:00
committed by GitHub
parent dfdfbc0990
commit 6179110b6b
53 changed files with 2367 additions and 13774 deletions

View File

@@ -5,9 +5,13 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -101,10 +105,6 @@ public class Expression {
return new ExpressionLiteral(bool);
}
//
// Types
//
/**
* Create a literal object expression.
*
@@ -159,10 +159,6 @@ public class Expression {
return rgb(literal(red), literal(green), literal(blue));
}
//
// Literals
//
/**
* 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.
@@ -224,10 +220,6 @@ public class Expression {
return new Expression("==", compareOne, compareTwo);
}
//
// Color
//
/**
* Returns true if the input values are equal, false otherwise.
*
@@ -301,10 +293,6 @@ public class Expression {
return new Expression("!=", literal(compareOne), literal(compareTwo));
}
//
// Decision
//
/**
* Returns `true` if the input values are not equal, `false` otherwise.
*
@@ -477,7 +465,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-all">Style specification</a>
*/
public static Expression all(@NonNull Expression... input) {
return new Expression("all", input);
}
@@ -494,7 +481,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-any">Style specification</a>
*/
public static Expression any(@NonNull Expression... input) {
return new Expression("any", input);
}
@@ -532,7 +518,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-case">Style specification</a>
*/
public static Expression switchCase(@NonNull @Size(min = 1) Expression... input) {
return new Expression("case", input);
}
@@ -661,10 +646,6 @@ public class Expression {
return new Expression("get", input);
}
//
// FeatureData
//
/**
* Retrieves a property value from the current feature's properties,
* or from another object if a second argument is provided.
@@ -704,10 +685,6 @@ public class Expression {
return get(literal(key), object);
}
//
// Heatmap
//
/**
* Tests for the presence of an property value in the current feature's properties.
*
@@ -719,10 +696,6 @@ public class Expression {
return new Expression("has", key);
}
//
// Lookup
//
/**
* Tests for the presence of an property value in the current feature's properties.
*
@@ -817,7 +790,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-+">Style specification</a>
*/
public static Expression sum(@Size(min = 2) Expression... numbers) {
return new Expression("+", numbers);
}
@@ -829,7 +801,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-+">Style specification</a>
*/
public static Expression sum(@Size(min = 2) Number... numbers) {
Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
@@ -845,7 +816,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-*">Style specification</a>
*/
public static Expression product(@Size(min = 2) Expression... numbers) {
return new Expression("*", numbers);
}
@@ -857,7 +827,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-*">Style specification</a>
*/
public static Expression product(@Size(min = 2) Number... numbers) {
Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
@@ -866,10 +835,6 @@ public class Expression {
return product(numberExpression);
}
//
// Math
//
/**
* Returns the result of subtracting a number from 0.
*
@@ -1215,7 +1180,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-min">Style specification</a>
*/
public static Expression min(@Size(min = 1) Expression... numbers) {
return new Expression("min", numbers);
}
@@ -1227,7 +1191,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-min">Style specification</a>
*/
public static Expression min(@Size(min = 1) Number... numbers) {
Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
@@ -1243,7 +1206,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-max">Style specification</a>
*/
public static Expression max(@Size(min = 1) Expression... numbers) {
return new Expression("max", numbers);
}
@@ -1255,7 +1217,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-max">Style specification</a>
*/
public static Expression max(@Size(min = 1) Number... numbers) {
Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
@@ -1331,7 +1292,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-concat">Style specification</a>
*/
public static Expression concat(@NonNull Expression... input) {
return new Expression("concat", input);
}
@@ -1343,7 +1303,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-concat">Style specification</a>
*/
public static Expression concat(@NonNull String... input) {
Expression[] stringExpression = new Expression[input.length];
for (int i = 0; i < input.length; i++) {
@@ -1365,10 +1324,6 @@ public class Expression {
return new Expression("array", input);
}
//
// String
//
/**
* Returns a string describing the type of the given value.
*
@@ -1448,10 +1403,6 @@ public class Expression {
return new Expression("to-string", input);
}
//
// Types
//
/**
* Converts the input value to a number, if possible.
* If the input is null or false, the result is 0.
@@ -1501,7 +1452,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-let">Style specification</a>
*/
public static Expression let(@Size(min = 1) Expression... input) {
return new Expression("let", input);
}
@@ -1565,7 +1515,6 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
public static Expression step(@NonNull Number input, @NonNull Expression expression, Expression... stops) {
return step(literal(input), expression, stops);
}
@@ -1582,15 +1531,10 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
public static Expression step(@NonNull Expression input, @NonNull Expression expression, Expression... stops) {
return new Expression("step", join(new Expression[] {input, expression}, stops));
}
//
// Variable binding
//
/**
* 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\"]`).
@@ -1603,14 +1547,8 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
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);
return step(literal(input), expression, Stop.toExpressionArray(stops));
}
/**
@@ -1625,14 +1563,8 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
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);
return step(input, expression, Stop.toExpressionArray(stops));
}
/**
@@ -1647,16 +1579,11 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
public static Expression interpolate(@NonNull Interpolator interpolation,
@NonNull Expression number, Expression... stops) {
return new Expression("interpolate", join(new Expression[] {interpolation, number}, stops));
}
//
// Zoom
//
/**
* 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\"]`).
@@ -1669,21 +1596,11 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
public static Expression interpolate(@NonNull Interpolator 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);
return interpolate(interpolation, number, Stop.toExpressionArray(stops));
}
//
// Ramps, scales, curves
//
/**
* interpolates linearly between the pair of stops just less than and just greater than the input.
*
@@ -1834,6 +1751,43 @@ public class Expression {
return builder.toString();
}
/**
* Indicates whether some other object is "equal to" this one.
*
* @param o the other object
* @return true if equal, false if not
*/
@Override
public boolean equals(Object o) {
super.equals(o);
if (this == o) {
return true;
}
if (o == null || !(o instanceof Expression)) {
return false;
}
Expression that = (Expression) o;
if (operator != null ? !operator.equals(that.operator) : that.operator != null) {
return false;
}
return Arrays.deepEquals(arguments, that.arguments);
}
/**
* Returns a hash code value for the expression.
*
* @return a hash code value for this expression
*/
@Override
public int hashCode() {
int result = operator != null ? operator.hashCode() : 0;
result = 31 * result + Arrays.hashCode(arguments);
return result;
}
/**
* ExpressionLiteral wraps an object to be used as a literal in an expression.
* <p>
@@ -1841,27 +1795,72 @@ public class Expression {
* {@link #literal(String)} and {@link #literal(Object)}.
* </p>
*/
private static class ExpressionLiteral extends Expression {
public static class ExpressionLiteral extends Expression {
protected Object literal;
/**
* Create an ExpressionValue wrapper.
* Create an expression literal.
*
* @param object the object to be wrapped
* @param object the object to be treated as literal
*/
ExpressionLiteral(@NonNull Object object) {
public ExpressionLiteral(@NonNull Object object) {
this.literal = object;
}
/**
* Get the wrapped object.
* Get the literal object.
*
* @return the wrapped object
* @return the literal object
*/
Object toValue() {
return literal;
}
/**
* Returns a string representation of the expression literal.
*
* @return a string representation of the object.
*/
@Override
public String toString() {
return literal.toString();
}
/**
* Indicates whether some other object is "equal to" this one.
*
* @param o the other object
* @return true if equal, false if not
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
ExpressionLiteral that = (ExpressionLiteral) o;
return literal != null ? literal.equals(that.literal) : that.literal == null;
}
/**
* Returns a hash code value for the expression literal.
*
* @return a hash code value for this expression literal
*/
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (literal != null ? literal.hashCode() : 0);
return result;
}
}
/**
@@ -1896,9 +1895,9 @@ public class Expression {
/**
* Converts the int color to rgba(d, d, d, d) string representation
*
* @return
* @return the string representation of a color
*/
public String convertColor() {
String convertColor() {
return PropertyFactory.colorToRgbaString(color);
}
}
@@ -1921,9 +1920,90 @@ public class Expression {
private Object value;
private Object output;
public Stop(Object value, Object output) {
Stop(Object value, Object output) {
this.value = value;
this.output = output;
}
/**
* Converts a varargs of Stops to a Expression array.
*
* @param stops the stops to convert
* @return the converted stops as an expression array
*/
static Expression[] toExpressionArray(Stop... stops) {
Expression[] expressions = new Expression[stops.length * 2];
Stop stop;
Object inputValue, outputValue;
for (int i = 0; i < stops.length; i++) {
stop = stops[i];
inputValue = stop.value;
outputValue = stop.output;
if (!(inputValue instanceof Expression)) {
inputValue = literal(inputValue);
}
if (!(outputValue instanceof Expression)) {
outputValue = literal(outputValue);
}
expressions[i * 2] = (Expression) inputValue;
expressions[i * 2 + 1] = (Expression) outputValue;
}
return expressions;
}
}
/**
* Converts a JsonArray to an expression.
*/
public final static class Converter {
/**
* Converts a JsonArray to an expression
*
* @param jsonArray the json array to convert
* @return the expression
*/
public static Expression convert(@NonNull JsonArray jsonArray) {
if (jsonArray.size() == 0) {
throw new IllegalArgumentException("Can't convert empty jsonArray expressions");
}
final String operator = jsonArray.get(0).getAsString();
final List<Expression> arguments = new ArrayList<>();
JsonElement jsonElement;
for (int i = 1; i < jsonArray.size(); i++) {
jsonElement = jsonArray.get(i);
if (jsonElement instanceof JsonArray) {
arguments.add(convert((JsonArray) jsonElement));
} else if (jsonElement instanceof JsonPrimitive) {
arguments.add(convert((JsonPrimitive) jsonElement));
} else {
throw new RuntimeException("Unsupported expression conversion for " + jsonElement.getClass());
}
}
return new Expression(operator, arguments.toArray(new Expression[arguments.size()]));
}
/**
* Converts a JsonPrimitive to an expression literal
*
* @param jsonPrimitive the json primitive to convert
* @return the expression literal
*/
private static Expression convert(@NonNull JsonPrimitive jsonPrimitive) {
if (jsonPrimitive.isBoolean()) {
return new Expression.ExpressionLiteral(jsonPrimitive.getAsBoolean());
} else if (jsonPrimitive.isNumber()) {
return new Expression.ExpressionLiteral(jsonPrimitive.getAsFloat());
} else if (jsonPrimitive.isString()) {
return new Expression.ExpressionLiteral(jsonPrimitive.getAsString());
} else {
throw new RuntimeException("Unsupported literal expression conversion for " + jsonPrimitive.getClass());
}
}
}
}

View File

@@ -1,50 +0,0 @@
package com.mapbox.mapboxsdk.style.functions;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
/**
* Camera function. Functions that take camera properties as input (zoom for now)
* <p>
* Zoom functions allow the appearance of a map feature to change with map&#x27;s zoom level.
* Zoom functions can be used to create the illusion of depth and control data density.
* Each stop is an array with two elements: the first is a zoom level and the second is
* a function output value.
*
* @param <I> the input type
* @param <O> the output type
* @see Function#zoom
*/
public class CameraFunction<I extends Number, O> extends Function<I, O> {
/**
* Create an exponential camera function
*
* @param stops @see {@link com.mapbox.mapboxsdk.style.functions.stops.Stops#exponential(float, Stop[])}
*/
CameraFunction(@NonNull ExponentialStops<I, O> stops) {
super(stops);
}
/**
* Create an interval camera function
*
* @param stops @see {@link com.mapbox.mapboxsdk.style.functions.stops.Stops#interval(Stop[])}
*/
CameraFunction(@NonNull IntervalStops<I, O> stops) {
super(stops);
}
/**
* JNI constructor
*/
@Keep
private CameraFunction(Stops<I, O> stops) {
super(stops);
}
}

View File

@@ -1,100 +0,0 @@
package com.mapbox.mapboxsdk.style.functions;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import java.util.Map;
/**
* Composite functions combine Camera and SourceFunctions.
* <p>
* Composite functions allow the appearance of a map feature to change with both its
* properties and zoom. Each stop is an array with two elements, the first is an object
* with a property input value and a zoom, and the second is a function output value. Note
* that support for property functions is not yet complete.
*
* @param <Z> the zoom type (usually Float)
* @param <I> the input type (the feature property type)
* @param <O> the output type (the property type)
* @see Function#composite
*/
public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.CompositeValue<Z, I>, O> {
private final String property;
private PropertyValue<O> defaultValue;
CompositeFunction(@NonNull String property,
@NonNull CategoricalStops<Stop.CompositeValue<Z, I>, O> stops) {
this(null, property, stops);
}
CompositeFunction(@NonNull String property,
@NonNull ExponentialStops<Stop.CompositeValue<Z, I>, O> stops) {
this(null, property, stops);
}
CompositeFunction(@NonNull String property,
@NonNull IntervalStops<Stop.CompositeValue<Z, I>, O> stops) {
this(null, property, stops);
}
/**
* JNI Constructor
*/
private CompositeFunction(@Nullable O defaultValue, @NonNull String property,
@NonNull Stops<Stop.CompositeValue<Z, I>, O> stops) {
super(stops);
this.defaultValue = new PropertyValue<>(property, defaultValue);
this.property = property;
}
/**
* Set the default value
*
* @param defaultValue the default value to use when no other applies
* @return this (for chaining)
*/
public CompositeFunction<Z, I, O> withDefaultValue(PropertyValue<O> defaultValue) {
this.defaultValue = defaultValue;
return this;
}
/**
* @return the defaultValue
*/
@Nullable
public PropertyValue<O> getDefaultValue() {
return defaultValue;
}
/**
* INTERNAL USAGE ONLY
*
* @return the feature property name
*/
public String getProperty() {
return property;
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> toValueObject() {
Map<String, Object> valueObject = super.toValueObject();
valueObject.put(PROPERTY_KEY, property);
if (defaultValue != null) {
valueObject.put(DEFAULT_VALUE_KEY, defaultValue.value);
}
return valueObject;
}
}

View File

@@ -1,300 +0,0 @@
package com.mapbox.mapboxsdk.style.functions;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import java.util.Map;
import timber.log.Timber;
/**
* Functions are used to change properties in relation to the state of the map.
* <p>
* The value for any layout or paint property may be specified as a function. Functions allow you to
* make the appearance of a map feature change with the current zoom level and/or the feature's properties.
*
* @param <I> the function's input type
* @param <O> the target property's value type. Make sure it matches.
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
*/
public class Function<I, O> {
static final String PROPERTY_KEY = "property";
static final String DEFAULT_VALUE_KEY = "default";
/**
* Create an exponential {@link CameraFunction}
* <p>
* Zoom functions allow the appearance of a map feature to change with map&#x27;s zoom.
* Zoom functions can be used to create the illusion of depth and control data density.
* Each stop is an array with two elements, the first is a zoom and the second is a function output value.
*
* @param <Z> the zoom level type (Float, Integer)
* @param <O> the property type
* @param stops the stops implementation that define the function. @see {@link Stops#exponential(Stop[])}
* @return the {@link CameraFunction}
* @see CameraFunction
* @see ExponentialStops
* @see Stops#exponential(Stop[])
* @see Stops#exponential(Stop[])
* @see Stop#stop
*/
public static <Z extends Number, O> CameraFunction<Z, O> zoom(@NonNull ExponentialStops<Z, O> stops) {
return new CameraFunction<>(stops);
}
/**
* Create an interval {@link CameraFunction}
* <p>
* Zoom functions allow the appearance of a map feature to change with map&#x2019;s zoom.
* Zoom functions can be used to create the illusion of depth and control data density.
* Each stop is an array with two elements, the first is a zoom and the second is a function output value.
*
* @param <Z> the zoom level type (Float, Integer)
* @param <O> the property type
* @param stops the stops implementation that define the function. @see {@link Stops#interval(Stop[])}
* @return the {@link CameraFunction}
* @see CameraFunction
* @see IntervalStops
* @see Stops#interval(Stop[])
* @see Stop#stop
*/
public static <Z extends Number, O> CameraFunction<Z, O> zoom(@NonNull IntervalStops<Z, O> stops) {
return new CameraFunction<>(stops);
}
/**
* Create an exponential {@link SourceFunction}
* <p>
* Source functions allow the appearance of a map feature to change with
* its properties. Source functions can be used to visually differentiate
* types of features within the same layer or create data visualizations.
* Each stop is an array with two elements, the first is a property input
* value and the second is a function output value. Note that support for
* property functions is not available across all properties and platforms
* at this time.
*
* @param property the feature property name
* @param stops the stops
* @param <I> the function input type
* @param <O> the function output type
* @return the {@link SourceFunction}
* @see SourceFunction
* @see ExponentialStops
* @see Stops#exponential(Stop[])
* @see Stop#stop
*/
public static <I, O> SourceFunction<I, O> property(@NonNull String property, @NonNull ExponentialStops<I, O> stops) {
return new SourceFunction<>(property, stops);
}
/**
* Create an identity {@link SourceFunction}
* <p>
* Source functions allow the appearance of a map feature to change with
* its properties. Source functions can be used to visually differentiate
* types of features within the same layer or create data visualizations.
* Each stop is an array with two elements, the first is a property input
* value and the second is a function output value. Note that support for
* property functions is not available across all properties and platforms
* at this time.
*
* @param property the feature property name
* @param stops the stops
* @param <T> the function input/output type
* @return the {@link SourceFunction}
* @see SourceFunction
* @see IdentityStops
* @see Stops#identity()
* @see Stop#stop
*/
public static <T> SourceFunction<T, T> property(@NonNull String property, @NonNull IdentityStops<T> stops) {
return new SourceFunction<>(property, stops);
}
/**
* Create an interval {@link SourceFunction}
* <p>
* Source functions allow the appearance of a map feature to change with
* its properties. Source functions can be used to visually differentiate
* types of features within the same layer or create data visualizations.
* Each stop is an array with two elements, the first is a property input
* value and the second is a function output value. Note that support for
* property functions is not available across all properties and platforms
* at this time.
*
* @param property the feature property name
* @param stops the stops
* @param <I> the function input type
* @param <O> the function output type
* @return the {@link SourceFunction}
* @see SourceFunction
* @see IntervalStops
* @see Stops#interval(Stop[])
* @see Stop#stop
*/
public static <I, O> SourceFunction<I, O> property(@NonNull String property, @NonNull IntervalStops<I, O> stops) {
return new SourceFunction<>(property, stops);
}
/**
* Create an categorical {@link SourceFunction}
* <p>
* Source functions allow the appearance of a map feature to change with
* its properties. Source functions can be used to visually differentiate
* types of features within the same layer or create data visualizations.
* Each stop is an array with two elements, the first is a property input
* value and the second is a function output value. Note that support for
* property functions is not available across all properties and platforms
* at this time.
*
* @param property the feature property name
* @param stops the stops
* @param <I> the function input type
* @param <O> the function output type
* @return the {@link SourceFunction}
* @see SourceFunction
* @see CategoricalStops
* @see Stops#categorical(Stop[])
* @see Stop#stop
*/
public static <I, O> SourceFunction<I, O> property(@NonNull String property, @NonNull CategoricalStops<I, O> stops) {
return new SourceFunction<>(property, stops);
}
/**
* Create a composite, categorical function.
* <p>
* Composite functions allow the appearance of a map feature to change with both its
* properties and zoom. Each stop is an array with two elements, the first is an object
* with a property input value and a zoom, and the second is a function output value. Note
* that support for property functions is not yet complete.
*
* @param property the feature property name for the source part of the function
* @param stops the stops
* @param <Z> the zoom function input type (Float usually)
* @param <I> the function input type for the source part of the function
* @param <O> the function output type
* @return the {@link CompositeFunction}
* @see CompositeFunction
* @see CategoricalStops
* @see Stops#categorical(Stop[])
* @see Stop#stop
*/
public static <Z extends Number, I, O> CompositeFunction<Z, I, O> composite(
@NonNull String property,
@NonNull CategoricalStops<Stop.CompositeValue<Z, I>, O> stops) {
return new CompositeFunction<>(property, stops);
}
/**
* Create a composite, exponential function.
* <p>
* Composite functions allow the appearance of a map feature to change with both its
* properties and zoom. Each stop is an array with two elements, the first is an object
* with a property input value and a zoom, and the second is a function output value. Note
* that support for property functions is not yet complete.
*
* @param property the feature property name for the source part of the function
* @param stops the stops
* @param <Z> the zoom function input type (Float usually)
* @param <I> the function input type for the source part of the function
* @param <O> the function output type
* @return the {@link CompositeFunction}
* @see CompositeFunction
* @see ExponentialStops
* @see Stops#exponential(Stop[])
* @see Stop#stop
*/
public static <Z extends Number, I, O> CompositeFunction<Z, I, O> composite(
@NonNull String property,
@NonNull ExponentialStops<Stop.CompositeValue<Z, I>, O> stops) {
return new CompositeFunction<>(property, stops);
}
/**
* Create a composite, interval function.
* <p>
* Composite functions allow the appearance of a map feature to change with both its
* properties and zoom. Each stop is an array with two elements, the first is an object
* with a property input value and a zoom, and the second is a function output value. Note
* that support for property functions is not yet complete.
*
* @param property the feature property name for the source part of the function
* @param stops the stops
* @param <Z> the zoom function input type (Float usually)
* @param <I> the function input type for the source part of the function
* @param <O> the function output type
* @return the {@link CompositeFunction}
* @see CompositeFunction
* @see IntervalStops
* @see Stops#interval(Stop[])
* @see Stop#stop
*/
public static <Z extends Number, I, O> CompositeFunction<Z, I, O> composite(
@NonNull String property,
@NonNull IntervalStops<Stop.CompositeValue<Z, I>, O> stops) {
return new CompositeFunction<>(property, stops);
}
// Class definition //
private final Stops<I, O> stops;
/**
* JNI Cosntructor for implementation classes
*
* @param stops the stops
*/
Function(@NonNull Stops<I, O> stops) {
this.stops = stops;
}
/**
* @return the stops in this function
*/
public Stops getStops() {
return stops;
}
/**
* Convenience method
*
* @param <S> the Stops implementation type
* @return the Stops implementation or null when the wrong type is specified
*/
@Nullable
public <S extends Stops> S getStopsAs() {
try {
// noinspection unchecked
return (S) stops;
} catch (ClassCastException exception) {
Timber.e(exception, "Stops: %s is a different type: ", stops.getClass());
return null;
}
}
/**
* INTERNAL USAGE ONLY
*
* @return a value object representation for core conversion
*/
public Map<String, Object> toValueObject() {
return stops.toValueObject();
}
@Override
public String toString() {
return String.format("%s: %s", getClass().getSimpleName(), stops);
}
}

View File

@@ -1,85 +0,0 @@
package com.mapbox.mapboxsdk.style.functions;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import java.util.Map;
/**
* Source functions take Feature property names as input.
* <p>
* Source functions allow the appearance of a map feature to change with
* its properties. Source functions can be used to visually differentiate
* types of features within the same layer or create data visualizations.
* Each stop is an array with two elements, the first is a property input
* value and the second is a function output value. Note that support for
* property functions is not available across all properties and platforms
* at this time.
*
* @param <I> the input type
* @param <O> the output type
* @see Function#property
*/
public class SourceFunction<I, O> extends Function<I, O> {
private final String property;
private PropertyValue<O> defaultValue;
SourceFunction(@NonNull String property, @NonNull Stops<I, O> stops) {
this(null, property, stops);
}
/**
* JNI Constructor
*/
private SourceFunction(@Nullable O defaultValue, @NonNull String property, @NonNull Stops<I, O> stops) {
super(stops);
this.property = property;
this.defaultValue = defaultValue != null ? new PropertyValue<>(property, defaultValue) : null;
}
/**
* INTERNAL USAGE ONLY
*
* @return The feature property name
*/
public String getProperty() {
return property;
}
/**
* Set the default value
*
* @param defaultValue the default value to use when no other applies
* @return this (for chaining)
*/
public SourceFunction<I, O> withDefaultValue(PropertyValue<O> defaultValue) {
this.defaultValue = defaultValue;
return this;
}
/**
* @return the defaultValue
*/
@Nullable
public PropertyValue<O> getDefaultValue() {
return defaultValue;
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> toValueObject() {
Map<String, Object> valueObject = super.toValueObject();
valueObject.put(PROPERTY_KEY, property);
if (defaultValue != null) {
valueObject.put(DEFAULT_VALUE_KEY, defaultValue.value);
}
return valueObject;
}
}

View File

@@ -1,6 +0,0 @@
/**
* Contains the Mapbox Maps Android Style Function API classes.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
*/
package com.mapbox.mapboxsdk.style.functions;

View File

@@ -1,64 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
/**
* {@link Stops} implementation for categorical functions
*
* @param <I> the {@link Stop} input type
* @param <O> the {@link Stop} output type
*/
public class CategoricalStops<I, O> extends IterableStops<I, O, Stop<I, O>> {
private final Stop<I, O>[] stops;
/**
* Create a categorical {@link Stops} implementation. Use through {@link Stops#categorical(Stop[])}
*
* @param stops the stops
*/
@SafeVarargs
public CategoricalStops(@NonNull @Size(min = 1) Stop<I, O>... stops) {
this.stops = stops;
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> toValueObject() {
Map<String, Object> map = super.toValueObject();
map.put("stops", toValueObjects(stops));
return map;
}
/**
* {@inheritDoc}
*/
@Override
public String getTypeName() {
return "categorical";
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<Stop<I, O>> iterator() {
return Arrays.asList(stops).iterator();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return stops.length;
}
}

View File

@@ -1,97 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
/**
* The {@link Stops} implementation for exponential functions
*
* @param <I> the input type
* @param <O> the output type
*/
public class ExponentialStops<I, O> extends IterableStops<I, O, Stop<I, O>> {
private float base;
private final Stop<I, O>[] stops;
/**
* Create exponential stops with an explicit base. Use through {@link Stops#exponential(Stop[])}
*
* @param base The exponential base of the interpolation curve. It controls the rate at which the function 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 stops the stops
*/
@SafeVarargs
public ExponentialStops(Float base, @NonNull @Size(min = 1) Stop<I, O>... stops) {
this.base = base != null ? base : 1.0f;
this.stops = stops;
}
/**
* Create exponential stops without an explicit base. Use through {@link Stops#exponential(Stop[])}
*
* @param stops the stops
*/
@SafeVarargs
public ExponentialStops(@NonNull @Size(min = 1) Stop<I, O>... stops) {
this(null, stops);
}
/**
* Set the exponential base
*
* @param base the base to use in the exponential function
* @return this (for chaining)
*/
public ExponentialStops<I, O> withBase(float base) {
this.base = base;
return this;
}
/**
* @return The exponential base
*/
public float getBase() {
return base;
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> toValueObject() {
Map<String, Object> map = super.toValueObject();
map.put("base", base);
map.put("stops", toValueObjects(stops));
return map;
}
/**
* {@inheritDoc}
*/
@Override
public String getTypeName() {
return "exponential";
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<Stop<I, O>> iterator() {
return Arrays.asList(stops).iterator();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return stops.length;
}
}

View File

@@ -1,18 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
/**
* The {@link Stops} implementation for identity functions
*
* @param <T> the input/output type
*/
public class IdentityStops<T> extends Stops<T, T> {
/**
* {@inheritDoc}
*/
@Override
protected String getTypeName() {
return "identity";
}
}

View File

@@ -1,58 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
/**
* The {@link Stops} implementation for interval functions
*
* @param <I> the input type
* @param <O> the output type
*/
public class IntervalStops<I, O> extends IterableStops<I, O, Stop<I, O>> {
private final Stop<I, O>[] stops;
@SafeVarargs
public IntervalStops(@NonNull @Size(min = 1) Stop<I, O>... stops) {
this.stops = stops;
}
/**
* {@inheritDoc}
*/
@Override
public String getTypeName() {
return "interval";
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> toValueObject() {
Map<String, Object> map = super.toValueObject();
map.put("stops", toValueObjects(stops));
return map;
}
/**
* @return an {@link Iterator} for the contained stops
*/
@Override
public Iterator<Stop<I, O>> iterator() {
return Arrays.asList(stops).iterator();
}
/**
* @return The number of contained stops
*/
@Override
public int size() {
return stops.length;
}
}

View File

@@ -1,52 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
import java.util.Iterator;
/**
* Base class for {@link Stops} implementations with a collection of stops
*
* @param <I> the {@link Stops} input type
* @param <O> the {@link Stops} output type
* @param <S> the {@link Iterable} element type (usually {@link Stop})
*/
public abstract class IterableStops<I, O, S> extends Stops<I, O> implements Iterable<S> {
/**
* @return The size of the contained stops collection
*/
public abstract int size();
/**
* Convenience function to toValueObjects an array of stops to an array of value objects
*
* @param stops the stops to toValueObjects
* @return the stops as value objects
*/
Object[] toValueObjects(Stop<I, O>[] stops) {
if (stops != null) {
Object[] stopsValue = new Object[stops.length];
for (int i = 0; i < stopsValue.length; i++) {
Stop stop = stops[i];
stopsValue[i] = stop.toValueObject();
}
return stopsValue;
}
return null;
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
Iterator<S> iterator = iterator();
while (iterator.hasNext()) {
S stop = iterator.next();
buffer.append(stop);
if (iterator.hasNext()) {
buffer.append(",");
}
}
return String.format("%s: [%s]", super.toString(), buffer.toString());
}
}

View File

@@ -1,109 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import java.util.HashMap;
import java.util.Map;
/**
* A stop represents a certain point in the range of this function
*
* @param <I> input the stop (function) input type
* @param <O> output the stop (function) output type
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
*/
public class Stop<I, O> {
/**
* Creates a {@link Stop} to use in a {@link Function}
*
* @param in the input for the stop
* @param output the output for the stop
* @param <I> the input property type
* @param <O> the output property type
* @return the {@link Stop}
*/
public static <I, O> Stop<I, O> stop(I in, PropertyValue<O> output) {
return new Stop<>(in, output.value);
}
/**
* Create a composite {@link Stop} for use in a {@link com.mapbox.mapboxsdk.style.functions.CompositeFunction}
*
* @param zoom the zoom input
* @param value the feature property input
* @param output the output for the stop
* @param <Z> the zoom type
* @param <I> the feature property input type
* @param <O> the output property type
* @return the {@link Stop}
* @see Function#composite(String, ExponentialStops)
*/
public static <Z extends Number, I, O> Stop<Stop.CompositeValue<Z, I>, O> stop(Z zoom,
I value,
PropertyValue<O> output) {
return new Stop<>(new Stop.CompositeValue<>(zoom, value), output.value);
}
/**
* Represents a composite input value for composite functions (eg zoom and feature property value)
*
* @param <Z> the zoom input type (typically Float)
* @param <V> the feature property input type
*/
public static class CompositeValue<Z extends Number, V> {
public final Z zoom;
public final V value;
CompositeValue(Z zoom, V value) {
this.zoom = zoom;
this.value = value;
}
/**
* INTERNAL USAGE ONLY
*
* @return the value object representation for core conversion
*/
Map<String, Object> toValueObject() {
HashMap<String, Object> map = new HashMap<>();
map.put("zoom", zoom);
map.put("value", value);
return map;
}
@Override
public String toString() {
return String.format("[zoom: %s, value: %s]", zoom, value);
}
}
/**
* The input type
*/
public final I in;
/**
* The output type
*/
public final O out;
Stop(I in, O out) {
this.in = in;
this.out = out;
}
/**
* INTERNAL USAGE ONLY
*
* @return an array representation of the Stop
*/
Object[] toValueObject() {
return new Object[] {in instanceof CompositeValue ? ((CompositeValue) in).toValueObject() : in, out};
}
@Override
public String toString() {
return String.format("[%s, %s]", in, out);
}
}

View File

@@ -1,99 +0,0 @@
package com.mapbox.mapboxsdk.style.functions.stops;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import java.util.HashMap;
import java.util.Map;
/**
* The base class for different stops implementations
*
* @param <I> the input type
* @param <O> the output type
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
*/
public abstract class Stops<I, O> {
/**
* Convenience method for use in function declarations
*
* @param stops the collections of discrete stops
* @param <I> the Stops input type
* @param <O> the Stops output type
* @return the {@link Stops} implementation
* @see Stop#stop
* @see CategoricalStops
*/
@SafeVarargs
public static <I, O> CategoricalStops<I, O> categorical(@NonNull @Size(min = 1) Stop<I, O>... stops) {
return new CategoricalStops<>(stops);
}
/**
* Convenience method for use in function declarations
*
* @param stops the collections of discrete stops
* @param <I> the Stops input type
* @param <O> the Stops output type
* @return the {@link Stops} implementation
* @see Stop#stop
* @see ExponentialStops
*/
@SafeVarargs
public static <I, O> ExponentialStops<I, O> exponential(@NonNull @Size(min = 1) Stop<I, O>... stops) {
return new ExponentialStops<>(stops);
}
/**
* Convenience method for use in function declarations
*
* @param <T> the Stops input/output type
* @return the {@link IdentityStops} implementation
* @see Stop#stop
* @see IdentityStops
*/
public static <T> IdentityStops<T> identity() {
return new IdentityStops<>();
}
/**
* Convenience method for use in function declarations
*
* @param stops the collections of discrete stops
* @param <I> the Stops input type
* @param <O> the Stops output type
* @return the {@link Stops} implementation
* @see Stop#stop
* @see IntervalStops
*/
@SafeVarargs
public static <I, O> IntervalStops<I, O> interval(@NonNull @Size(min = 1) Stop<I, O>... stops) {
return new IntervalStops<>(stops);
}
/**
* INTERNAL USAGE ONLY
*
* @return the value object representation for conversion to core
*/
@CallSuper
public Map<String, Object> toValueObject() {
HashMap<String, Object> map = new HashMap<>();
map.put("type", getTypeName());
return map;
}
/**
* INTERNAL USAGE ONLY
*
* @return the unique type name as a string according to the style specification
*/
protected abstract String getTypeName();
@Override
public String toString() {
return getTypeName();
}
}

View File

@@ -1,6 +0,0 @@
/**
* Contains the Mapbox Maps Android Style Function Stop implementation API classes.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
*/
package com.mapbox.mapboxsdk.style.functions.stops;

View File

@@ -3,7 +3,6 @@ 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;
/**
* Base class for the different Layer types
@@ -89,12 +88,8 @@ public abstract class Layer {
}
private Object convertValue(Object value) {
if (value != null) {
if (value instanceof Function) {
return ((Function) value).toValueObject();
} else if (value instanceof Expression) {
return ((Expression) value).toArray();
}
if (value != null && value instanceof Expression) {
return ((Expression) value).toArray();
}
return value;
}

View File

@@ -4,8 +4,9 @@ import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.gson.JsonArray;
import com.mapbox.mapboxsdk.exceptions.ConversionException;
import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.utils.ColorUtils;
import timber.log.Timber;
@@ -40,12 +41,27 @@ public class PropertyValue<T> {
}
/**
* Returns if this is a function.
* Returns if this is a expression.
*
* @return true if is a function, false if not
* @return true if this is a expression, false if not
*/
public boolean isFunction() {
return !isNull() && value instanceof Function;
public boolean isExpression() {
return !isNull() && value instanceof JsonArray;
}
/**
* Get the expression of the property.
*
* @return the property expression
*/
@Nullable
public Expression getExpression() {
if (isExpression()) {
return Expression.Converter.convert((JsonArray) value);
} else {
Timber.w("not a expression, try value");
return null;
}
}
/**
@@ -54,18 +70,7 @@ public class PropertyValue<T> {
* @return true if is a value, false if not
*/
public boolean isValue() {
return !isNull() && !isFunction();
}
@Nullable
public Function<?, T> getFunction() {
if (isFunction()) {
// noinspection unchecked
return (Function<?, T>) value;
} else {
Timber.w("not a function, try value");
return null;
}
return !isNull() && !isExpression();
}
/**
@@ -77,7 +82,7 @@ public class PropertyValue<T> {
public T getValue() {
if (isValue()) {
// noinspection unchecked
return (T) value;
return value;
} else {
Timber.w("not a value, try function");
return null;
@@ -114,4 +119,4 @@ public class PropertyValue<T> {
public String toString() {
return String.format("%s: %s", name, value);
}
}
}

View File

@@ -8,9 +8,7 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.functions.Function;
import java.util.Locale;
@@ -31,18 +29,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("visibility", value);
}
/**
* Set the property visibility.
*
* @param <T> the function input type
* @param function the visibility function
* @return property wrapper around a String function
*/
@Deprecated
public static <T> PropertyValue<Function<T, String>> visibility(Function<T, String> function) {
return new LayoutPropertyValue<>("visibility", function);
}
<% for (const property of paintProperties) { -%>
<% if (property.type == 'color') { -%>
/**
@@ -76,35 +62,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("<%- property.name %>", expression);
}
<% if (supportsPropertyFunction(property)) { -%>
/**
* <%- propertyFactoryMethodDoc(property) %>
*
* @param <T> the function input type
* @param function a wrapper function for <%- propertyType(property) %>
* @return property wrapper around a <%- propertyType(property) %> function
*/
@Deprecated
public static <T> PropertyValue<Function<T, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(Function<T, <%- propertyType(property) %>> function) {
return new PaintPropertyValue<>("<%- property.name %>", function);
}
<% } else if (supportsZoomFunction(property)) { -%>
/**
* <%- propertyFactoryMethodDoc(property) %>
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for <%- propertyType(property) %>
* @return property wrapper around a <%- propertyType(property) %> function
*/
@Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(CameraFunction<Z, <%- propertyType(property) %>> function) {
return new PaintPropertyValue<>("<%- property.name %>", function);
}
<% } -%>
<% } -%>
<% for (const property of layoutProperties) { -%>
/**
@@ -127,33 +84,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("<%- property.name %>", value);
}
<% if (supportsPropertyFunction(property)) { -%>
/**
* <%- propertyFactoryMethodDoc(property) %>
*
* @param <T> the function input type
* @param function a wrapper function for <%- propertyType(property) %>
* @return property wrapper around a <%- propertyType(property) %> function
*/
public static <T> PropertyValue<Function<T, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(Function<T, <%- propertyType(property) %>> function) {
return new LayoutPropertyValue<>("<%- property.name %>", function);
}
<% } else if (supportsZoomFunction(property)) { -%>
/**
* <%- propertyFactoryMethodDoc(property) %>
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for <%- propertyType(property) %>
* @return property wrapper around a <%- propertyType(property) %> function
*/
public static <Z extends Number> PropertyValue<CameraFunction<Z, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(CameraFunction<Z, <%- propertyType(property) %>> function) {
return new LayoutPropertyValue<>("<%- property.name %>", function);
}
<% } -%>
<% } -%>
public static String colorToRgbaString(@ColorInt int value) {
return String.format(Locale.US,"rgba(%d, %d, %d, %d)",