Repository: metron Updated Branches: refs/heads/master 31d99f122 -> 91a017b6d
METRON-1148: Add SET and MULTISET data structures to stellar closes apache/incubator-metron#728 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/91a017b6 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/91a017b6 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/91a017b6 Branch: refs/heads/master Commit: 91a017b6dcefc250bfd67cecf9803cb59015d213 Parents: 31d99f1 Author: cstella <ceste...@gmail.com> Authored: Tue Sep 5 10:18:25 2017 -0400 Committer: cstella <ceste...@gmail.com> Committed: Tue Sep 5 10:18:25 2017 -0400 ---------------------------------------------------------------------- metron-stellar/stellar-common/README.md | 69 +++- .../dsl/functions/DataStructureFunctions.java | 5 + .../stellar/dsl/functions/SetFunctions.java | 287 ++++++++++++++++ .../stellar/dsl/functions/SetFunctionsTest.java | 326 +++++++++++++++++++ 4 files changed, 686 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/91a017b6/metron-stellar/stellar-common/README.md ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/README.md b/metron-stellar/stellar-common/README.md index 926132e..4dc7d8d 100644 --- a/metron-stellar/stellar-common/README.md +++ b/metron-stellar/stellar-common/README.md @@ -168,6 +168,11 @@ In the core language functions, we support basic functional programming primitiv | [ `MAP`](#map) | | [ `MAP_EXISTS`](#map_exists) | | [ `MONTH`](#month) | +| [ `MULTISET_ADD`](#multiset_add) | +| [ `MULTISET_INIT`](#multiset_init) | +| [ `MULTISET_MERGE`](#multiset_merge) | +| [ `MULTISET_REMOVE`](#multiset_remove) | +| [ `MULTISET_TO_SET`](#multiset_to_set) | | [ `PREPEND_IF_MISSING`](#prepend_if_missing) | | [ `PROFILE_GET`](#profile_get) | | [ `PROFILE_FIXED`](#profile_fixed) | @@ -177,6 +182,10 @@ In the core language functions, we support basic functional programming primitiv | [ `REGEXP_MATCH`](#regexp_match) | | [ `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) | @@ -502,7 +511,7 @@ In the core language functions, we support basic functional programming primitiv * Description: Returns true if the passed string is encoded in one of the supported encodings and false if otherwise. * Input: * string - The string to test - * encoding - The name of the encoding as string. See [ `GET_SUPPORTED_ENCODINGS`](#get_supported_encodings). + * encoding - The name of the encoding as string. See [ `GET_SUPPORTED_ENCODINGS`](#get_supported_encodings). * Returns: True if the passed string is encoded in one of the supported encodings and false if otherwise. ### `IS_INTEGER` @@ -639,6 +648,38 @@ In the core language functions, we support basic functional programming primitiv * dateTime - The datetime as a long representing the milliseconds since unix epoch * Returns: The current month (0-based). +### `MULTISET_ADD` + * Description: Adds to a multiset, which is a map associating objects to their instance counts. + * Input: + * set - The multiset to add to + * o - object to add to multiset + * Returns: A multiset + +### `MULTISET_INIT` + * Description: Creates an empty multiset, which is a map associating objects to their instance counts. + * Input: + * input? - An initialization of the multiset + * Returns: A multiset + +### `MULTISET_MERGE` + * Description: Merges a list of multisets, which is a map associating objects to their instance counts. + * Input: + * sets - A collection of multisets to merge + * Returns: A multiset + +### `MULTISET_REMOVE` + * Description: Removes from a multiset, which is a map associating objects to their instance counts. + * Input: + * set - The multiset to add to + * o - object to remove from multiset + * Returns: A multiset + +### `MULTISET_TO_SET` + * Description: Create a set out of a multiset, which is a map associating objects to their instance counts. + * Input: + * multiset - The multiset to convert. + * Returns: The set of objects in the multiset ignoring multiplicity + ### `PREPEND_IF_MISSING` * Description: Prepends the prefix to the start of the string if the string does not already start with any of the prefixes. * Input: @@ -708,6 +749,32 @@ In the core language functions, we support basic functional programming primitiv * number - The number to round * Returns: The nearest integer (based on half-up rounding). +### `SET_ADD` + * Description: Adds to a set + * Input: + * set - The set to add to + * o - object to add to set + * Returns: A Set + +### `SET_INIT` + * Description: Creates an new set + * Input: + * input? - An initialization of the set + * Returns: A Set + +### `SET_MERGE` + * Description: Merges a list of sets + * Input: + * sets - A collection of sets to merge + * Returns: A Set + +### `SET_REMOVE` + * Description: Removes from a set + * Input: + * set - The set to add to + * o - object to add to set + * Returns: A Set + ### `SIN` * Description: Returns the sine of a number. * Input: http://git-wip-us.apache.org/repos/asf/metron/blob/91a017b6/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctions.java ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctions.java b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctions.java index f3d995f..a92406b 100644 --- a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctions.java +++ b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctions.java @@ -17,6 +17,7 @@ */ package org.apache.metron.stellar.dsl.functions; +import com.google.common.collect.Iterables; import org.apache.metron.stellar.dsl.BaseStellarFunction; import org.apache.metron.stellar.dsl.Stellar; import org.apache.metron.stellar.common.utils.BloomFilter; @@ -24,7 +25,9 @@ import org.apache.metron.stellar.common.utils.ConversionUtils; import org.apache.metron.stellar.common.utils.SerDeUtils; import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; public class DataStructureFunctions { @@ -217,4 +220,6 @@ public class DataStructureFunctions { } } } + + } http://git-wip-us.apache.org/repos/asf/metron/blob/91a017b6/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/SetFunctions.java ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/SetFunctions.java b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/SetFunctions.java new file mode 100644 index 0000000..1b4df1e --- /dev/null +++ b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/SetFunctions.java @@ -0,0 +1,287 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.metron.stellar.dsl.functions; + +import com.google.common.collect.Iterables; +import org.apache.metron.stellar.dsl.BaseStellarFunction; +import org.apache.metron.stellar.dsl.Stellar; + +import java.util.*; + +public class SetFunctions { + @Stellar(name="INIT" + , namespace="SET" + , description="Creates a new set" + , params = { "input? - An initialization of the set"} + , returns = "A Set" + ) + public static class SetInit extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + LinkedHashSet<Object> ret = new LinkedHashSet<>(); + if(list.size() == 1) { + Object o = list.get(0); + if(o != null) { + if (o instanceof Iterable) { + Iterables.addAll(ret, (Iterable) o); + } + else { + throw new IllegalArgumentException("Expected an Iterable, but " + o + " is of type " + o.getClass()); + } + } + + } + return ret; + } + } + + @Stellar(name="ADD" + , namespace="SET" + , description="Adds to a set" + , params = {"set - The set to add to" + ,"o - object to add to set" + } + , returns = "A Set" + ) + public static class SetAdd extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashSet<Object> ret = (LinkedHashSet<Object>)list.get(0); + if(ret == null) { + ret = new LinkedHashSet<>(); + } + for(int i = 1;i < list.size();++i) { + Object o = list.get(i); + if (o != null) { + ret.add(o); + } + } + return ret; + } + } + + @Stellar(name="REMOVE" + , namespace="SET" + , description="Removes from a set" + , params = {"set - The set to add to" + ,"o - object to add to set" + } + , returns = "A Set" + ) + public static class SetRemove extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashSet<Object> ret = (LinkedHashSet<Object>)list.get(0); + if(ret == null) { + ret = new LinkedHashSet<>(); + } + for(int i = 1;i < list.size();++i) { + Object o = list.get(i); + if (o != null) { + ret.remove(o); + } + } + return ret; + } + } + + @Stellar(name="MERGE" + , namespace="SET" + , description="Merges a list of sets" + , params = {"sets - A collection of sets to merge" + } + , returns = "A Set" + ) + public static class SetMerge extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashSet<Object> ret = new LinkedHashSet<>(); + if(list.size() > 0) { + Object o = list.get(0); + if(o != null) { + if(!(o instanceof Iterable)) { + throw new IllegalArgumentException("Expected an Iterable, but " + o + " is of type " + o.getClass()); + } + Iterable<? extends Iterable> sets = (Iterable<? extends Iterable>) o; + + for (Iterable s : sets) { + if (s != null) { + if(!(s instanceof Iterable)) { + throw new IllegalArgumentException("Expected an Iterable, but " + s + " is of type " + s.getClass()); + } + Iterables.addAll(ret, s); + } + } + } + } + return ret; + } + } + + @Stellar(name="INIT" + , namespace="MULTISET" + , description="Creates an empty multiset, which is a map associating objects to their instance counts." + , params = { "input? - An initialization of the multiset"} + , returns = "A multiset" + ) + public static class MultiSetInit extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + LinkedHashMap<Object, Integer> ret = new LinkedHashMap<>(); + if (list.size() >= 1) { + Object o = list.get(0); + if (o != null) { + if (!(o instanceof Iterable)) { + throw new IllegalArgumentException("Expected an Iterable, but " + o + " is of type " + o.getClass()); + } + for (Object obj : (Iterable) o) { + ret.merge(obj, 1, (k, one) -> k + one); + } + } + } + return ret; + } + } + + @Stellar(name="ADD" + , namespace="MULTISET" + , description="Adds to a multiset, which is a map associating objects to their instance counts." + , params = {"set - The multiset to add to" + ,"o - object to add to multiset" + } + , returns = "A multiset" + ) + public static class MultiSetAdd extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashMap<Object, Integer> ret = (LinkedHashMap<Object, Integer>)list.get(0); + if(ret == null) { + ret = new LinkedHashMap<>(); + } + for(int i = 1;i < list.size();++i) { + Object o = list.get(i); + if (o != null) { + ret.merge(o, 1, (k, one) -> k + one); + } + } + return ret; + } + } + + @Stellar(name="REMOVE" + , namespace="MULTISET" + , description="Removes from a multiset, which is a map associating objects to their instance counts." + , params = {"set - The multiset to add to" + ,"o - object to remove from multiset" + } + , returns = "A multiset" + ) + public static class MultiSetRemove extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashMap<Object, Integer> ret = (LinkedHashMap<Object, Integer>)list.get(0); + if(ret == null) { + ret = new LinkedHashMap<>(); + } + for(int i = 1;i < list.size();++i) { + Object o = list.get(i); + if (o != null) { + Integer cnt = ret.get(o); + if(cnt == null) { + continue; + } + if(cnt == 1) { + ret.remove(o); + } + else { + ret.put(o, cnt - 1); + } + } + } + return ret; + } + } + + @Stellar(name="MERGE" + , namespace="MULTISET" + , description="Merges a list of multisets, which is a map associating objects to their instance counts." + , params = {"sets - A collection of multisets to merge" + } + , returns = "A multiset" + ) + public static class MultiSetMerge extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashMap<Object, Integer> ret = new LinkedHashMap<>(); + if(list.size() > 0) { + Iterable<Map<Object, Integer>> maps = (Iterable<Map<Object, Integer>>)list.get(0); + for(Map<Object, Integer> s : maps) { + if(s != null) { + for (Map.Entry<Object, Integer> kv : s.entrySet()) { + ret.merge(kv.getKey(), kv.getValue(), (k, cnt) -> k + cnt); + } + } + } + } + return ret; + } + } + + + @Stellar(name="TO_SET" + , namespace="MULTISET" + , description="Create a set out of a multiset, which is a map associating objects to their instance counts." + , params = {"multiset - The multiset to convert." + } + , returns = "The set of objects in the multiset ignoring multiplicity" + ) + public static class MultiSetToSet extends BaseStellarFunction { + @Override + public Object apply(List<Object> list) { + if(list.size() < 1) { + return null; + } + LinkedHashSet<Object> ret = new LinkedHashSet<>(); + if(list.size() == 1) { + Map<Object, Integer> multiset = (Map<Object, Integer>)list.get(0); + if(multiset != null) { + ret.addAll(multiset.keySet()); + } + } + return ret; + } + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/91a017b6/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SetFunctionsTest.java ---------------------------------------------------------------------- diff --git a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SetFunctionsTest.java b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SetFunctionsTest.java new file mode 100644 index 0000000..1aa8eb4 --- /dev/null +++ b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SetFunctionsTest.java @@ -0,0 +1,326 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.metron.stellar.dsl.functions; + +import org.apache.metron.stellar.common.utils.StellarProcessorUtils; +import org.apache.metron.stellar.dsl.ParseException; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class SetFunctionsTest { + + @Test(expected=ParseException.class) + public void multisetInitTest_wrongType() throws Exception { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_INIT({ 'foo' : 'bar'})", new HashMap<>()); + } + + @Test + public void multisetInitTest() throws Exception { + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_INIT()", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + //int initialization + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_INIT([1,2,3,2])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.containsKey(1)); + Assert.assertEquals(1,(int)s.get(1)); + Assert.assertTrue(s.containsKey(2)); + Assert.assertEquals(2,(int)s.get(2)); + Assert.assertTrue(s.containsKey(3)); + Assert.assertEquals(1,(int)s.get(3)); + } + //string initialization + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_INIT(['one','two','three','two'])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.containsKey("one")); + Assert.assertEquals(1,(int)s.get("one")); + Assert.assertTrue(s.containsKey("two")); + Assert.assertEquals(2,(int)s.get("two")); + Assert.assertTrue(s.containsKey("three")); + Assert.assertEquals(1,(int)s.get("three")); + + } + } + + @Test + public void multisetAddTest() throws Exception { + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_ADD(MULTISET_INIT(), 1)", new HashMap<>()); + Assert.assertEquals(1, s.size()); + Assert.assertTrue(s.containsKey(1)); + Assert.assertEquals(1,(int)s.get(1)); + } + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_ADD(null, 1)", new HashMap<>()); + Assert.assertEquals(1, s.size()); + Assert.assertTrue(s.containsKey(1)); + Assert.assertEquals(1,(int)s.get(1)); + } + //int + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_ADD(MULTISET_INIT([1,2,3,4,4]), 4)", new HashMap<>()); + Assert.assertEquals(4, s.size()); + Assert.assertTrue(s.containsKey(1)); + Assert.assertEquals(1,(int)s.get(1)); + Assert.assertTrue(s.containsKey(2)); + Assert.assertEquals(1,(int)s.get(2)); + Assert.assertTrue(s.containsKey(3)); + Assert.assertEquals(1,(int)s.get(3)); + Assert.assertTrue(s.containsKey(4)); + Assert.assertEquals(3,(int)s.get(4)); + } + //string + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_ADD(MULTISET_INIT(['one','two','three', 'four', 'four']), 'four')", new HashMap<>()); + Assert.assertEquals(4, s.size()); + Assert.assertTrue(s.containsKey("one")); + Assert.assertEquals(1,(int)s.get("one")); + Assert.assertTrue(s.containsKey("two")); + Assert.assertEquals(1,(int)s.get("two")); + Assert.assertTrue(s.containsKey("three")); + Assert.assertEquals(1,(int)s.get("three")); + Assert.assertTrue(s.containsKey("four")); + Assert.assertEquals(3,(int)s.get("four")); + } + } +@Test + public void multisetRemoveTest() throws Exception { + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_REMOVE(MULTISET_INIT([1]), 1)", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_REMOVE(null, 1)", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + //int + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_REMOVE(MULTISET_INIT([1,2,3,2]), 2)", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.containsKey(1)); + Assert.assertEquals(1, (int)s.get(1)); + Assert.assertTrue(s.containsKey(2)); + Assert.assertEquals(1, (int)s.get(2)); + Assert.assertTrue(s.containsKey(3)); + Assert.assertEquals(1, (int)s.get(3)); + } + //string + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_REMOVE(MULTISET_INIT(['one','two','three', 'two']), 'two')", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.containsKey("one")); + Assert.assertEquals(1, (int)s.get("one")); + Assert.assertTrue(s.containsKey("two")); + Assert.assertEquals(1, (int)s.get("two")); + Assert.assertTrue(s.containsKey("three")); + Assert.assertEquals(1, (int)s.get("three")); + } + } + + @Test(expected=ParseException.class) + public void multisetMergeTest_wrongType() throws Exception { + + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_MERGE({ 'bar' : 'foo' } )", new HashMap<>()); + } + + @Test + public void multisetMergeTest() throws Exception { + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_MERGE([MULTISET_INIT(), MULTISET_INIT(null), null])", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + //int + { + Map<Object, Integer> s = (Map<Object, Integer>) StellarProcessorUtils.run("MULTISET_MERGE([MULTISET_INIT([1,2]), MULTISET_INIT([2,3]), null, MULTISET_INIT()])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.containsKey(1)); + Assert.assertEquals(1, (int)s.get(1)); + Assert.assertTrue(s.containsKey(2)); + Assert.assertEquals(2, (int)s.get(2)); + Assert.assertTrue(s.containsKey(3)); + Assert.assertEquals(1, (int)s.get(3)); + } + //string + { + Map<Object, Integer> s = (Map<Object, Integer>)StellarProcessorUtils.run("MULTISET_MERGE([MULTISET_INIT(['one','two']), MULTISET_INIT(['two', 'three'])])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.containsKey("one")); + Assert.assertEquals(1, (int)s.get("one")); + Assert.assertTrue(s.containsKey("two")); + Assert.assertEquals(2, (int)s.get("two")); + Assert.assertTrue(s.containsKey("three")); + Assert.assertEquals(1, (int)s.get("three")); + } + } + + @Test(expected=ParseException.class) + public void setInitTest_wrongType() throws Exception { + Set s = (Set) StellarProcessorUtils.run("SET_INIT({ 'foo' : 2})", new HashMap<>()); + } + + @Test + public void setInitTest() throws Exception { + { + Set s = (Set) StellarProcessorUtils.run("SET_INIT()", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + //int initialization + { + Set s = (Set) StellarProcessorUtils.run("SET_INIT([1,2,3])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.contains(1)); + Assert.assertTrue(s.contains(2)); + Assert.assertTrue(s.contains(3)); + } + //string initialization + { + Set s = (Set) StellarProcessorUtils.run("SET_INIT(['one','two','three'])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.contains("one")); + Assert.assertTrue(s.contains("two")); + Assert.assertTrue(s.contains("three")); + } + } + + @Test + public void multisetToSetTest() throws Exception { + { + Set s = (Set) StellarProcessorUtils.run("MULTISET_TO_SET(MULTISET_ADD(MULTISET_INIT(), 1))", new HashMap<>()); + Assert.assertEquals(1, s.size()); + Assert.assertTrue(s.contains(1)); + } + { + Set s = (Set) StellarProcessorUtils.run("MULTISET_TO_SET(MULTISET_ADD(null, 1))", new HashMap<>()); + Assert.assertEquals(1, s.size()); + Assert.assertTrue(s.contains(1)); + } + //int + { + Set s = (Set) StellarProcessorUtils.run("MULTISET_TO_SET(MULTISET_ADD(MULTISET_INIT([1,2,3]), 4))", new HashMap<>()); + Assert.assertEquals(4, s.size()); + Assert.assertTrue(s.contains(1)); + Assert.assertTrue(s.contains(2)); + Assert.assertTrue(s.contains(3)); + Assert.assertTrue(s.contains(4)); + } + //string + { + Set s = (Set) StellarProcessorUtils.run("MULTISET_TO_SET(MULTISET_ADD(MULTISET_INIT(['one','two','three']), 'four'))", new HashMap<>()); + Assert.assertEquals(4, s.size()); + Assert.assertTrue(s.contains("one")); + Assert.assertTrue(s.contains("two")); + Assert.assertTrue(s.contains("three")); + Assert.assertTrue(s.contains("four")); + } + } + + @Test + public void setAddTest() throws Exception { + { + Set s = (Set) StellarProcessorUtils.run("SET_ADD(SET_INIT(), 1)", new HashMap<>()); + Assert.assertEquals(1, s.size()); + Assert.assertTrue(s.contains(1)); + } + { + Set s = (Set) StellarProcessorUtils.run("SET_ADD(null, 1)", new HashMap<>()); + Assert.assertEquals(1, s.size()); + Assert.assertTrue(s.contains(1)); + } + //int + { + Set s = (Set) StellarProcessorUtils.run("SET_ADD(SET_INIT([1,2,3]), 4)", new HashMap<>()); + Assert.assertEquals(4, s.size()); + Assert.assertTrue(s.contains(1)); + Assert.assertTrue(s.contains(2)); + Assert.assertTrue(s.contains(3)); + Assert.assertTrue(s.contains(4)); + } + //string + { + Set s = (Set) StellarProcessorUtils.run("SET_ADD(SET_INIT(['one','two','three']), 'four')", new HashMap<>()); + Assert.assertEquals(4, s.size()); + Assert.assertTrue(s.contains("one")); + Assert.assertTrue(s.contains("two")); + Assert.assertTrue(s.contains("three")); + Assert.assertTrue(s.contains("four")); + } + } + + @Test + public void setRemoveTest() throws Exception { + { + Set s = (Set) StellarProcessorUtils.run("SET_REMOVE(SET_INIT([1]), 1)", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + { + Set s = (Set) StellarProcessorUtils.run("SET_REMOVE(null, 1)", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + //int + { + Set s = (Set) StellarProcessorUtils.run("SET_REMOVE(SET_INIT([1,2,3]), 2)", new HashMap<>()); + Assert.assertEquals(2, s.size()); + Assert.assertTrue(s.contains(1)); + Assert.assertTrue(s.contains(3)); + } + //string + { + Set s = (Set) StellarProcessorUtils.run("SET_REMOVE(SET_INIT(['one','two','three']), 'three')", new HashMap<>()); + Assert.assertEquals(2, s.size()); + Assert.assertTrue(s.contains("one")); + Assert.assertTrue(s.contains("two")); + } + } + + @Test(expected=ParseException.class) + public void setMergeTest_wrongType() throws Exception { + Set s = (Set) StellarProcessorUtils.run("SET_MERGE({ 'foo' : 'bar'} )", new HashMap<>()); + } + + @Test + public void setMergeTest() throws Exception { + { + Set s = (Set) StellarProcessorUtils.run("SET_MERGE([SET_INIT(), SET_INIT(null), null])", new HashMap<>()); + Assert.assertEquals(0, s.size()); + } + //int + { + Set s = (Set) StellarProcessorUtils.run("SET_MERGE([SET_INIT([1,2]), SET_INIT([3]), null, SET_INIT()])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.contains(1)); + Assert.assertTrue(s.contains(2)); + Assert.assertTrue(s.contains(3)); + } + //string + { + Set s = (Set) StellarProcessorUtils.run("SET_MERGE([SET_INIT(['one','two']), SET_INIT(['three'])])", new HashMap<>()); + Assert.assertEquals(3, s.size()); + Assert.assertTrue(s.contains("one")); + Assert.assertTrue(s.contains("two")); + Assert.assertTrue(s.contains("three")); + } + } +}