metron-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ceste...@apache.org
Subject [3/4] incubator-metron git commit: METRON-366: Add MODEL_APPLY to Stellar closes apache/incubator-metron#210
Date Mon, 22 Aug 2016 01:50:49 GMT
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MaaSFunctions.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MaaSFunctions.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MaaSFunctions.java
new file mode 100644
index 0000000..6fee251
--- /dev/null
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MaaSFunctions.java
@@ -0,0 +1,258 @@
+/**
+ * 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.common.dsl.functions;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.metron.common.dsl.Context;
+import org.apache.metron.common.dsl.ParseException;
+import org.apache.metron.common.dsl.StellarFunction;
+import org.apache.metron.common.utils.JSONUtils;
+import org.apache.metron.maas.config.Endpoint;
+import org.apache.metron.maas.config.MaaSConfig;
+import org.apache.metron.maas.config.ModelEndpoint;
+import org.apache.metron.maas.discovery.ServiceDiscoverer;
+import org.apache.metron.maas.util.ConfigUtil;
+import org.apache.metron.maas.util.RESTUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+public class MaaSFunctions {
+ protected static final Logger LOG = LoggerFactory.getLogger(MaaSFunctions.class);
+  private static class ModelCacheKey {
+    String name;
+    String version;
+    String method;
+    Map<String, String> args;
+    public ModelCacheKey(String name, String version, String method, Map<String, String> args) {
+      this.name = name;
+      this.version = version;
+      this.method = method;
+      this.args = args;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      ModelCacheKey that = (ModelCacheKey) o;
+
+      if (name != null ? !name.equals(that.name) : that.name != null) return false;
+      if (version != null ? !version.equals(that.version) : that.version != null) return false;
+      if (method != null ? !method.equals(that.method) : that.method != null) return false;
+      return args != null ? args.equals(that.args) : that.args == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+      int result = name != null ? name.hashCode() : 0;
+      result = 31 * result + (version != null ? version.hashCode() : 0);
+      result = 31 * result + (method != null ? method.hashCode() : 0);
+      result = 31 * result + (args != null ? args.hashCode() : 0);
+      return result;
+    }
+  }
+  public static class ModelApply implements StellarFunction {
+    private ServiceDiscoverer discoverer;
+    private Cache<ModelCacheKey, Map<String, Object> > resultCache;
+    public ModelApply() {
+      resultCache = CacheBuilder.newBuilder()
+                            .concurrencyLevel(4)
+                            .weakKeys()
+                            .maximumSize(100000)
+                            .expireAfterWrite(10, TimeUnit.MINUTES)
+                            .build();
+    }
+
+    @Override
+    public Object apply(List<Object> args, Context context) throws ParseException {
+      if(args.size() < 2) {
+        throw new ParseException("Unable to execute model_apply. " +
+                                 "Expected arguments: endpoint_map:map, " +
+                                 " [endpoint method:string], model_args:map"
+                                 );
+      }
+      int i = 0;
+      if(args.size() == 0) {
+        return null;
+      }
+      Object endpointObj = args.get(i++);
+      Map endpoint = null;
+      String modelName;
+      String modelVersion;
+      String modelUrl;
+      if(endpointObj instanceof Map) {
+        endpoint = (Map)endpointObj;
+        modelName = endpoint.get("name") + "";
+        modelVersion = endpoint.get("version") + "";
+        modelUrl = endpoint.get("url") + "";
+      }
+      else {
+        return null;
+      }
+      String modelFunction = "apply";
+      Map<String, String> modelArgs = new HashMap<>();
+      if(args.get(i) instanceof String) {
+        String func = (String)args.get(i);
+        if(endpoint.containsKey("endpoint:" + func)) {
+          modelFunction = "" + endpoint.get("endpoint:" + func);
+        }
+        else {
+          modelFunction = func;
+        }
+        i++;
+      }
+
+      if(args.get(i) instanceof Map) {
+        if(endpoint.containsKey("endpoint:apply")) {
+          modelFunction = "" + endpoint.get("endpoint:apply");
+        }
+        modelArgs = (Map)args.get(i);
+      }
+      if( modelName == null
+       || modelVersion == null
+       || modelFunction == null
+        ) {
+        return null;
+      }
+      ModelCacheKey cacheKey = new ModelCacheKey(modelName, modelVersion, modelFunction, modelArgs);
+      Map<String, Object> ret = resultCache.getIfPresent(cacheKey);
+      if(ret != null) {
+        return ret;
+      }
+      else {
+        String url = modelUrl;
+        if (url.endsWith("/")) {
+          url = url.substring(0, url.length() - 1);
+        }
+        if (modelFunction.startsWith("/")) {
+          modelFunction = modelFunction.substring(1);
+        }
+        try {
+          URL u = new URL(url + "/" + modelFunction);
+
+          String results = RESTUtil.INSTANCE.getRESTJSONResults(u, modelArgs);
+          ret = JSONUtils.INSTANCE.load(results, new TypeReference<Map<String, Object>>() {
+          });
+          resultCache.put(cacheKey, ret);
+          return ret;
+        } catch (Exception e) {
+          LOG.error(e.getMessage(), e);
+          if (discoverer != null) {
+            try {
+              URL u = new URL(modelUrl);
+              discoverer.blacklist(u);
+            } catch (MalformedURLException e1) {
+            }
+          }
+        }
+      }
+      return null;
+    }
+
+    @Override
+    public void initialize(Context context) {
+      try {
+        Optional<ServiceDiscoverer> discovererOpt = (Optional) (context.getCapability(Context.Capabilities.SERVICE_DISCOVERER));
+        if (discovererOpt.isPresent()) {
+          discoverer = discovererOpt.get();
+        }
+      }
+      catch(Exception ex) {
+        LOG.error(ex.getMessage(), ex);
+      }
+    }
+  }
+
+  public static class GetEndpoint implements StellarFunction {
+    ServiceDiscoverer discoverer;
+    @Override
+    public Object apply(List<Object> args, Context context) throws ParseException {
+      if(discoverer == null) {
+        throw new ParseException("Unable to find ServiceDiscoverer service...");
+      }
+      String modelName = null;
+      String modelVersion = null;
+      if(args.size() >= 1) {
+        modelName = args.get(0).toString();
+      }
+      if(args.size() >= 2)
+      {
+        modelVersion = args.get(1).toString();
+      }
+      if(modelName == null) {
+        return null;
+      }
+      try {
+        ModelEndpoint ep = null;
+        if (modelVersion == null) {
+          ep = discoverer.getEndpoint(modelName);
+        } else {
+          ep = discoverer.getEndpoint(modelName, modelVersion);
+        }
+        return ep == null ? null : endpointToMap(ep.getName(), ep.getVersion(), ep.getEndpoint());
+      }
+      catch(Exception ex) {
+        LOG.error("Unable to discover endpoint: " + ex.getMessage(), ex);
+        return null;
+      }
+    }
+    public static Map<String, String> endpointToMap(String name, String version, Endpoint ep) {
+      Map<String, String> ret = new HashMap<>();
+      ret.put("url", ep.getUrl());
+      ret.put("name", name);
+      ret.put("version", version);
+      for(Map.Entry<String, String> kv : ep.getFunctions().entrySet()) {
+        ret.put("endpoint:" + kv.getKey(), kv.getValue());
+      }
+      return ret;
+    }
+    @Override
+    public void initialize(Context context) {
+      Optional<Object> clientOptional = context.getCapability(Context.Capabilities.ZOOKEEPER_CLIENT);
+      CuratorFramework client = null;
+      if(clientOptional.isPresent() && clientOptional.get() instanceof CuratorFramework) {
+        client = (CuratorFramework)clientOptional.get();
+      }
+      else {
+        return;
+      }
+      try {
+        MaaSConfig config = ConfigUtil.INSTANCE.read(client, "/metron/maas/config", new MaaSConfig(), MaaSConfig.class);
+        discoverer = new ServiceDiscoverer(client, config.getServiceRoot());
+        discoverer.start();
+        context.addCapability(Context.Capabilities.SERVICE_DISCOVERER, () -> discoverer);
+      } catch (Exception e) {
+        LOG.error(e.getMessage(), e);
+        return;
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MapFunctions.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MapFunctions.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MapFunctions.java
index 5d43416..0e322b7 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MapFunctions.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/MapFunctions.java
@@ -18,12 +18,29 @@
 
 package org.apache.metron.common.dsl.functions;
 
+import org.apache.metron.common.dsl.BaseStellarFunction;
+
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 
 public class MapFunctions {
-  public static class MapGet implements Function<List<Object>, Object> {
+  public static class MapExists extends BaseStellarFunction {
+
+    @Override
+    public Object apply(List<Object> list) {
+      if(list.size() < 2) {
+        return false;
+      }
+      Object key = list.get(0);
+      Object mapObj = list.get(1);
+      if(key != null && mapObj != null && mapObj instanceof Map) {
+        return ((Map)mapObj).containsKey(key);
+      }
+      return false;
+    }
+  }
+  public static class MapGet extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> objects) {
       Object keyObj = objects.get(0);

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/NetworkFunctions.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/NetworkFunctions.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/NetworkFunctions.java
index e8cda44..e6a1818 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/NetworkFunctions.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/NetworkFunctions.java
@@ -21,6 +21,8 @@ package org.apache.metron.common.dsl.functions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.net.InternetDomainName;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.metron.common.dsl.BaseStellarFunction;
 
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -28,7 +30,32 @@ import java.util.List;
 import java.util.function.Function;
 
 public class NetworkFunctions {
-  public static class RemoveSubdomains implements Function<List<Object>, Object> {
+  public static class InSubnet extends BaseStellarFunction {
+
+    @Override
+    public Object apply(List<Object> list) {
+      if(list.size() < 2) {
+        throw new IllegalStateException("IN_SUBNET expects at least two args: [ip, cidr1, cidr2, ...]"
+                + " where cidr is the subnet mask in cidr form"
+        );
+      }
+      String ip = (String) list.get(0);
+      if(ip == null) {
+        return false;
+      }
+      boolean inSubnet = false;
+      for(int i = 1;i < list.size() && !inSubnet;++i) {
+        String cidr = (String) list.get(1);
+        if(cidr == null) {
+          continue;
+        }
+        inSubnet |= new SubnetUtils(cidr).getInfo().isInRange(ip);
+      }
+
+      return inSubnet;
+    }
+  }
+  public static class RemoveSubdomains extends BaseStellarFunction {
 
     @Override
     public Object apply(List<Object> objects) {
@@ -54,7 +81,7 @@ public class NetworkFunctions {
       return null;
     }
   }
-  public static class RemoveTLD implements Function<List<Object>, Object> {
+  public static class RemoveTLD extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> objects) {
       Object dnObj = objects.get(0);
@@ -75,7 +102,7 @@ public class NetworkFunctions {
     }
   }
 
-  public static class ExtractTLD implements Function<List<Object>, Object> {
+  public static class ExtractTLD extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> objects) {
       Object dnObj = objects.get(0);
@@ -87,7 +114,7 @@ public class NetworkFunctions {
     }
   }
 
-  public static class URLToPort implements Function<List<Object>, Object> {
+  public static class URLToPort extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> objects) {
       URL url =  toUrl(objects.get(0));
@@ -99,14 +126,14 @@ public class NetworkFunctions {
     }
   }
 
-  public static class URLToPath implements Function<List<Object>, Object> {
+  public static class URLToPath extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> objects) {
       URL url =  toUrl(objects.get(0));
       return url == null?null:url.getPath();
     }
   }
-  public static class URLToHost implements Function<List<Object>, Object> {
+  public static class URLToHost extends BaseStellarFunction {
 
     @Override
     public Object apply(List<Object> objects) {
@@ -115,7 +142,7 @@ public class NetworkFunctions {
     }
   }
 
-  public static class URLToProtocol implements Function<List<Object>, Object> {
+  public static class URLToProtocol extends BaseStellarFunction {
 
     @Override
     public Object apply(List<Object> objects) {

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/functions/StringFunctions.java
----------------------------------------------------------------------
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 2793f02..beca43f 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
@@ -21,13 +21,83 @@ package org.apache.metron.common.dsl.functions;
 import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
+import org.apache.metron.common.dsl.BaseStellarFunction;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Function;
 
 public class StringFunctions {
-  public static class JoinFunction implements Function<List<Object>, Object> {
+  public static class RegexpMatch extends BaseStellarFunction {
+
+    @Override
+    public Object apply(List<Object> list) {
+      if(list.size() < 2) {
+        throw new IllegalStateException("REGEXP_MATCH expects two args: [string, pattern] where pattern is a regexp pattern");
+      }
+      String pattern = (String) list.get(1);
+      String str = (String) list.get(0);
+      if(str == null || pattern == null) {
+        return false;
+      }
+      return str.matches(pattern);
+    }
+  }
+
+  public static class EndsWith extends BaseStellarFunction {
+    @Override
+    public Object apply(List<Object> list) {
+      if(list.size() < 2) {
+        throw new IllegalStateException("ENDS_WITH expects two args: [string, suffix] where suffix is the string fragment that the string should end with");
+      }
+      String prefix = (String) list.get(1);
+      String str = (String) list.get(0);
+      if(str == null || prefix == null) {
+        return false;
+      }
+      return str.endsWith(prefix);
+    }
+  }
+  public static class StartsWith extends BaseStellarFunction {
+
+    @Override
+    public Object apply(List<Object> list) {
+      if(list.size() < 2) {
+        throw new IllegalStateException("STARTS_WITH expects two args: [string, prefix] where prefix is the string fragment that the string should start with");
+      }
+      String prefix = (String) list.get(1);
+      String str = (String) list.get(0);
+      if(str == null || prefix == null) {
+        return false;
+      }
+      return str.startsWith(prefix);
+    }
+  }
+  public static class ToLower extends BaseStellarFunction {
+    @Override
+    public Object apply(List<Object> strings) {
+      return strings.get(0)==null?null:strings.get(0).toString().toLowerCase();
+    }
+  }
+  public static class ToUpper extends BaseStellarFunction {
+    @Override
+    public Object apply(List<Object> strings) {
+      return strings.get(0)==null?null:strings.get(0).toString().toUpperCase();
+    }
+  }
+  public static class ToString extends BaseStellarFunction {
+    @Override
+    public Object apply(List<Object> strings) {
+      return strings.get(0)==null?null:strings.get(0).toString();
+    }
+  }
+  public static class Trim extends BaseStellarFunction {
+    @Override
+    public Object apply(List<Object> strings) {
+      return strings.get(0)==null?null:strings.get(0).toString().trim();
+    }
+  }
+  public static class JoinFunction extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> args) {
       List<Object> arg1 = (List<Object>) args.get(0);
@@ -35,7 +105,7 @@ public class StringFunctions {
       return Joiner.on(delim).join(Iterables.filter(arg1, x -> x != null));
     }
   }
-  public static class SplitFunction implements Function<List<Object>, Object> {
+  public static class SplitFunction extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> args) {
       List ret = new ArrayList();
@@ -49,14 +119,14 @@ public class StringFunctions {
     }
   }
 
-  public static class GetLast implements Function<List<Object>, Object> {
+  public static class GetLast extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> args) {
       List<Object> arg1 = (List<Object>) args.get(0);
       return Iterables.getLast(arg1, null);
     }
   }
-  public static class GetFirst implements Function<List<Object>, Object> {
+  public static class GetFirst extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> args) {
       List<Object> arg1 = (List<Object>) args.get(0);
@@ -64,7 +134,7 @@ public class StringFunctions {
     }
   }
 
-  public static class Get implements Function<List<Object>, Object> {
+  public static class Get extends BaseStellarFunction {
     @Override
     public Object apply(List<Object> args) {
       List<Object> arg1 = (List<Object>) args.get(0);

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/FieldTransformation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/FieldTransformation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/FieldTransformation.java
index e308dd3..a19d165 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/FieldTransformation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/FieldTransformation.java
@@ -18,6 +18,8 @@
 
 package org.apache.metron.common.field.transformation;
 
+import org.apache.metron.common.dsl.Context;
+
 import java.io.Serializable;
 import java.util.List;
 import java.util.Map;
@@ -27,5 +29,6 @@ public interface FieldTransformation extends Serializable {
                          , List<String> outputField
                          , Map<String, Object> fieldMappingConfig
                          , Map<String, Object> sensorConfig
+                         , Context context
                          );
 }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/IPProtocolTransformation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/IPProtocolTransformation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/IPProtocolTransformation.java
index c789018..0a4137a 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/IPProtocolTransformation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/IPProtocolTransformation.java
@@ -20,6 +20,9 @@ package org.apache.metron.common.field.transformation;
 
 
 import org.apache.hadoop.yarn.util.ConverterUtils;
+import org.apache.metron.common.dsl.Context;
+import org.apache.metron.common.dsl.ParseException;
+import org.apache.metron.common.dsl.StellarFunction;
 import org.apache.metron.common.utils.ConversionUtils;
 
 import java.util.HashMap;
@@ -27,7 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 
-public class IPProtocolTransformation extends SimpleFieldTransformation implements Function<List<Object>, Object> {
+public class IPProtocolTransformation extends SimpleFieldTransformation implements StellarFunction {
 
   private final static Map<Integer, String> PROTOCOLS = new HashMap<>();
 
@@ -183,7 +186,7 @@ public class IPProtocolTransformation extends SimpleFieldTransformation implemen
 
 
   @Override
-  public Object apply(List<Object> objects) {
+  public Object apply(List<Object> objects, Context context) throws ParseException {
     Object keyObj = objects.get(0);
     if(keyObj == null) {
       return keyObj;
@@ -198,4 +201,9 @@ public class IPProtocolTransformation extends SimpleFieldTransformation implemen
     }
     return ret;
   }
+
+  @Override
+  public void initialize(Context context) {
+
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/RemoveTransformation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/RemoveTransformation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/RemoveTransformation.java
index f2f34c0..be8b409 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/RemoveTransformation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/RemoveTransformation.java
@@ -18,20 +18,19 @@
 
 package org.apache.metron.common.field.transformation;
 
-import org.apache.metron.common.dsl.MapVariableResolver;
-import org.apache.metron.common.dsl.ParseException;
+import org.apache.metron.common.dsl.*;
 import org.apache.metron.common.stellar.StellarPredicateProcessor;
-import org.apache.metron.common.dsl.VariableResolver;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 public class RemoveTransformation implements FieldTransformation {
   public static final String CONDITION_CONF = "condition";
   public static final StellarPredicateProcessor PASSTHROUGH_PROCESSOR = new StellarPredicateProcessor() {
     @Override
-    public Boolean parse(String rule, VariableResolver resolver) {
+    public Boolean parse(String rule, VariableResolver resolver, Function<String, StellarFunction> functionResolver, Context context) {
       return true;
     }
 
@@ -69,10 +68,11 @@ public class RemoveTransformation implements FieldTransformation {
                                 , final List<String> outputFields
                                 , Map<String, Object> fieldMappingConfig
                                 , Map<String, Object> sensorConfig
+                                , Context context
                                 ) {
     String condition = getCondition(fieldMappingConfig);
     StellarPredicateProcessor processor = getPredicateProcessor(condition);
-    if(processor.parse(condition, new MapVariableResolver(input))) {
+    if(processor.parse(condition, new MapVariableResolver(input), StellarFunctions.FUNCTION_RESOLVER(), context)) {
       return new HashMap<String, Object>() {{
         for(String outputField : outputFields) {
           put(outputField, null);

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/SimpleFieldTransformation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/SimpleFieldTransformation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/SimpleFieldTransformation.java
index 3f6215e..86e6f51 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/SimpleFieldTransformation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/SimpleFieldTransformation.java
@@ -19,6 +19,7 @@
 package org.apache.metron.common.field.transformation;
 
 import com.google.common.collect.Iterables;
+import org.apache.metron.common.dsl.Context;
 
 import java.util.List;
 import java.util.Map;
@@ -29,6 +30,7 @@ public abstract class SimpleFieldTransformation implements FieldTransformation {
                                 , List<String> outputField
                                 , Map<String, Object> fieldMappingConfig
                                 , Map<String, Object> sensorConfig
+                                , Context context
                                 )
   {
     Object value = (input == null || input.values() == null && input.values().isEmpty())

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/StellarTransformation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/StellarTransformation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/StellarTransformation.java
index a8ad052..fdc2fb5 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/StellarTransformation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/transformation/StellarTransformation.java
@@ -18,7 +18,9 @@
 
 package org.apache.metron.common.field.transformation;
 
+import org.apache.metron.common.dsl.Context;
 import org.apache.metron.common.dsl.MapVariableResolver;
+import org.apache.metron.common.dsl.StellarFunctions;
 import org.apache.metron.common.dsl.VariableResolver;
 import org.apache.metron.common.stellar.StellarProcessor;
 
@@ -32,6 +34,7 @@ public class StellarTransformation implements FieldTransformation {
                                 , List<String> outputField
                                 , Map<String, Object> fieldMappingConfig
                                 , Map<String, Object> sensorConfig
+                                , Context context
                                 )
   {
     Map<String, Object> ret = new HashMap<>();
@@ -40,7 +43,7 @@ public class StellarTransformation implements FieldTransformation {
     for(String oField : outputField) {
       Object transformObj = fieldMappingConfig.get(oField);
       if(transformObj != null) {
-        Object o = processor.parse(transformObj.toString(), resolver);
+        Object o = processor.parse(transformObj.toString(), resolver, StellarFunctions.FUNCTION_RESOLVER(), context);
         if (o != null) {
           ret.put(oField, o);
         }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/FieldValidation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/FieldValidation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/FieldValidation.java
index c0d4c40..59ba9bb 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/FieldValidation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/FieldValidation.java
@@ -18,6 +18,8 @@
 
 package org.apache.metron.common.field.validation;
 
+import org.apache.metron.common.dsl.Context;
+
 import java.io.Serializable;
 import java.util.Map;
 
@@ -25,6 +27,7 @@ public interface FieldValidation extends Serializable {
   boolean isValid( Map<String, Object> input
                  , Map<String, Object> validationConfig
                  , Map<String, Object> globalConfig
+                 , Context context
                  );
   void initialize(Map<String, Object> validationConfig, Map<String, Object> globalConfig);
 }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/QueryValidation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/QueryValidation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/QueryValidation.java
index f9060af..ee4314a 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/QueryValidation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/QueryValidation.java
@@ -18,7 +18,9 @@
 
 package org.apache.metron.common.field.validation;
 
+import org.apache.metron.common.dsl.Context;
 import org.apache.metron.common.dsl.MapVariableResolver;
+import org.apache.metron.common.dsl.StellarFunctions;
 import org.apache.metron.common.stellar.StellarPredicateProcessor;
 
 import java.util.Map;
@@ -45,6 +47,7 @@ public class QueryValidation implements FieldValidation {
   public boolean isValid( Map<String, Object> input
                         , Map<String, Object> validationConfig
                         , Map<String, Object> globalConfig
+                        , Context context
                         ) {
     String condition = Config.CONDITION.get(validationConfig, String.class);
     if(condition == null) {
@@ -52,7 +55,7 @@ public class QueryValidation implements FieldValidation {
     }
     else {
       StellarPredicateProcessor processor = new StellarPredicateProcessor();
-      return processor.parse(condition, new MapVariableResolver(input, validationConfig, globalConfig));
+      return processor.parse(condition, new MapVariableResolver(input, validationConfig, globalConfig), StellarFunctions.FUNCTION_RESOLVER(), context);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/SimpleValidation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/SimpleValidation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/SimpleValidation.java
index 13b922f..33f7896 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/SimpleValidation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/SimpleValidation.java
@@ -18,6 +18,8 @@
 
 package org.apache.metron.common.field.validation;
 
+import org.apache.metron.common.dsl.Context;
+
 import java.util.List;
 import java.util.Map;
 import java.util.function.Predicate;
@@ -27,6 +29,7 @@ public abstract class SimpleValidation implements FieldValidation, Predicate<Lis
   public boolean isValid( Map<String, Object> input
                         , Map<String, Object> validationConfig
                         , Map<String, Object> globalConfig
+                        , Context context
                         )
   {
     Predicate<Object> predicate = getPredicate();

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/network/IPValidation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/network/IPValidation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/network/IPValidation.java
index 0aa9075..94c32a5 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/network/IPValidation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/network/IPValidation.java
@@ -19,6 +19,7 @@
 package org.apache.metron.common.field.validation.network;
 
 import org.apache.commons.validator.routines.InetAddressValidator;
+import org.apache.metron.common.dsl.Context;
 import org.apache.metron.common.field.validation.FieldValidation;
 
 import java.util.List;
@@ -103,6 +104,7 @@ public class IPValidation implements FieldValidation, Predicate<List<Object>> {
   public boolean isValid( Map<String, Object> input
                         , Map<String, Object> validationConfig
                         , Map<String, Object> globalConfig
+                        , Context context
                         ) {
     IPType type = IPType.get(Config.TYPE.get(validationConfig, String.class));
     for(Object o : input.values()) {

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/DateValidation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/DateValidation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/DateValidation.java
index 85121e2..d0dc43e 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/DateValidation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/DateValidation.java
@@ -18,6 +18,7 @@
 
 package org.apache.metron.common.field.validation.primitive;
 
+import org.apache.metron.common.dsl.Context;
 import org.apache.metron.common.field.validation.FieldValidation;
 
 import java.text.ParseException;
@@ -80,6 +81,7 @@ public class DateValidation implements FieldValidation, Predicate<List<Object>>
   public boolean isValid( Map<String, Object> input
                         , Map<String, Object> validationConfig
                         , Map<String, Object> globalConfig
+                        , Context context
                         )
   {
     String format = Config.FORMAT.get(validationConfig, String.class);

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/RegexValidation.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/RegexValidation.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/RegexValidation.java
index 248eaff..fc44f40 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/RegexValidation.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/field/validation/primitive/RegexValidation.java
@@ -18,6 +18,7 @@
 
 package org.apache.metron.common.field.validation.primitive;
 
+import org.apache.metron.common.dsl.Context;
 import org.apache.metron.common.field.validation.FieldValidation;
 
 import java.util.Map;
@@ -44,6 +45,7 @@ public class RegexValidation implements FieldValidation {
   public boolean isValid( Map<String, Object> input
                         , Map<String, Object> validationConfig
                         , Map<String, Object> globalConfig
+                        , Context context
                         ) {
 
     String regex = Config.REGEX.get(validationConfig, String.class);

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
index ffd4b96..0ce374b 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
@@ -21,12 +21,12 @@ package org.apache.metron.common.stellar;
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.TokenStream;
-import org.apache.metron.common.dsl.ErrorListener;
-import org.apache.metron.common.dsl.ParseException;
-import org.apache.metron.common.dsl.VariableResolver;
+import org.apache.metron.common.dsl.*;
 import org.apache.metron.common.stellar.generated.StellarLexer;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
+import java.util.function.Function;
+
 import static org.apache.commons.lang3.StringUtils.isEmpty;
 
 public class BaseStellarProcessor<T> {
@@ -34,7 +34,12 @@ public class BaseStellarProcessor<T> {
   public BaseStellarProcessor(Class<T> clazz) {
     this.clazz = clazz;
   }
-  public T parse(String rule, VariableResolver resolver) {
+  public T parse( String rule
+                , VariableResolver variableResolver
+                , Function<String, StellarFunction> functionResolver
+                , Context context
+                )
+  {
     if (rule == null || isEmpty(rule.trim())) {
       return null;
     }
@@ -45,7 +50,7 @@ public class BaseStellarProcessor<T> {
     TokenStream tokens = new CommonTokenStream(lexer);
     StellarParser parser = new StellarParser(tokens);
 
-    StellarCompiler treeBuilder = new StellarCompiler(resolver);
+    StellarCompiler treeBuilder = new StellarCompiler(variableResolver, functionResolver, context);
     parser.addParseListener(treeBuilder);
     parser.removeErrorListeners();
     parser.addErrorListener(new ErrorListener());
@@ -58,7 +63,7 @@ public class BaseStellarProcessor<T> {
   }
   public boolean validate(String rule, boolean throwException) throws ParseException {
     try {
-      parse(rule, x -> null);
+      parse(rule, x -> null, StellarFunctions.FUNCTION_RESOLVER(), Context.EMPTY_CONTEXT());
       return true;
     }
     catch(Throwable t) {

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
index 6d92a07..8a91992 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
@@ -29,10 +29,18 @@ import java.util.*;
 import java.util.function.Function;
 
 public class StellarCompiler extends StellarBaseListener {
-  private VariableResolver resolver = null;
+  private Context context = null;
   private Stack<Token> tokenStack = new Stack<>();
-  public StellarCompiler(VariableResolver resolver) {
-    this.resolver = resolver;
+  private Function<String, StellarFunction> functionResolver;
+  private VariableResolver variableResolver;
+  public StellarCompiler( VariableResolver variableResolver
+                        , Function<String, StellarFunction> functionResolver
+                        , Context context
+                        )
+  {
+    this.variableResolver = variableResolver;
+    this.functionResolver = functionResolver;
+    this.context = context;
   }
 
   @Override
@@ -72,6 +80,12 @@ public class StellarCompiler extends StellarBaseListener {
     }
   }
 
+
+  @Override
+  public void exitNullConst(StellarParser.NullConstContext ctx) {
+    tokenStack.push(new Token<>(null, Object.class));
+  }
+
   @Override
   public void exitArithExpr_plus(StellarParser.ArithExpr_plusContext ctx) {
     Token<?> right = popStack();
@@ -103,7 +117,6 @@ public class StellarCompiler extends StellarBaseListener {
     tokenStack.push(new Token<>(l / r, Double.class));
   }
 
-
   @Override
   public void exitArithExpr_mul(StellarParser.ArithExpr_mulContext ctx) {
     Token<?> right = popStack();
@@ -113,8 +126,7 @@ public class StellarCompiler extends StellarBaseListener {
     tokenStack.push(new Token<>(l * r, Double.class));
   }
 
-  @Override
-  public void exitTernaryFunc(StellarParser.TernaryFuncContext ctx) {
+  private void handleConditional() {
     Token<?> elseExpr = popStack();
     Token<?> thenExpr = popStack();
     Token<?> ifExpr = popStack();
@@ -127,6 +139,18 @@ public class StellarCompiler extends StellarBaseListener {
     }
   }
 
+
+  @Override
+  public void exitTernaryFuncWithoutIf(StellarParser.TernaryFuncWithoutIfContext ctx) {
+    handleConditional();
+  }
+
+
+  @Override
+  public void exitTernaryFuncWithIf(StellarParser.TernaryFuncWithIfContext ctx) {
+    handleConditional();
+  }
+
   @Override
   public void exitInExpression(StellarParser.InExpressionContext ctx) {
     Token<?> left = popStack();
@@ -150,7 +174,7 @@ public class StellarCompiler extends StellarBaseListener {
 
   @Override
   public void exitVariable(StellarParser.VariableContext ctx) {
-    tokenStack.push(new Token<>(resolver.resolve(ctx.getText()), Object.class));
+    tokenStack.push(new Token<>(variableResolver.resolve(ctx.getText()), Object.class));
   }
 
   @Override
@@ -158,7 +182,6 @@ public class StellarCompiler extends StellarBaseListener {
     tokenStack.push(new Token<>(ctx.getText().substring(1, ctx.getText().length() - 1), String.class));
   }
 
-
   @Override
   public void exitIntLiteral(StellarParser.IntLiteralContext ctx) {
     tokenStack.push(new Token<>(Integer.parseInt(ctx.getText()), Integer.class));
@@ -214,15 +237,16 @@ public class StellarCompiler extends StellarBaseListener {
   @Override
   public void exitTransformationFunc(StellarParser.TransformationFuncContext ctx) {
     String funcName = ctx.getChild(0).getText();
-    Function<List<Object>, Object> func;
+    StellarFunction func = null;
     try {
-      func = StellarFunctions.valueOf(funcName);
+      func = functionResolver.apply(funcName);
     }
-    catch(IllegalArgumentException iae) {
+    catch(Exception iae) {
       throw new ParseException("Unable to find string function " + funcName + ".  Valid functions are "
               + Joiner.on(',').join(StellarFunctions.values())
       );
     }
+
     Token<?> left = popStack();
     List<Object> argList = null;
     if(left.getUnderlyingType().equals(List.class)) {
@@ -231,7 +255,7 @@ public class StellarCompiler extends StellarBaseListener {
     else {
       throw new ParseException("Unable to process in clause because " + left.getValue() + " is not a set");
     }
-    Object result = func.apply(argList);
+    Object result = func.apply(argList, context);
     tokenStack.push(new Token<>(result, Object.class));
   }
 
@@ -239,7 +263,7 @@ public class StellarCompiler extends StellarBaseListener {
   @Override
   public void exitExistsFunc(StellarParser.ExistsFuncContext ctx) {
     String variable = ctx.getChild(2).getText();
-    boolean exists = resolver.resolve(variable) != null;
+    boolean exists = variableResolver.resolve(variable) != null;
     tokenStack.push(new Token<>(exists, Boolean.class));
   }
 
@@ -248,7 +272,6 @@ public class StellarCompiler extends StellarBaseListener {
     tokenStack.push(new Token<>(new FunctionMarker(), FunctionMarker.class));
   }
 
-
   @Override
   public void exitFunc_args(StellarParser.Func_argsContext ctx) {
     LinkedList<Object> args = new LinkedList<>();
@@ -264,8 +287,32 @@ public class StellarCompiler extends StellarBaseListener {
     tokenStack.push(new Token<>(args, List.class));
   }
 
+  @Override
+  public void enterMap_entity(StellarParser.Map_entityContext ctx) {
+    tokenStack.push(new Token<>(new FunctionMarker(), FunctionMarker.class));
+  }
 
   @Override
+  public void exitMap_entity(StellarParser.Map_entityContext ctx) {
+    HashMap<String, Object> args = new HashMap<>();
+    Object value = null;
+    for(int i = 0;true;i++) {
+      Token<?> token = popStack();
+      if(token.getUnderlyingType().equals(FunctionMarker.class)) {
+        break;
+      }
+      else {
+        if(i % 2 == 0) {
+          value = token.getValue();
+        }
+        else {
+          args.put(token.getValue() + "" , value);
+        }
+      }
+    }
+    tokenStack.push(new Token<>(args, Map.class));
+  }
+  @Override
   public void exitList_entity(StellarParser.List_entityContext ctx) {
     LinkedList<Object> args = new LinkedList<>();
     while(true) {

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarPredicateProcessor.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarPredicateProcessor.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarPredicateProcessor.java
index e609880..093a8d8 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarPredicateProcessor.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarPredicateProcessor.java
@@ -19,8 +19,12 @@
 package org.apache.metron.common.stellar;
 
 
+import org.apache.metron.common.dsl.Context;
+import org.apache.metron.common.dsl.StellarFunction;
 import org.apache.metron.common.dsl.VariableResolver;
 
+import java.util.function.Function;
+
 import static org.apache.commons.lang3.StringUtils.isEmpty;
 
 /**
@@ -29,6 +33,7 @@ import static org.apache.commons.lang3.StringUtils.isEmpty;
  * tool, the output of the stellar statement is always a boolean.  In java parlance, this is like a
  * java.util.function.Predicate
  */
