diff options
author | Łukasz Paczos <lukas.paczos@gmail.com> | 2018-08-20 19:38:16 +0200 |
---|---|---|
committer | Łukasz Paczos <lukasz.paczos@mapbox.com> | 2018-08-22 11:06:59 +0200 |
commit | 87f73bb0a2ec0bc2d9830c17a754dde66b0f113a (patch) | |
tree | d1f052821430e00134aaac23dcedf4fbf63782de /platform/android/MapboxGLAndroidSDK | |
parent | 67f6891ea7ebe0360458c13ff20fa83648a3bc66 (diff) | |
download | qtlocation-mapboxgl-87f73bb0a2ec0bc2d9830c17a754dde66b0f113a.tar.gz |
[android] "collator" and "resolved-locale" expressions support
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK')
2 files changed, 639 insertions, 34 deletions
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 index 1aa0ce9093..bd4d5d7d4b 100644 --- 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 @@ -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)); } @@ -386,6 +392,32 @@ public class Expression { /** * 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> * Example usage: * </p> @@ -432,6 +464,32 @@ public class Expression { /** * 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> * Example usage: * </p> @@ -478,6 +536,32 @@ public class Expression { } /** + * 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> * Example usage: @@ -524,6 +608,32 @@ public class Expression { } /** + * 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> * Example usage: @@ -572,6 +682,32 @@ public class Expression { /** * 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> * Example usage: * </p> @@ -617,6 +753,32 @@ public class Expression { } /** + * 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. * <p> @@ -626,13 +788,13 @@ 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 number + * @param compareTwo the second expression * @return expression * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a> */ @@ -642,6 +804,32 @@ public class Expression { /** * 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, + @NonNull Expression collator) { + return new Expression("<", compareOne, compareTwo, collator); + } + + /** + * Returns true if the first input is strictly less than the second, false otherwise. * <p> * Example usage: * </p> @@ -687,6 +875,32 @@ public class Expression { } /** + * 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. * <p> @@ -712,6 +926,32 @@ public class Expression { /** * 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> * Example usage: * </p> @@ -757,6 +997,32 @@ public class Expression { } /** + * 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. * <p> @@ -782,6 +1048,32 @@ public class Expression { /** * 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> * Example usage: * </p> @@ -827,6 +1119,32 @@ public class Expression { } /** + * 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> * The inputs are evaluated in order, and evaluation is short-circuiting: @@ -2479,6 +2797,32 @@ public class Expression { } /** + * 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> * Follows the Unicode Default Case Conversion algorithm @@ -2697,6 +3041,104 @@ public class Expression { } /** + * 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()); } @@ -3433,22 +3875,6 @@ public class Expression { } /** - * 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> * If this expression contains a coma (,) delimited literal, like 'rgba(r, g, b, a)`, @@ -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,20 +4166,36 @@ 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 * * @param jsonPrimitive the json primitive to convert @@ -3816,6 +4271,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[] * * @param object the object to convert to an object array diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java index fb74904f96..79bcdd7b5e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java @@ -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); + } }
\ No newline at end of file |