[android] "collator" and "resolved-locale" expressions support

This commit is contained in:
Łukasz Paczos
2018-08-20 19:38:16 +02:00
committed by Łukasz Paczos
parent 67f6891ea7
commit 87f73bb0a2
3 changed files with 702 additions and 36 deletions

View File

@@ -4,17 +4,22 @@ import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* The value for any layout property, paint property, or filter may be specified as an expression.
@@ -345,7 +350,8 @@ public class Expression {
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-rgba">Style specification</a>
*/
public static Expression rgba(@NonNull Number red, @NonNull Number green, @NonNull Number blue, @NonNull Number alpha) {
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));
}
@@ -384,6 +390,32 @@ public class Expression {
return new Expression("==", compareOne, compareTwo);
}
/**
* Returns true if the input values are equal, false otherwise.
* The inputs must be numbers, strings, or booleans, and both of the same type.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* eq(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-==">Style specification</a>
*/
public static Expression eq(@NonNull Expression compareOne, @NonNull Expression compareTwo,
@NonNull Expression collator) {
return new Expression("==", compareOne, compareTwo, collator);
}
/**
* Returns true if the input values are equal, false otherwise.
* <p>
@@ -430,6 +462,32 @@ public class Expression {
return eq(compareOne, literal(compareTwo));
}
/**
* Returns true if the input values are equal, false otherwise.
* The inputs must be numbers, strings, or booleans, and both of the same type.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* eq(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second String
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-==">Style specification</a>
*/
public static Expression eq(@NonNull Expression compareOne, @NonNull String compareTwo,
@NonNull Expression collator) {
return eq(compareOne, literal(compareTwo), collator);
}
/**
* Returns true if the input values are equal, false otherwise.
* <p>
@@ -477,6 +535,32 @@ public class Expression {
return new Expression("!=", compareOne, 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* neq(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!=">Style specification</a>
*/
public static Expression neq(@NonNull Expression compareOne, @NonNull Expression compareTwo,
@NonNull Expression collator) {
return new Expression("!=", compareOne, compareTwo, collator);
}
/**
* Returns true if the input values are equal, false otherwise.
* <p>
@@ -523,6 +607,32 @@ public class Expression {
return new Expression("!=", 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* neq(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second String
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!=">Style specification</a>
*/
public static Expression neq(@NonNull Expression compareOne, @NonNull String compareTwo,
@NonNull Expression collator) {
return new Expression("!=", compareOne, literal(compareTwo), collator);
}
/**
* Returns `true` if the input values are not equal, `false` otherwise.
* <p>
@@ -570,6 +680,32 @@ public class Expression {
return new Expression(">", compareOne, 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* gt(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E">Style specification</a>
*/
public static Expression gt(@NonNull Expression compareOne, @NonNull Expression compareTwo,
@NonNull Expression collator) {
return new Expression(">", compareOne, compareTwo, collator);
}
/**
* Returns true if the first input is strictly greater than the second, false otherwise.
* <p>
@@ -616,6 +752,32 @@ public class Expression {
return new Expression(">", 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* gt(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second String
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E">Style specification</a>
*/
public static Expression gt(@NonNull Expression compareOne, @NonNull String compareTwo,
@NonNull Expression collator) {
return new Expression(">", compareOne, literal(compareTwo), collator);
}
/**
* 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.
@@ -626,18 +788,44 @@ public class Expression {
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* lt(get("keyToValue"), get("keyToOtherValue"))
* lt(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a>
*/
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.
* The inputs must be numbers or strings, and both of the same type.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* lt(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second number
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a>
*/
public static Expression lt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
return new Expression("<", compareOne, compareTwo);
public static Expression lt(@NonNull Expression compareOne, @NonNull Expression compareTwo,
@NonNull Expression collator) {
return new Expression("<", compareOne, compareTwo, collator);
}
/**
@@ -686,6 +874,32 @@ public class Expression {
return new Expression("<", 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* lt(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second String
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a>
*/
public static Expression lt(@NonNull Expression compareOne, @NonNull String compareTwo,
@NonNull Expression collator) {
return new Expression("<", compareOne, literal(compareTwo), collator);
}
/**
* 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.
@@ -710,6 +924,32 @@ public class Expression {
return new Expression(">=", compareOne, 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* gte(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E%3D">Style specification</a>
*/
public static Expression gte(@NonNull Expression compareOne, @NonNull Expression compareTwo,
@NonNull Expression collator) {
return new Expression(">=", compareOne, compareTwo, collator);
}
/**
* Returns true if the first input is greater than or equal to the second, false otherwise.
* <p>
@@ -756,6 +996,32 @@ public class Expression {
return new Expression(">=", 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* gte(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second String
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E%3D">Style specification</a>
*/
public static Expression gte(@NonNull Expression compareOne, @NonNull String compareTwo,
@NonNull Expression collator) {
return new Expression(">=", compareOne, literal(compareTwo), collator);
}
/**
* 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.
@@ -780,6 +1046,32 @@ public class Expression {
return new Expression("<=", compareOne, 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* lte(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C%3D">Style specification</a>
*/
public static Expression lte(@NonNull Expression compareOne, @NonNull Expression compareTwo,
@NonNull Expression collator) {
return new Expression("<=", compareOne, compareTwo, collator);
}
/**
* Returns true if the first input is less than or equal to the second, false otherwise.
* <p>
@@ -826,6 +1118,32 @@ public class Expression {
return new Expression("<=", 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.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* FillLayer fillLayer = new FillLayer("layer-id", "source-id");
* fillLayer.setFilter(
* lte(get("keyToValue"), get("keyToOtherValue"), collator(true, false))
* );
* }
* </pre>
*
* @param compareOne the first expression
* @param compareTwo the second String
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C%3D">Style specification</a>
*/
public static Expression lte(@NonNull Expression compareOne, @NonNull String compareTwo,
@NonNull Expression collator) {
return new Expression("<=", compareOne, literal(compareTwo), collator);
}
/**
* Returns `true` if all the inputs are `true`, `false` otherwise.
* <p>
@@ -2478,6 +2796,32 @@ public class Expression {
return floor(literal(number));
}
/**
* Returns the IETF language tag of the locale being used by the provided collator.
* This can be used to determine the default system locale,
* or to determine if a requested locale was successfully loaded.
* <p>
* Example usage:
* </p>
* <pre>
* {@code
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
* circleLayer.setProperties(
* circleColor(switchCase(
eq(literal("it"), resolvedLocale(collator(true, true, "it"))), literal(ColorUtils.colorToRgbaString(Color.GREEN)),
literal(ColorUtils.colorToRgbaString(Color.RED))))
* );
* }
* </pre>
*
* @param collator the collator expression
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-resolved-locale">Style specification</a>
*/
public static Expression resolvedLocale(Expression collator) {
return new Expression("resolved-locale", collator);
}
/**
* Returns the input string converted to uppercase.
* <p>
@@ -2696,6 +3040,104 @@ public class Expression {
return new Expression("boolean", input);
}
/**
* Returns a collator for use in locale-dependent comparison operations.
* The case-sensitive and diacritic-sensitive options default to false.
* The locale argument specifies the IETF language tag of the locale to use.
* If none is provided, the default locale is used. If the requested locale is not available,
* the collator will use a system-defined fallback locale.
* Use resolved-locale to test the results of locale fallback behavior.
*
* @param caseSensitive case sensitive flag
* @param diacriticSensitive diacritic sensitive flag
* @param locale locale
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-collator">Style specification</a>
*/
public static Expression collator(boolean caseSensitive, boolean diacriticSensitive, Locale locale) {
Map<String, Expression> map = new HashMap<>();
map.put("case-sensitive", literal(caseSensitive));
map.put("diacritic-sensitive", literal(diacriticSensitive));
StringBuilder localeStringBuilder = new StringBuilder();
String language = locale.getLanguage();
if (language != null && !language.isEmpty()) {
localeStringBuilder.append(language);
}
String country = locale.getCountry();
if (country != null && !country.isEmpty()) {
localeStringBuilder.append("-");
localeStringBuilder.append(country);
}
map.put("locale", literal(localeStringBuilder.toString()));
return new Expression("collator", new ExpressionMap(map));
}
/**
* Returns a collator for use in locale-dependent comparison operations.
* The case-sensitive and diacritic-sensitive options default to false.
* The locale argument specifies the IETF language tag of the locale to use.
* If none is provided, the default locale is used. If the requested locale is not available,
* the collator will use a system-defined fallback locale.
* Use resolved-locale to test the results of locale fallback behavior.
*
* @param caseSensitive case sensitive flag
* @param diacriticSensitive diacritic sensitive flag
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-collator">Style specification</a>
*/
public static Expression collator(boolean caseSensitive, boolean diacriticSensitive) {
Map<String, Expression> map = new HashMap<>();
map.put("case-sensitive", literal(caseSensitive));
map.put("diacritic-sensitive", literal(diacriticSensitive));
return new Expression("collator", new ExpressionMap(map));
}
/**
* Returns a collator for use in locale-dependent comparison operations.
* The case-sensitive and diacritic-sensitive options default to false.
* The locale argument specifies the IETF language tag of the locale to use.
* If none is provided, the default locale is used. If the requested locale is not available,
* the collator will use a system-defined fallback locale.
* Use resolved-locale to test the results of locale fallback behavior.
*
* @param caseSensitive case sensitive flag
* @param diacriticSensitive diacritic sensitive flag
* @param locale locale
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-collator">Style specification</a>
*/
public static Expression collator(Expression caseSensitive, Expression diacriticSensitive, Expression locale) {
Map<String, Expression> map = new HashMap<>();
map.put("case-sensitive", caseSensitive);
map.put("diacritic-sensitive", diacriticSensitive);
map.put("locale", locale);
return new Expression("collator", new ExpressionMap(map));
}
/**
* Returns a collator for use in locale-dependent comparison operations.
* The case-sensitive and diacritic-sensitive options default to false.
* The locale argument specifies the IETF language tag of the locale to use.
* If none is provided, the default locale is used. If the requested locale is not available,
* the collator will use a system-defined fallback locale.
* Use resolved-locale to test the results of locale fallback behavior.
*
* @param caseSensitive case sensitive flag
* @param diacriticSensitive diacritic sensitive flag
* @return expression
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-collator">Style specification</a>
*/
public static Expression collator(Expression caseSensitive, Expression diacriticSensitive) {
Map<String, Expression> map = new HashMap<>();
map.put("case-sensitive", caseSensitive);
map.put("diacritic-sensitive", diacriticSensitive);
return new Expression("collator", new ExpressionMap(map));
}
/**
* Asserts that the input value is an object. If it is not, the expression is an error
* The asserted input value is returned as result.
@@ -3422,8 +3864,8 @@ public class Expression {
array.add(operator);
if (arguments != null) {
for (Expression argument : arguments) {
if (argument instanceof Expression.ExpressionLiteral) {
array.add(toValue((ExpressionLiteral) argument));
if (argument instanceof ValueExpression) {
array.add(((ValueExpression) argument).toValue());
} else {
array.add(argument.toArray());
}
@@ -3432,22 +3874,6 @@ public class Expression {
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 PropertyValue) {
throw new IllegalArgumentException("PropertyValue are not allowed as an expression literal, use value instead.");
} else if (value instanceof Expression.ExpressionLiteral) {
return toValue((ExpressionLiteral) value);
}
return value;
}
/**
* Returns a string representation of the object that matches the definition set in the style specification.
* <p>
@@ -3549,7 +3975,7 @@ public class Expression {
* {@link #literal(String)} and {@link #literal(Object)}.
* </p>
*/
public static class ExpressionLiteral extends Expression {
public static class ExpressionLiteral extends Expression implements ValueExpression {
protected Object literal;
@@ -3572,7 +3998,14 @@ public class Expression {
*
* @return the literal object
*/
Object toValue() {
@Override
public Object toValue() {
if (literal instanceof PropertyValue) {
throw new IllegalArgumentException(
"PropertyValue are not allowed as an expression literal, use value instead.");
} else if (literal instanceof Expression.ExpressionLiteral) {
return ((ExpressionLiteral) literal).toValue();
}
return literal;
}
@@ -3589,7 +4022,13 @@ public class Expression {
*/
@Override
public String toString() {
return literal.toString();
String string;
if (literal instanceof String) {
string = "\"" + literal + "\"";
} else {
string = literal.toString();
}
return string;
}
/**
@@ -3627,7 +4066,7 @@ public class Expression {
return result;
}
private String unwrapStringLiteral(String value) {
private static String unwrapStringLiteral(String value) {
if (value.length() > 1 &&
value.charAt(0) == '\"' && value.charAt(value.length() - 1) == '\"') {
return value.substring(1, value.length() - 1);
@@ -3727,19 +4166,35 @@ public class Expression {
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 if (jsonElement instanceof JsonNull) {
arguments.add(new Expression.ExpressionLiteral(""));
} else {
throw new RuntimeException("Unsupported expression conversion for " + jsonElement.getClass());
}
arguments.add(convert(jsonElement));
}
return new Expression(operator, arguments.toArray(new Expression[arguments.size()]));
}
/**
* Converts a JsonElement to an expression
*
* @param jsonElement the json element to convert
* @return the expression
*/
private static Expression convert(@NonNull JsonElement jsonElement) {
if (jsonElement instanceof JsonArray) {
return convert((JsonArray) jsonElement);
} else if (jsonElement instanceof JsonPrimitive) {
return convert((JsonPrimitive) jsonElement);
} else if (jsonElement instanceof JsonNull) {
return new Expression.ExpressionLiteral("");
} else if (jsonElement instanceof JsonObject) {
Map<String, Expression> map = new HashMap<>();
for (String key : ((JsonObject) jsonElement).keySet()) {
map.put(key, convert(((JsonObject) jsonElement).get(key)));
}
return new ExpressionMap(map);
} else {
throw new RuntimeException("Unsupported expression conversion for " + jsonElement.getClass());
}
}
/**
* Converts a JsonPrimitive to an expression literal
*
@@ -3815,6 +4270,79 @@ public class Expression {
}
}
/**
* Wraps an expression value stored in a Map.
*/
private static class ExpressionMap extends Expression implements ValueExpression {
private Map<String, Expression> map;
ExpressionMap(Map<String, Expression> map) {
this.map = map;
}
@Override
public Object toValue() {
Map<String, Object> unwrappedMap = new HashMap<>();
for (String key : map.keySet()) {
Expression expression = map.get(key);
if (expression instanceof Expression.ExpressionLiteral) {
unwrappedMap.put(key, ((ExpressionLiteral) expression).toValue());
} else {
unwrappedMap.put(key, expression.toArray());
}
}
return unwrappedMap;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("{");
for (String key : map.keySet()) {
builder.append("\"").append(key).append("\": ");
builder.append(map.get(key));
builder.append(", ");
}
if (map.size() > 0) {
builder.delete(builder.length() - 2, builder.length());
}
builder.append("}");
return builder.toString();
}
@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;
}
ExpressionMap that = (ExpressionMap) o;
return map.equals(that.map);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (map == null ? 0 : map.hashCode());
return result;
}
}
/**
* Interface used to describe expressions that hold a Java value.
*/
private interface ValueExpression {
Object toValue();
}
/**
* Converts an object that is a primitive array to an Object[]
*

View File

@@ -1,12 +1,16 @@
package com.mapbox.mapboxsdk.style.expressions;
import android.graphics.Color;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import static com.mapbox.mapboxsdk.style.expressions.Expression.abs;
import static com.mapbox.mapboxsdk.style.expressions.Expression.acos;
@@ -19,6 +23,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.atan;
import static com.mapbox.mapboxsdk.style.expressions.Expression.bool;
import static com.mapbox.mapboxsdk.style.expressions.Expression.ceil;
import static com.mapbox.mapboxsdk.style.expressions.Expression.coalesce;
import static com.mapbox.mapboxsdk.style.expressions.Expression.collator;
import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
import static com.mapbox.mapboxsdk.style.expressions.Expression.cos;
@@ -60,6 +65,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.pow;
import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
import static com.mapbox.mapboxsdk.style.expressions.Expression.properties;
import static com.mapbox.mapboxsdk.style.expressions.Expression.raw;
import static com.mapbox.mapboxsdk.style.expressions.Expression.resolvedLocale;
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
import static com.mapbox.mapboxsdk.style.expressions.Expression.round;
@@ -1290,4 +1296,75 @@ public class ExpressionTest {
String alpha = color.substring(0, color.length() - 1);
assertEquals("alpha value should match", 0.254f, Float.valueOf(alpha), 0.001f);
}
@Test
public void testCollator() {
Object[] expected = new Object[] {"collator",
new HashMap<String, Object>() {
{
put("case-sensitive", true);
put("diacritic-sensitive", true);
put("locale", "it-IT");
}
}
};
Object[] actual = collator(true, true, Locale.ITALY).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@Test
public void testStringCollator() {
String expected = "[\"collator\", {\"diacritic-sensitive\": true, \"case-sensitive\": true, \"locale\": "
+ "\"it\"}]";
String actual = collator(true, true, Locale.ITALIAN).toString();
assertEquals("expression should match", expected, actual);
}
@Test
public void testResolvedLocale() {
Object[] expected = new Object[] {"resolved-locale",
new Object[] {"collator",
new HashMap<String, Object>() {
{
put("case-sensitive", false);
put("diacritic-sensitive", false);
put("locale", "it");
}
}
}
};
Object[] actual = resolvedLocale(collator(false, false, Locale.ITALIAN)).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@Test
public void testRawCollator() {
Object[] expected = new Object[] {"collator",
new HashMap<String, Object>() {
{
put("case-sensitive", true);
put("diacritic-sensitive", true);
put("locale", "it-IT");
}
}
};
Object[] actual = raw("[\"collator\", {\"diacritic-sensitive\": true, \"case-sensitive\": true, \"locale\": "
+ "\"it-IT\"}]").toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@Test
public void testRawCollatorDoubleConversion() {
Expression expected = collator(false, false, Locale.ITALIAN);
Object[] actual = raw(expected.toString()).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected.toArray(), actual));
}
@Test
public void testStringNestedCollator() {
String expected = "[\"collator\", {\"diacritic-sensitive\": [\"==\", 2.0, 1.0], \"case-sensitive\": false,"
+ " \"locale\": \"it\"}]";
String actual = collator(literal(false), eq(literal(2), literal(1)), literal("it")).toString();
assertEquals("expression should match", expected, actual);
}
}

View File

@@ -2,20 +2,30 @@ package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.runner.AndroidJUnit4;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
import com.mapbox.mapboxsdk.utils.ColorUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import timber.log.Timber;
import java.io.IOException;
import timber.log.Timber;
import static com.mapbox.mapboxsdk.style.expressions.Expression.collator;
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
@@ -26,13 +36,16 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
import static com.mapbox.mapboxsdk.style.expressions.Expression.string;
import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase;
import static com.mapbox.mapboxsdk.style.expressions.Expression.toColor;
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillAntialias;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOutlineColor;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@RunWith(AndroidJUnit4.class)
public class ExpressionTest extends BaseActivityTest {
@@ -204,6 +217,54 @@ public class ExpressionTest extends BaseActivityTest {
});
}
@Test
public void testCollatorExpression() {
validateTestSetup();
setupStyle();
invoke(mapboxMap, (uiController, mapboxMap) -> {
LatLng latLng = new LatLng(51, 17);
Expression expression1 = eq(literal("Łukasz"), literal("lukasz"), collator(true, true));
Expression expression2 = eq(literal("Łukasz"), literal("lukasz"), collator(literal(false), eq(literal(1),
literal(1)), literal("en")));
Expression expression3 = eq(literal("Łukasz"), literal("lukasz"), collator(literal(false), eq(literal(2),
literal(1))));
mapboxMap.addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
Layer layer = new CircleLayer("layer", "source")
.withProperties(circleColor(
switchCase(
expression1, literal(ColorUtils.colorToRgbaString(Color.GREEN)),
literal(ColorUtils.colorToRgbaString(Color.RED))
)
));
mapboxMap.addLayer(layer);
uiController.loopMainThreadForAtLeast(1000);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
layer.setProperties(circleColor(
switchCase(
expression2, literal(ColorUtils.colorToRgbaString(Color.GREEN)),
literal(ColorUtils.colorToRgbaString(Color.RED))
)
));
uiController.loopMainThreadForAtLeast(1000);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
layer.setProperties(circleColor(
switchCase(
expression3, literal(ColorUtils.colorToRgbaString(Color.GREEN)),
literal(ColorUtils.colorToRgbaString(Color.RED))
)
));
uiController.loopMainThreadForAtLeast(1000);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
});
}
private void setupStyle() {
invoke(mapboxMap, (uiController, mapboxMap) -> {
// Add a source