+
 public class StellarPredicateProcessor extends BaseStellarProcessor<Boolean> {
 
   public StellarPredicateProcessor() {
@@ -36,10 +41,15 @@ public class StellarPredicateProcessor extends BaseStellarProcessor<Boolean> {
   }
 
   @Override
-  public Boolean parse(String rule, VariableResolver resolver) {
+  public Boolean parse( String rule
+                      , VariableResolver variableResolver
+                      , Function<String, StellarFunction> functionResolver
+                      , Context context
+                      )
+  {
     if(rule == null || isEmpty(rule.trim())) {
       return true;
     }
-    return super.parse(rule, resolver);
+    return super.parse(rule, variableResolver, functionResolver, context);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
index f4ea0f4..69a8457 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
@@ -49,37 +49,37 @@ public class StellarBaseListener implements StellarListener {
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterComparisonExpression(StellarParser.ComparisonExpressionContext ctx) { }
+	@Override public void enterConditionalExpr(StellarParser.ConditionalExprContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitComparisonExpression(StellarParser.ComparisonExpressionContext ctx) { }
+	@Override public void exitConditionalExpr(StellarParser.ConditionalExprContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterTernaryFunc(StellarParser.TernaryFuncContext ctx) { }
+	@Override public void enterTransformationExpr(StellarParser.TransformationExprContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitTernaryFunc(StellarParser.TernaryFuncContext ctx) { }
+	@Override public void exitTransformationExpr(StellarParser.TransformationExprContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterNotFunc(StellarParser.NotFuncContext ctx) { }
+	@Override public void enterArithExpression(StellarParser.ArithExpressionContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitNotFunc(StellarParser.NotFuncContext ctx) { }
+	@Override public void exitArithExpression(StellarParser.ArithExpressionContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -97,61 +97,61 @@ public class StellarBaseListener implements StellarListener {
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterArithExpression(StellarParser.ArithExpressionContext ctx) { }
+	@Override public void enterComparisonExpression(StellarParser.ComparisonExpressionContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitArithExpression(StellarParser.ArithExpressionContext ctx) { }
+	@Override public void exitComparisonExpression(StellarParser.ComparisonExpressionContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterTransformationExpr(StellarParser.TransformationExprContext ctx) { }
+	@Override public void enterTernaryFuncWithoutIf(StellarParser.TernaryFuncWithoutIfContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitTransformationExpr(StellarParser.TransformationExprContext ctx) { }
+	@Override public void exitTernaryFuncWithoutIf(StellarParser.TernaryFuncWithoutIfContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterLogicalExpressionAnd(StellarParser.LogicalExpressionAndContext ctx) { }
+	@Override public void enterTernaryFuncWithIf(StellarParser.TernaryFuncWithIfContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitLogicalExpressionAnd(StellarParser.LogicalExpressionAndContext ctx) { }
+	@Override public void exitTernaryFuncWithIf(StellarParser.TernaryFuncWithIfContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterLogicalExpressionOr(StellarParser.LogicalExpressionOrContext ctx) { }
+	@Override public void enterNotFunc(StellarParser.NotFuncContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitLogicalExpressionOr(StellarParser.LogicalExpressionOrContext ctx) { }
+	@Override public void exitNotFunc(StellarParser.NotFuncContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterComparisonExpressionWithOperator(StellarParser.ComparisonExpressionWithOperatorContext ctx) { }
+	@Override public void enterComparisonExpressionParens(StellarParser.ComparisonExpressionParensContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitComparisonExpressionWithOperator(StellarParser.ComparisonExpressionWithOperatorContext ctx) { }
+	@Override public void exitComparisonExpressionParens(StellarParser.ComparisonExpressionParensContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -169,6 +169,30 @@ public class StellarBaseListener implements StellarListener {
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
+	@Override public void enterComparisonExpressionWithOperator(StellarParser.ComparisonExpressionWithOperatorContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitComparisonExpressionWithOperator(StellarParser.ComparisonExpressionWithOperatorContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterLogicalExpressionAnd(StellarParser.LogicalExpressionAndContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitLogicalExpressionAnd(StellarParser.LogicalExpressionAndContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
 	@Override public void enterNInExpression(StellarParser.NInExpressionContext ctx) { }
 	/**
 	 * {@inheritDoc}
@@ -181,13 +205,25 @@ public class StellarBaseListener implements StellarListener {
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterComparisonExpressionParens(StellarParser.ComparisonExpressionParensContext ctx) { }
+	@Override public void enterLogicalExpressionOr(StellarParser.LogicalExpressionOrContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitComparisonExpressionParens(StellarParser.ComparisonExpressionParensContext ctx) { }
+	@Override public void exitLogicalExpressionOr(StellarParser.LogicalExpressionOrContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterOperand(StellarParser.OperandContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitOperand(StellarParser.OperandContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -289,6 +325,30 @@ public class StellarBaseListener implements StellarListener {
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
+	@Override public void enterKv_list(StellarParser.Kv_listContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitKv_list(StellarParser.Kv_listContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterMap_entity(StellarParser.Map_entityContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitMap_entity(StellarParser.Map_entityContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
 	@Override public void enterArithExpr_solo(StellarParser.ArithExpr_soloContext ctx) { }
 	/**
 	 * {@inheritDoc}
@@ -481,6 +541,30 @@ public class StellarBaseListener implements StellarListener {
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
+	@Override public void enterMapConst(StellarParser.MapConstContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitMapConst(StellarParser.MapConstContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterNullConst(StellarParser.NullConstContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitNullConst(StellarParser.NullConstContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
 	@Override public void enterExistsFunc(StellarParser.ExistsFuncContext ctx) { }
 	/**
 	 * {@inheritDoc}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/1ea8d9ee/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarLexer.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarLexer.java b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarLexer.java
index 21c17e3..1f655ad 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarLexer.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarLexer.java
@@ -38,33 +38,33 @@ public class StellarLexer extends Lexer {
 		new PredictionContextCache();
 	public static final int
 		COMMA=1, AND=2, OR=3, NOT=4, TRUE=5, FALSE=6, EQ=7, NEQ=8, LT=9, LTE=10, 
-		GT=11, GTE=12, QUESTION=13, COLON=14, IF=15, MINUS=16, PLUS=17, DIV=18, 
-		MUL=19, LBRACKET=20, RBRACKET=21, LPAREN=22, RPAREN=23, IN=24, NIN=25, 
-		EXISTS=26, INT_LITERAL=27, DOUBLE_LITERAL=28, IDENTIFIER=29, STRING_LITERAL=30, 
-		COMMENT=31, WS=32;
+		GT=11, GTE=12, QUESTION=13, COLON=14, IF=15, THEN=16, ELSE=17, NULL=18, 
+		MINUS=19, PLUS=20, DIV=21, MUL=22, LBRACE=23, RBRACE=24, LBRACKET=25, 
+		RBRACKET=26, LPAREN=27, RPAREN=28, IN=29, NIN=30, EXISTS=31, INT_LITERAL=32, 
+		DOUBLE_LITERAL=33, IDENTIFIER=34, STRING_LITERAL=35, COMMENT=36, WS=37;
 	public static String[] modeNames = {
 		"DEFAULT_MODE"
 	};
 
 	public static final String[] ruleNames = {
 		"COMMA", "AND", "OR", "NOT", "TRUE", "FALSE", "EQ", "NEQ", "LT", "LTE", 
-		"GT", "GTE", "QUESTION", "COLON", "IF", "MINUS", "PLUS", "DIV", "MUL", 
-		"LBRACKET", "RBRACKET", "LPAREN", "RPAREN", "IN", "NIN", "EXISTS", "INT_LITERAL", 
-		"DOUBLE_LITERAL", "IDENTIFIER", "SCHAR", "STRING_LITERAL", "COMMENT", 
-		"WS"
+		"GT", "GTE", "QUESTION", "COLON", "IF", "THEN", "ELSE", "NULL", "MINUS", 
+		"PLUS", "DIV", "MUL", "LBRACE", "RBRACE", "LBRACKET", "RBRACKET", "LPAREN", 
+		"RPAREN", "IN", "NIN", "EXISTS", "INT_LITERAL", "DOUBLE_LITERAL", "IDENTIFIER", 
+		"SCHAR", "STRING_LITERAL", "COMMENT", "WS"
 	};
 
 	private static final String[] _LITERAL_NAMES = {
 		null, "','", null, null, null, null, null, "'=='", "'!='", "'<'", "'<='", 
-		"'>'", "'>='", null, null, null, "'-'", "'+'", "'/'", "'*'", "'['", "']'", 
-		"'('", "')'", "'in'", "'not in'"
+		"'>'", "'>='", "'?'", "':'", null, null, null, null, "'-'", "'+'", "'/'", 
+		"'*'", "'{'", "'}'", "'['", "']'", "'('", "')'", "'in'", "'not in'"
 	};
 	private static final String[] _SYMBOLIC_NAMES = {
 		null, "COMMA", "AND", "OR", "NOT", "TRUE", "FALSE", "EQ", "NEQ", "LT", 
-		"LTE", "GT", "GTE", "QUESTION", "COLON", "IF", "MINUS", "PLUS", "DIV", 
-		"MUL", "LBRACKET", "RBRACKET", "LPAREN", "RPAREN", "IN", "NIN", "EXISTS", 
-		"INT_LITERAL", "DOUBLE_LITERAL", "IDENTIFIER", "STRING_LITERAL", "COMMENT", 
-		"WS"
+		"LTE", "GT", "GTE", "QUESTION", "COLON", "IF", "THEN", "ELSE", "NULL", 
+		"MINUS", "PLUS", "DIV", "MUL", "LBRACE", "RBRACE", "LBRACKET", "RBRACKET", 
+		"LPAREN", "RPAREN", "IN", "NIN", "EXISTS", "INT_LITERAL", "DOUBLE_LITERAL", 
+		"IDENTIFIER", "STRING_LITERAL", "COMMENT", "WS"
 	};
 	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
 
@@ -121,97 +121,105 @@ public class StellarLexer extends Lexer {
 	public ATN getATN() { return _ATN; }
 
 	public static final String _serializedATN =
-		"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\"\u0110\b\1\4\2\t"+
+		"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\'\u012a\b\1\4\2\t"+
 		"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
 		"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
 		"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
 		"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
-		"\t!\4\"\t\"\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3P\n\3\3\4\3\4\3"+
-		"\4\3\4\3\4\3\4\5\4X\n\4\3\5\3\5\3\5\3\5\3\5\3\5\5\5`\n\5\3\6\3\6\3\6\3"+
-		"\6\3\6\3\6\3\6\3\6\5\6j\n\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5"+
-		"\7v\n\7\3\b\3\b\3\b\3\t\3\t\3\t\3\n\3\n\3\13\3\13\3\13\3\f\3\f\3\r\3\r"+
-		"\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\5\16\u0091\n\16\3\17"+
-		"\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\5\17\u009c\n\17\3\20\3\20\3\20"+
-		"\3\20\5\20\u00a2\n\20\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3\25"+
-		"\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32"+
-		"\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
-		"\5\33\u00ca\n\33\3\34\5\34\u00cd\n\34\3\34\6\34\u00d0\n\34\r\34\16\34"+
-		"\u00d1\3\35\5\35\u00d5\n\35\3\35\6\35\u00d8\n\35\r\35\16\35\u00d9\3\35"+
-		"\3\35\6\35\u00de\n\35\r\35\16\35\u00df\3\36\3\36\7\36\u00e4\n\36\f\36"+
-		"\16\36\u00e7\13\36\3\37\3\37\3 \3 \7 \u00ed\n \f \16 \u00f0\13 \3 \3 "+
-		"\3 \7 \u00f5\n \f \16 \u00f8\13 \3 \5 \u00fb\n \3!\3!\3!\3!\6!\u0101\n"+
-		"!\r!\16!\u0102\3!\5!\u0106\n!\3!\3!\3\"\6\"\u010b\n\"\r\"\16\"\u010c\3"+
-		"\"\3\"\3\u0102\2#\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31"+
-		"\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65"+
-		"\34\67\359\36;\37=\2? A!C\"\3\2\7\5\2C\\aac|\b\2\60\60\62;C\\^^aac|\7"+
-		"\2\f\f\17\17$$))^^\3\3\f\f\5\2\13\f\16\17\"\"\u0126\2\3\3\2\2\2\2\5\3"+
-		"\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2"+
-		"\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3"+
-		"\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'"+
-		"\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63"+
-		"\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2?\3\2\2\2\2"+
-		"A\3\2\2\2\2C\3\2\2\2\3E\3\2\2\2\5O\3\2\2\2\7W\3\2\2\2\t_\3\2\2\2\13i\3"+
-		"\2\2\2\ru\3\2\2\2\17w\3\2\2\2\21z\3\2\2\2\23}\3\2\2\2\25\177\3\2\2\2\27"+
-		"\u0082\3\2\2\2\31\u0084\3\2\2\2\33\u0090\3\2\2\2\35\u009b\3\2\2\2\37\u00a1"+
-		"\3\2\2\2!\u00a3\3\2\2\2#\u00a5\3\2\2\2%\u00a7\3\2\2\2\'\u00a9\3\2\2\2"+
-		")\u00ab\3\2\2\2+\u00ad\3\2\2\2-\u00af\3\2\2\2/\u00b1\3\2\2\2\61\u00b3"+
-		"\3\2\2\2\63\u00b6\3\2\2\2\65\u00c9\3\2\2\2\67\u00cc\3\2\2\29\u00d4\3\2"+
-		"\2\2;\u00e1\3\2\2\2=\u00e8\3\2\2\2?\u00fa\3\2\2\2A\u00fc\3\2\2\2C\u010a"+
-		"\3\2\2\2EF\7.\2\2F\4\3\2\2\2GH\7c\2\2HI\7p\2\2IP\7f\2\2JK\7(\2\2KP\7("+
-		"\2\2LM\7C\2\2MN\7P\2\2NP\7F\2\2OG\3\2\2\2OJ\3\2\2\2OL\3\2\2\2P\6\3\2\2"+
-		"\2QR\7q\2\2RX\7t\2\2ST\7~\2\2TX\7~\2\2UV\7Q\2\2VX\7T\2\2WQ\3\2\2\2WS\3"+
-		"\2\2\2WU\3\2\2\2X\b\3\2\2\2YZ\7p\2\2Z[\7q\2\2[`\7v\2\2\\]\7P\2\2]^\7Q"+
-		"\2\2^`\7V\2\2_Y\3\2\2\2_\\\3\2\2\2`\n\3\2\2\2ab\7v\2\2bc\7t\2\2cd\7w\2"+
-		"\2dj\7g\2\2ef\7V\2\2fg\7T\2\2gh\7W\2\2hj\7G\2\2ia\3\2\2\2ie\3\2\2\2j\f"+
-		"\3\2\2\2kl\7h\2\2lm\7c\2\2mn\7n\2\2no\7u\2\2ov\7g\2\2pq\7H\2\2qr\7C\2"+
-		"\2rs\7N\2\2st\7U\2\2tv\7G\2\2uk\3\2\2\2up\3\2\2\2v\16\3\2\2\2wx\7?\2\2"+
-		"xy\7?\2\2y\20\3\2\2\2z{\7#\2\2{|\7?\2\2|\22\3\2\2\2}~\7>\2\2~\24\3\2\2"+
-		"\2\177\u0080\7>\2\2\u0080\u0081\7?\2\2\u0081\26\3\2\2\2\u0082\u0083\7"+
-		"@\2\2\u0083\30\3\2\2\2\u0084\u0085\7@\2\2\u0085\u0086\7?\2\2\u0086\32"+
-		"\3\2\2\2\u0087\u0091\7A\2\2\u0088\u0089\7V\2\2\u0089\u008a\7J\2\2\u008a"+
-		"\u008b\7G\2\2\u008b\u0091\7P\2\2\u008c\u008d\7v\2\2\u008d\u008e\7j\2\2"+
-		"\u008e\u008f\7g\2\2\u008f\u0091\7p\2\2\u0090\u0087\3\2\2\2\u0090\u0088"+
-		"\3\2\2\2\u0090\u008c\3\2\2\2\u0091\34\3\2\2\2\u0092\u009c\7<\2\2\u0093"+
-		"\u0094\7G\2\2\u0094\u0095\7N\2\2\u0095\u0096\7U\2\2\u0096\u009c\7G\2\2"+
-		"\u0097\u0098\7g\2\2\u0098\u0099\7n\2\2\u0099\u009a\7u\2\2\u009a\u009c"+
-		"\7g\2\2\u009b\u0092\3\2\2\2\u009b\u0093\3\2\2\2\u009b\u0097\3\2\2\2\u009c"+
-		"\36\3\2\2\2\u009d\u009e\7K\2\2\u009e\u00a2\7H\2\2\u009f\u00a0\7k\2\2\u00a0"+
-		"\u00a2\7h\2\2\u00a1\u009d\3\2\2\2\u00a1\u009f\3\2\2\2\u00a2 \3\2\2\2\u00a3"+
-		"\u00a4\7/\2\2\u00a4\"\3\2\2\2\u00a5\u00a6\7-\2\2\u00a6$\3\2\2\2\u00a7"+
-		"\u00a8\7\61\2\2\u00a8&\3\2\2\2\u00a9\u00aa\7,\2\2\u00aa(\3\2\2\2\u00ab"+
-		"\u00ac\7]\2\2\u00ac*\3\2\2\2\u00ad\u00ae\7_\2\2\u00ae,\3\2\2\2\u00af\u00b0"+
-		"\7*\2\2\u00b0.\3\2\2\2\u00b1\u00b2\7+\2\2\u00b2\60\3\2\2\2\u00b3\u00b4"+
-		"\7k\2\2\u00b4\u00b5\7p\2\2\u00b5\62\3\2\2\2\u00b6\u00b7\7p\2\2\u00b7\u00b8"+
-		"\7q\2\2\u00b8\u00b9\7v\2\2\u00b9\u00ba\7\"\2\2\u00ba\u00bb\7k\2\2\u00bb"+
-		"\u00bc\7p\2\2\u00bc\64\3\2\2\2\u00bd\u00be\7g\2\2\u00be\u00bf\7z\2\2\u00bf"+
-		"\u00c0\7k\2\2\u00c0\u00c1\7u\2\2\u00c1\u00c2\7v\2\2\u00c2\u00ca\7u\2\2"+
-		"\u00c3\u00c4\7G\2\2\u00c4\u00c5\7Z\2\2\u00c5\u00c6\7K\2\2\u00c6\u00c7"+
-		"\7U\2\2\u00c7\u00c8\7V\2\2\u00c8\u00ca\7U\2\2\u00c9\u00bd\3\2\2\2\u00c9"+
-		"\u00c3\3\2\2\2\u00ca\66\3\2\2\2\u00cb\u00cd\5!\21\2\u00cc\u00cb\3\2\2"+
-		"\2\u00cc\u00cd\3\2\2\2\u00cd\u00cf\3\2\2\2\u00ce\u00d0\4\62;\2\u00cf\u00ce"+
-		"\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1\u00cf\3\2\2\2\u00d1\u00d2\3\2\2\2\u00d2"+
-		"8\3\2\2\2\u00d3\u00d5\5!\21\2\u00d4\u00d3\3\2\2\2\u00d4\u00d5\3\2\2\2"+
-		"\u00d5\u00d7\3\2\2\2\u00d6\u00d8\4\62;\2\u00d7\u00d6\3\2\2\2\u00d8\u00d9"+
-		"\3\2\2\2\u00d9\u00d7\3\2\2\2\u00d9\u00da\3\2\2\2\u00da\u00db\3\2\2\2\u00db"+
-		"\u00dd\7\60\2\2\u00dc\u00de\4\62;\2\u00dd\u00dc\3\2\2\2\u00de\u00df\3"+
-		"\2\2\2\u00df\u00dd\3\2\2\2\u00df\u00e0\3\2\2\2\u00e0:\3\2\2\2\u00e1\u00e5"+
-		"\t\2\2\2\u00e2\u00e4\t\3\2\2\u00e3\u00e2\3\2\2\2\u00e4\u00e7\3\2\2\2\u00e5"+
-		"\u00e3\3\2\2\2\u00e5\u00e6\3\2\2\2\u00e6<\3\2\2\2\u00e7\u00e5\3\2\2\2"+
-		"\u00e8\u00e9\n\4\2\2\u00e9>\3\2\2\2\u00ea\u00ee\7$\2\2\u00eb\u00ed\5="+
-		"\37\2\u00ec\u00eb\3\2\2\2\u00ed\u00f0\3\2\2\2\u00ee\u00ec\3\2\2\2\u00ee"+
-		"\u00ef\3\2\2\2\u00ef\u00f1\3\2\2\2\u00f0\u00ee\3\2\2\2\u00f1\u00fb\7$"+
-		"\2\2\u00f2\u00f6\7)\2\2\u00f3\u00f5\5=\37\2\u00f4\u00f3\3\2\2\2\u00f5"+
-		"\u00f8\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f6\u00f7\3\2\2\2\u00f7\u00f9\3\2"+
-		"\2\2\u00f8\u00f6\3\2\2\2\u00f9\u00fb\7)\2\2\u00fa\u00ea\3\2\2\2\u00fa"+
-		"\u00f2\3\2\2\2\u00fb@\3\2\2\2\u00fc\u00fd\7\61\2\2\u00fd\u00fe\7\61\2"+
-		"\2\u00fe\u0100\3\2\2\2\u00ff\u0101\13\2\2\2\u0100\u00ff\3\2\2\2\u0101"+
-		"\u0102\3\2\2\2\u0102\u0103\3\2\2\2\u0102\u0100\3\2\2\2\u0103\u0105\3\2"+
-		"\2\2\u0104\u0106\t\5\2\2\u0105\u0104\3\2\2\2\u0106\u0107\3\2\2\2\u0107"+
-		"\u0108\b!\2\2\u0108B\3\2\2\2\u0109\u010b\t\6\2\2\u010a\u0109\3\2\2\2\u010b"+
-		"\u010c\3\2\2\2\u010c\u010a\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2"+
-		"\2\2\u010e\u010f\b\"\2\2\u010fD\3\2\2\2\30\2OW_iu\u0090\u009b\u00a1\u00c9"+
-		"\u00cc\u00d1\u00d4\u00d9\u00df\u00e5\u00ee\u00f6\u00fa\u0102\u0105\u010c"+
-		"\3\b\2\2";
+		"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\3\2\3\2\3\3\3\3\3\3\3\3\3"+
+		"\3\3\3\3\3\3\3\5\3Z\n\3\3\4\3\4\3\4\3\4\3\4\3\4\5\4b\n\4\3\5\3\5\3\5\3"+
+		"\5\3\5\3\5\5\5j\n\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6t\n\6\3\7\3\7\3"+
+		"\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7\u0080\n\7\3\b\3\b\3\b\3\t\3\t\3\t\3"+
+		"\n\3\n\3\13\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20"+
+		"\3\20\3\20\5\20\u009a\n\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21"+
+		"\u00a4\n\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\5\22\u00ae\n\22\3"+
+		"\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u00b8\n\23\3\24\3\24\3\25"+
+		"\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\34"+
+		"\3\34\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3 \3"+
+		" \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \5 \u00e4\n \3!\5!\u00e7\n!\3!\6!\u00ea"+
+		"\n!\r!\16!\u00eb\3\"\5\"\u00ef\n\"\3\"\6\"\u00f2\n\"\r\"\16\"\u00f3\3"+
+		"\"\3\"\6\"\u00f8\n\"\r\"\16\"\u00f9\3#\3#\7#\u00fe\n#\f#\16#\u0101\13"+
+		"#\3$\3$\3%\3%\7%\u0107\n%\f%\16%\u010a\13%\3%\3%\3%\7%\u010f\n%\f%\16"+
+		"%\u0112\13%\3%\5%\u0115\n%\3&\3&\3&\3&\6&\u011b\n&\r&\16&\u011c\3&\5&"+
+		"\u0120\n&\3&\3&\3\'\6\'\u0125\n\'\r\'\16\'\u0126\3\'\3\'\3\u011c\2(\3"+
+		"\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37"+
+		"\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37="+
+		" ?!A\"C#E$G\2I%K&M\'\3\2\7\5\2C\\aac|\b\2\60\60\62;C\\^^aac|\7\2\f\f\17"+
+		"\17$$))^^\3\3\f\f\5\2\13\f\16\17\"\"\u013f\2\3\3\2\2\2\2\5\3\2\2\2\2\7"+
+		"\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2"+
+		"\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2"+
+		"\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2"+
+		"\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2"+
+		"\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2"+
+		"\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\3O"+
+		"\3\2\2\2\5Y\3\2\2\2\7a\3\2\2\2\ti\3\2\2\2\13s\3\2\2\2\r\177\3\2\2\2\17"+
+		"\u0081\3\2\2\2\21\u0084\3\2\2\2\23\u0087\3\2\2\2\25\u0089\3\2\2\2\27\u008c"+
+		"\3\2\2\2\31\u008e\3\2\2\2\33\u0091\3\2\2\2\35\u0093\3\2\2\2\37\u0099\3"+
+		"\2\2\2!\u00a3\3\2\2\2#\u00ad\3\2\2\2%\u00b7\3\2\2\2\'\u00b9\3\2\2\2)\u00bb"+
+		"\3\2\2\2+\u00bd\3\2\2\2-\u00bf\3\2\2\2/\u00c1\3\2\2\2\61\u00c3\3\2\2\2"+
+		"\63\u00c5\3\2\2\2\65\u00c7\3\2\2\2\67\u00c9\3\2\2\29\u00cb\3\2\2\2;\u00cd"+
+		"\3\2\2\2=\u00d0\3\2\2\2?\u00e3\3\2\2\2A\u00e6\3\2\2\2C\u00ee\3\2\2\2E"+
+		"\u00fb\3\2\2\2G\u0102\3\2\2\2I\u0114\3\2\2\2K\u0116\3\2\2\2M\u0124\3\2"+
+		"\2\2OP\7.\2\2P\4\3\2\2\2QR\7c\2\2RS\7p\2\2SZ\7f\2\2TU\7(\2\2UZ\7(\2\2"+
+		"VW\7C\2\2WX\7P\2\2XZ\7F\2\2YQ\3\2\2\2YT\3\2\2\2YV\3\2\2\2Z\6\3\2\2\2["+
+		"\\\7q\2\2\\b\7t\2\2]^\7~\2\2^b\7~\2\2_`\7Q\2\2`b\7T\2\2a[\3\2\2\2a]\3"+
+		"\2\2\2a_\3\2\2\2b\b\3\2\2\2cd\7p\2\2de\7q\2\2ej\7v\2\2fg\7P\2\2gh\7Q\2"+
+		"\2hj\7V\2\2ic\3\2\2\2if\3\2\2\2j\n\3\2\2\2kl\7v\2\2lm\7t\2\2mn\7w\2\2"+
+		"nt\7g\2\2op\7V\2\2pq\7T\2\2qr\7W\2\2rt\7G\2\2sk\3\2\2\2so\3\2\2\2t\f\3"+
+		"\2\2\2uv\7h\2\2vw\7c\2\2wx\7n\2\2xy\7u\2\2y\u0080\7g\2\2z{\7H\2\2{|\7"+
+		"C\2\2|}\7N\2\2}~\7U\2\2~\u0080\7G\2\2\177u\3\2\2\2\177z\3\2\2\2\u0080"+
+		"\16\3\2\2\2\u0081\u0082\7?\2\2\u0082\u0083\7?\2\2\u0083\20\3\2\2\2\u0084"+
+		"\u0085\7#\2\2\u0085\u0086\7?\2\2\u0086\22\3\2\2\2\u0087\u0088\7>\2\2\u0088"+
+		"\24\3\2\2\2\u0089\u008a\7>\2\2\u008a\u008b\7?\2\2\u008b\26\3\2\2\2\u008c"+
+		"\u008d\7@\2\2\u008d\30\3\2\2\2\u008e\u008f\7@\2\2\u008f\u0090\7?\2\2\u0090"+
+		"\32\3\2\2\2\u0091\u0092\7A\2\2\u0092\34\3\2\2\2\u0093\u0094\7<\2\2\u0094"+
+		"\36\3\2\2\2\u0095\u0096\7K\2\2\u0096\u009a\7H\2\2\u0097\u0098\7k\2\2\u0098"+
+		"\u009a\7h\2\2\u0099\u0095\3\2\2\2\u0099\u0097\3\2\2\2\u009a \3\2\2\2\u009b"+
+		"\u009c\7V\2\2\u009c\u009d\7J\2\2\u009d\u009e\7G\2\2\u009e\u00a4\7P\2\2"+
+		"\u009f\u00a0\7v\2\2\u00a0\u00a1\7j\2\2\u00a1\u00a2\7g\2\2\u00a2\u00a4"+
+		"\7p\2\2\u00a3\u009b\3\2\2\2\u00a3\u009f\3\2\2\2\u00a4\"\3\2\2\2\u00a5"+
+		"\u00a6\7G\2\2\u00a6\u00a7\7N\2\2\u00a7\u00a8\7U\2\2\u00a8\u00ae\7G\2\2"+
+		"\u00a9\u00aa\7g\2\2\u00aa\u00ab\7n\2\2\u00ab\u00ac\7u\2\2\u00ac\u00ae"+
+		"\7g\2\2\u00ad\u00a5\3\2\2\2\u00ad\u00a9\3\2\2\2\u00ae$\3\2\2\2\u00af\u00b0"+
+		"\7p\2\2\u00b0\u00b1\7w\2\2\u00b1\u00b2\7n\2\2\u00b2\u00b8\7n\2\2\u00b3"+
+		"\u00b4\7P\2\2\u00b4\u00b5\7W\2\2\u00b5\u00b6\7N\2\2\u00b6\u00b8\7N\2\2"+
+		"\u00b7\u00af\3\2\2\2\u00b7\u00b3\3\2\2\2\u00b8&\3\2\2\2\u00b9\u00ba\7"+
+		"/\2\2\u00ba(\3\2\2\2\u00bb\u00bc\7-\2\2\u00bc*\3\2\2\2\u00bd\u00be\7\61"+
+		"\2\2\u00be,\3\2\2\2\u00bf\u00c0\7,\2\2\u00c0.\3\2\2\2\u00c1\u00c2\7}\2"+
+		"\2\u00c2\60\3\2\2\2\u00c3\u00c4\7\177\2\2\u00c4\62\3\2\2\2\u00c5\u00c6"+
+		"\7]\2\2\u00c6\64\3\2\2\2\u00c7\u00c8\7_\2\2\u00c8\66\3\2\2\2\u00c9\u00ca"+
+		"\7*\2\2\u00ca8\3\2\2\2\u00cb\u00cc\7+\2\2\u00cc:\3\2\2\2\u00cd\u00ce\7"+
+		"k\2\2\u00ce\u00cf\7p\2\2\u00cf<\3\2\2\2\u00d0\u00d1\7p\2\2\u00d1\u00d2"+
+		"\7q\2\2\u00d2\u00d3\7v\2\2\u00d3\u00d4\7\"\2\2\u00d4\u00d5\7k\2\2\u00d5"+
+		"\u00d6\7p\2\2\u00d6>\3\2\2\2\u00d7\u00d8\7g\2\2\u00d8\u00d9\7z\2\2\u00d9"+
+		"\u00da\7k\2\2\u00da\u00db\7u\2\2\u00db\u00dc\7v\2\2\u00dc\u00e4\7u\2\2"+
+		"\u00dd\u00de\7G\2\2\u00de\u00df\7Z\2\2\u00df\u00e0\7K\2\2\u00e0\u00e1"+
+		"\7U\2\2\u00e1\u00e2\7V\2\2\u00e2\u00e4\7U\2\2\u00e3\u00d7\3\2\2\2\u00e3"+
+		"\u00dd\3\2\2\2\u00e4@\3\2\2\2\u00e5\u00e7\5\'\24\2\u00e6\u00e5\3\2\2\2"+
+		"\u00e6\u00e7\3\2\2\2\u00e7\u00e9\3\2\2\2\u00e8\u00ea\4\62;\2\u00e9\u00e8"+
+		"\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00e9\3\2\2\2\u00eb\u00ec\3\2\2\2\u00ec"+
+		"B\3\2\2\2\u00ed\u00ef\5\'\24\2\u00ee\u00ed\3\2\2\2\u00ee\u00ef\3\2\2\2"+
+		"\u00ef\u00f1\3\2\2\2\u00f0\u00f2\4\62;\2\u00f1\u00f0\3\2\2\2\u00f2\u00f3"+
+		"\3\2\2\2\u00f3\u00f1\3\2\2\2\u00f3\u00f4\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5"+
+		"\u00f7\7\60\2\2\u00f6\u00f8\4\62;\2\u00f7\u00f6\3\2\2\2\u00f8\u00f9\3"+
+		"\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2\u00faD\3\2\2\2\u00fb\u00ff"+
+		"\t\2\2\2\u00fc\u00fe\t\3\2\2\u00fd\u00fc\3\2\2\2\u00fe\u0101\3\2\2\2\u00ff"+
+		"\u00fd\3\2\2\2\u00ff\u0100\3\2\2\2\u0100F\3\2\2\2\u0101\u00ff\3\2\2\2"+
+		"\u0102\u0103\n\4\2\2\u0103H\3\2\2\2\u0104\u0108\7$\2\2\u0105\u0107\5G"+
+		"$\2\u0106\u0105\3\2\2\2\u0107\u010a\3\2\2\2\u0108\u0106\3\2\2\2\u0108"+
+		"\u0109\3\2\2\2\u0109\u010b\3\2\2\2\u010a\u0108\3\2\2\2\u010b\u0115\7$"+
+		"\2\2\u010c\u0110\7)\2\2\u010d\u010f\5G$\2\u010e\u010d\3\2\2\2\u010f\u0112"+
+		"\3\2\2\2\u0110\u010e\3\2\2\2\u0110\u0111\3\2\2\2\u0111\u0113\3\2\2\2\u0112"+
+		"\u0110\3\2\2\2\u0113\u0115\7)\2\2\u0114\u0104\3\2\2\2\u0114\u010c\3\2"+
+		"\2\2\u0115J\3\2\2\2\u0116\u0117\7\61\2\2\u0117\u0118\7\61\2\2\u0118\u011a"+
+		"\3\2\2\2\u0119\u011b\13\2\2\2\u011a\u0119\3\2\2\2\u011b\u011c\3\2\2\2"+
+		"\u011c\u011d\3\2\2\2\u011c\u011a\3\2\2\2\u011d\u011f\3\2\2\2\u011e\u0120"+
+		"\t\5\2\2\u011f\u011e\3\2\2\2\u0120\u0121\3\2\2\2\u0121\u0122\b&\2\2\u0122"+
+		"L\3\2\2\2\u0123\u0125\t\6\2\2\u0124\u0123\3\2\2\2\u0125\u0126\3\2\2\2"+
+		"\u0126\u0124\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128\3\2\2\2\u0128\u0129"+
+		"\b\'\2\2\u0129N\3\2\2\2\31\2Yais\177\u0099\u00a3\u00ad\u00b7\u00e3\u00e6"+
+		"\u00eb\u00ee\u00f3\u00f9\u00ff\u0108\u0110\u0114\u011c\u011f\u0126\3\b"+
+		"\2\2";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {


Mime
View raw message