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"));
+    }
+  }
+}

Reply via email to