METRON-1168: Add SUBSTRING method to stellar this closes apache/incubator-metron#742
Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/7768ff67 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/7768ff67 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/7768ff67 Branch: refs/heads/Metron_0.4.1 Commit: 7768ff673cb4a7a62180d16fdb92dc0f4123f4f1 Parents: ea65a37 Author: cstella <[email protected]> Authored: Fri Sep 8 20:26:06 2017 -0400 Committer: cstella <[email protected]> Committed: Fri Sep 8 20:26:06 2017 -0400 ---------------------------------------------------------------------- metron-stellar/stellar-common/README.md | 47 ++++++++++++-------- .../stellar/dsl/functions/StringFunctions.java | 40 +++++++++++++++++ .../dsl/functions/StringFunctionsTest.java | 17 +++++++ 3 files changed, 85 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/7768ff67/metron-stellar/stellar-common/README.md ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/README.md b/metron-stellar/stellar-common/README.md index 340a7ae..a070c13 100644 --- a/metron-stellar/stellar-common/README.md +++ b/metron-stellar/stellar-common/README.md @@ -110,8 +110,8 @@ In the core language functions, we support basic functional programming primitiv | [ `BLOOM_EXISTS`](#bloom_exists) | | [ `BLOOM_INIT`](#bloom_init) | | [ `BLOOM_MERGE`](#bloom_merge) | -| [ `CEILING`](#ceiling) | -| [ `COS`](#cos) | +| [ `CEILING`](#ceiling) | +| [ `COS`](#cos) | | [ `CHOP`](#chop) | | [ `CHOMP`](#chomp) | | [ `COUNT_MATCHES`](#count_matches) | @@ -126,13 +126,13 @@ In the core language functions, we support basic functional programming primitiv | [ `ENDS_WITH`](#ends_with) | | [ `ENRICHMENT_EXISTS`](#enrichment_exists) | | [ `ENRICHMENT_GET`](#enrichment_get) | -| [ `EXP`](#exp) | +| [ `EXP`](#exp) | | [ `FILL_LEFT`](#fill_left) | | [ `FILL_RIGHT`](#fill_right) | | [ `FILTER`](#filter) | -| [ `FLOOR`](#floor) | -| [ `FUZZY_LANGS`](#fuzzy_langs) | -| [ `FUZZY_SCORE`](#fuzzy_score) | +| [ `FLOOR`](#floor) | +| [ `FUZZY_LANGS`](#fuzzy_langs) | +| [ `FUZZY_SCORE`](#fuzzy_score) | | [ `FORMAT`](#format) | | [ `GEO_GET`](#geo_get) | | [ `GEOHASH_CENTROID`](#geohash_centroid) | @@ -144,8 +144,8 @@ In the core language functions, we support basic functional programming primitiv | [ `GET`](#get) | | [ `GET_FIRST`](#get_first) | | [ `GET_LAST`](#get_last) | -| [ `GET_SUPPORTED_ENCODINGS`](#get_supported_encodings) | -| [ `HASH`](#hash) | +| [ `GET_SUPPORTED_ENCODINGS`](#get_supported_encodings) | +| [ `HASH`](#hash) | | [ `HLLP_CARDINALITY`](../../metron-analytics/metron-statistics#hllp_cardinality) | | [ `HLLP_INIT`](../../metron-analytics/metron-statistics#hllp_init) | | [ `HLLP_MERGE`](../../metron-analytics/metron-statistics#hllp_merge) | @@ -166,9 +166,9 @@ In the core language functions, we support basic functional programming primitiv | [ `KAFKA_TAIL`](#kafka_tail) | | [ `LENGTH`](#length) | | [ `LIST_ADD`](#list_add) | -| [ `LOG2`](#log2) | -| [ `LOG10`](#log10) | -| [ `LN`](#ln) | +| [ `LOG2`](#log2) | +| [ `LOG10`](#log10) | +| [ `LN`](#ln) | | [ `MAAS_GET_ENDPOINT`](#maas_get_endpoint) | | [ `MAAS_MODEL_APPLY`](#maas_model_apply) | | [ `MAP`](#map) | @@ -186,15 +186,15 @@ In the core language functions, we support basic functional programming primitiv | [ `PROTOCOL_TO_NAME`](#protocol_to_name) | | [ `REDUCE`](#reduce) | | [ `REGEXP_MATCH`](#regexp_match) | -| [ `REGEXP_GROUP_VAL`](#regexp_group_val) | -| [ `ROUND`](#round) | -| [ `SET_ADD`](#set_add) | +| [ `REGEXP_GROUP_VAL`](#regexp_group_val) | +| [ `ROUND`](#round) | +| [ `SET_ADD`](#set_add) | | [ `SET_INIT`](#set_init) | | [ `SET_MERGE`](#set_merge) | | [ `SET_REMOVE`](#set_remove) | | [ `SPLIT`](#split) | -| [ `SIN`](#sin) | -| [ `SQRT`](#sqrt) | +| [ `SIN`](#sin) | +| [ `SQRT`](#sqrt) | | [ `STARTS_WITH`](#starts_with) | | [ `STATS_ADD`](../../metron-analytics/metron-statistics#stats_add) | | [ `STATS_BIN`](../../metron-analytics/metron-statistics#stats_bin) | @@ -216,9 +216,10 @@ In the core language functions, we support basic functional programming primitiv | [ `STATS_SUM_SQUARES`](../../metron-analytics/metron-statistics#stats_sum_squares) | | [ `STATS_VARIANCE`](../../metron-analytics/metron-statistics#stats_variance) | | [ `STRING_ENTROPY`](#string_entropy) | +| [ `SUBSTRING`](#substring) | | [ `SYSTEM_ENV_GET`](#system_env_get) | | [ `SYSTEM_PROPERTY_GET`](#system_property_get) | -| [ `TAN`](#tan) | +| [ `TAN`](#tan) | | [ `TO_DOUBLE`](#to_double) | | [ `TO_EPOCH_TIMESTAMP`](#to_epoch_timestamp) | | [ `TO_FLOAT`](#to_float) | @@ -235,8 +236,8 @@ In the core language functions, we support basic functional programming primitiv | [ `WEEK_OF_MONTH`](#week_of_month) | | [ `WEEK_OF_YEAR`](#week_of_year) | | [ `YEAR`](#year) | -| [ `ZIP`](#zip) | -| [ `ZIP_JAGGED`](#zip_jagged) | +| [ `ZIP`](#zip) | +| [ `ZIP_JAGGED`](#zip_jagged) | ### `APPEND_IF_MISSING` * Description: Appends the suffix to the end of the string if the string does not already end with any of the suffixes. @@ -869,6 +870,14 @@ In the core language functions, we support basic functional programming primitiv * key - Property to get the value for * Returns: String +### `SUBSTRING` + * Description: Returns the substring of a string + * Input: + * input - The string to take the substring of + * start - The starting position (`0`-based and inclusive) + * end? - The ending position (`0`-based and exclusive) + * Returns: The substring of the input + ### `TAN` * Description: Returns the tangent of a number. * Input: http://git-wip-us.apache.org/repos/asf/metron/blob/7768ff67/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/StringFunctions.java ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/StringFunctions.java b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/StringFunctions.java index 289fa7f..99c8fe7 100644 --- a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/StringFunctions.java +++ b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/StringFunctions.java @@ -321,6 +321,46 @@ public class StringFunctions { } } + @Stellar( name="SUBSTRING" + , description = "Returns a substring of a string" + , params = { + "input - The string to take the substring of", + "start - The starting position (0-based and inclusive)", + "end? - The ending position (0-based and exclusive)" + } + , returns = "The substring of the input" + ) + public static class Substring extends BaseStellarFunction { + + @Override + public Object apply(List<Object> strings) { + + if(strings == null || strings.size() < 2 ) { + throw new IllegalArgumentException("[SUBSTRING] required 2 arguments: the input and the start position (inclusive)"); + } + String var = strings.get(0) == null?null: (String) strings.get(0); + Integer start = strings.get(1) == null?null:(Integer)strings.get(1); + Integer end = null; + if(strings.size() > 2) { + end = strings.get(2) == null ? null : (Integer) strings.get(2); + } + if(var == null || start == null) { + return null; + } + else if(var.length() == 0) { + return var; + } + else { + if(end == null) { + return var.substring(start); + } + else { + return var.substring(start, end); + } + } + } + } + @Stellar( name="CHOMP" , description = "Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is \"\\n\", \"\\r\", or \"\\r\\n\"" , params = { "the String to chomp a newline from, may be null"} http://git-wip-us.apache.org/repos/asf/metron/blob/7768ff67/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java index 858a043..2b1115e 100644 --- a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java +++ b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java @@ -408,6 +408,23 @@ public class StringFunctionsTest { } + @Test + public void testSubstring() throws Exception { + Map<String, Object> variables = ImmutableMap.of("s", "apache metron"); + Assert.assertEquals("metron", run("SUBSTRING(s, 7)", variables)); + Assert.assertEquals("me", run("SUBSTRING(s, 7, 9)", variables)); + Assert.assertNull(run("SUBSTRING(null, 7, 9)", new HashMap<>())); + Assert.assertNull(run("SUBSTRING(null, null, 9)", new HashMap<>())); + Assert.assertNull(run("SUBSTRING(s, null, 9)", variables)); + Assert.assertNull(run("SUBSTRING(null, null, null)", new HashMap<>())); + Assert.assertEquals("metron", run("SUBSTRING(s, 7, null)", variables)); + } + + @Test(expected=ParseException.class) + public void testSubstring_invalidEmpty() throws Exception { + Assert.assertEquals("metron", (String) run("SUBSTRING()", new HashMap<>())); + } + /** * COUNT_MATCHES StringFunction */
