From 5b1fad7ecc73f2e7a44ba644812eb1f008e82853 Mon Sep 17 00:00:00 2001 From: Nick Allen Date: Thu, 2 Feb 2017 11:42:13 -0500 Subject: [PATCH 1/2] METRON-687 Create String Formatting Function for Stellar --- metron-platform/metron-common/README.md | 8 +++++ .../common/dsl/functions/StringFunctions.java | 21 +++++++++++ .../dsl/functions/StringFunctionsTest.java | 35 +++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/metron-platform/metron-common/README.md b/metron-platform/metron-common/README.md index ace1a0c9a2..46837d96bb 100644 --- a/metron-platform/metron-common/README.md +++ b/metron-platform/metron-common/README.md @@ -96,6 +96,7 @@ The `!=` operator is the negation of the above. | [ `ENRICHMENT_GET`](#enrichment_get) | | [ `FILL_LEFT`](#fill_left) | | [ `FILL_RIGHT`](#fill_right) | +| [ `FORMAT`](#format) | | [ `HLLP_CARDINALITY`](../../metron-analytics/metron-statistics#hllp_cardinality) | | [ `HLLP_INIT`](../../metron-analytics/metron-statistics#hllp_init) | | [ `HLLP_MERGE`](../../metron-analytics/metron-statistics#hllp_merge) | @@ -270,6 +271,13 @@ The `!=` operator is the negation of the above. * len - the required length * Returns: Last element of the list +### `FORMAT` + * Description: Returns a formatted string using the specified format string and arguments. + * Input: + * format - string + * arguments... - object(s) + * Returns: A formatted string. + ### `GEO_GET` * Description: Look up an IPV4 address and returns geographic information about it * Input: diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/StringFunctions.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/StringFunctions.java index fa2b55b855..1086da3f98 100644 --- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/StringFunctions.java +++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/StringFunctions.java @@ -322,4 +322,25 @@ public Object apply(List strings) { return ret; } } + + @Stellar( name="FORMAT" + , description = "Returns a formatted string using the specified format string and arguments. Uses Java's string formatting conventions." + , params = { "format - string", "arguments... - object(s)" } + , returns = "A formatted string." + ) + public static class Format extends BaseStellarFunction { + + @Override + public Object apply(List args) { + + if(args.size() == 0) { + throw new IllegalArgumentException("[FORMAT] missing argument: format string"); + } + + String format = ConversionUtils.convert(args.get(0), String.class); + Object[] formatArgs = args.subList(1, args.size()).toArray(); + + return String.format(format, formatArgs); + } + } } diff --git a/metron-platform/metron-common/src/test/java/org/apache/metron/common/dsl/functions/StringFunctionsTest.java b/metron-platform/metron-common/src/test/java/org/apache/metron/common/dsl/functions/StringFunctionsTest.java index 18d2eb2e8d..d8854f820c 100644 --- a/metron-platform/metron-common/src/test/java/org/apache/metron/common/dsl/functions/StringFunctionsTest.java +++ b/metron-platform/metron-common/src/test/java/org/apache/metron/common/dsl/functions/StringFunctionsTest.java @@ -21,10 +21,13 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.apache.commons.collections.map.HashedMap; +import org.apache.commons.collections.map.SingletonMap; import org.apache.metron.common.dsl.ParseException; import org.junit.Assert; import org.junit.Test; +import java.util.Calendar; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -172,4 +175,36 @@ public void shannonEntropyTest() throws Exception { */ Assert.assertEquals(1.5, (Double)run("STRING_ENTROPY(foo)", ImmutableMap.of("foo", "aaaaaaaaaabbbbbccccc")), 0.0); } + + @Test + public void testFormat() throws Exception { + + Map vars = ImmutableMap.of( + "cal", new Calendar.Builder().setDate(2017, 02, 02).build(), + "x", 234, + "y", 3); + + Assert.assertEquals("no args", run("FORMAT('no args')", vars)); + Assert.assertEquals("234.0", run("FORMAT('%.1f', TO_DOUBLE(234))", vars)); + Assert.assertEquals("000234", run("FORMAT('%06d', 234)", vars)); + Assert.assertEquals("03 2,2017", run("FORMAT('%1$tm %1$te,%1$tY', cal)", vars)); + Assert.assertEquals("234 > 3", run("FORMAT('%d > %d', x, y)", vars)); + Assert.assertEquals("missing: null", run("FORMAT('missing: %d', missing)", vars)); + } + + /** + * FORMAT - Not passing a format string will throw an exception + */ + @Test(expected = ParseException.class) + public void testFormatWithNoArguments() throws Exception { + run("FORMAT()", Collections.emptyMap()); + } + + /** + * FORMAT - Forgetting to pass an argument required by the format string will throw an exception. + */ + @Test(expected = ParseException.class) + public void testFormatWithMissingArguments() throws Exception { + run("FORMAT('missing arg: %d')", Collections.emptyMap()); + } } From 936a90a4b73671cfc26adb88424883f76165cccf Mon Sep 17 00:00:00 2001 From: Nick Allen Date: Thu, 2 Feb 2017 13:33:36 -0500 Subject: [PATCH 2/2] Update README to match annotation --- metron-platform/metron-common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metron-platform/metron-common/README.md b/metron-platform/metron-common/README.md index 46837d96bb..c24ae737c2 100644 --- a/metron-platform/metron-common/README.md +++ b/metron-platform/metron-common/README.md @@ -272,7 +272,7 @@ The `!=` operator is the negation of the above. * Returns: Last element of the list ### `FORMAT` - * Description: Returns a formatted string using the specified format string and arguments. + * Description: Returns a formatted string using the specified format string and arguments. Uses Java's string formatting conventions. * Input: * format - string * arguments... - object(s)