Repository: metron
Updated Branches:
  refs/heads/feature/METRON-1554-pcap-query-panel 6c90724d8 -> 7dff4def2


METRON-1606 Add a 'wrap' to incoming messages in the metron json 
parser (ottobackwards) closes apache/metron#1054


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/6bac842d
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/6bac842d
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/6bac842d

Branch: refs/heads/feature/METRON-1554-pcap-query-panel
Commit: 6bac842d7ad2819c56412837d8befb603ef15f35
Parents: aceca46
Author: ottobackwards <ottobackwa...@gmail.com>
Authored: Fri Jul 20 17:44:35 2018 -0400
Committer: otto <o...@apache.org>
Committed: Fri Jul 20 17:44:35 2018 -0400

----------------------------------------------------------------------
 .../docker/rpm-docker/SPECS/metron.spec         |   1 +
 .../parsed/jsonMapExampleParsed                 |   6 +
 .../raw/jsonMapExampleOutput                    |   3 +
 metron-platform/metron-parsers/README.md        |   5 +
 .../zookeeper/parsers/jsonMapWrappedQuery.json  |   5 +
 .../metron/parsers/json/JSONMapParser.java      |  40 +++-
 .../JSONMapWrappedQueryIntegrationTest.java     |  37 ++++
 .../integration/ParserIntegrationTest.java      |  22 +-
 .../json/JSONMapParserWrappedQueryTest.java     | 199 +++++++++++++++++++
 9 files changed, 299 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-deployment/packaging/docker/rpm-docker/SPECS/metron.spec
----------------------------------------------------------------------
diff --git a/metron-deployment/packaging/docker/rpm-docker/SPECS/metron.spec 
b/metron-deployment/packaging/docker/rpm-docker/SPECS/metron.spec
index 4b88fd0..b308908 100644
--- a/metron-deployment/packaging/docker/rpm-docker/SPECS/metron.spec
+++ b/metron-deployment/packaging/docker/rpm-docker/SPECS/metron.spec
@@ -151,6 +151,7 @@ This package installs the Metron Parser files
 %{metron_home}/config/zookeeper/parsers/bro.json
 %{metron_home}/config/zookeeper/parsers/jsonMap.json
 %{metron_home}/config/zookeeper/parsers/jsonMapQuery.json
+%{metron_home}/config/zookeeper/parsers/jsonMapWrappedQuery.json
 %{metron_home}/config/zookeeper/parsers/snort.json
 %{metron_home}/config/zookeeper/parsers/squid.json
 %{metron_home}/config/zookeeper/parsers/websphere.json

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/parsed/jsonMapExampleParsed
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/parsed/jsonMapExampleParsed
 
b/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/parsed/jsonMapExampleParsed
new file mode 100644
index 0000000..c6aac78
--- /dev/null
+++ 
b/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/parsed/jsonMapExampleParsed
@@ -0,0 +1,6 @@
+{ "string" : "foo", "number" : 1, "ignored" : [ "blah" ], "original_string":"{ 
\"string\" : \"foo\", \"number\" : 1, \"ignored\" : [ \"blah\" ] 
}","timestamp":1000000000000, 
"source.type":"jsonMapWrappedQuery","guid":"this-is-random-uuid-will-be-36-chars"
 }
+{ "number" : 4 , "original_string" : "{ \"number\" : 4 }", 
"source.type":"jsonMapWrappedQuery","timestamp":1000000000000,"guid":"this-is-random-uuid-will-be-36-chars"}
+{ "string" : "bar", "number" : 2, "ignored" : [ "blah" ], "original_string":"{ 
\"string\" : \"bar\", \"number\" : 2, \"ignored\" : [ \"blah\" ] 
}","timestamp":1000000000000, 
"source.type":"jsonMapWrappedQuery","guid":"this-is-random-uuid-will-be-36-chars"
 }
+{ "number" : 5 , "original_string" : "{ \"number\" : 5 }", 
"source.type":"jsonMapWrappedQuery","timestamp":1000000000000,"guid":"this-is-random-uuid-will-be-36-chars"}
+{ "string" : "baz", "number" : 3, "ignored" : [ "blah" ], "original_string":"{ 
\"string\" : \"baz\", \"number\" : 3, \"ignored\" : [ \"blah\" ] 
}","timestamp":1000000000000, 
"source.type":"jsonMapWrappedQuery","guid":"this-is-random-uuid-will-be-36-chars"
 }
+{ "number" : 6 , "original_string" : "{ \"number\" : 6 }", 
"source.type":"jsonMapWrappedQuery","timestamp":1000000000000,"guid":"this-is-random-uuid-will-be-36-chars"}

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/raw/jsonMapExampleOutput
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/raw/jsonMapExampleOutput
 
b/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/raw/jsonMapExampleOutput
new file mode 100644
index 0000000..f142a55
--- /dev/null
+++ 
b/metron-platform/metron-integration-test/src/main/sample/data/jsonMapWrappedQuery/raw/jsonMapExampleOutput
@@ -0,0 +1,3 @@
+{ "string" : "foo", "number" : 1, "ignored" : [ "blah" ] },{ "number" : 4 },
+{ "string" : "bar", "number" : 2, "ignored" : [ "blah" ] },{ "number" : 5 },
+{ "string" : "baz", "number" : 3, "ignored" : [ "blah" ] },{ "number" : 6 }

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-parsers/README.md
----------------------------------------------------------------------
diff --git a/metron-platform/metron-parsers/README.md 
b/metron-platform/metron-parsers/README.md
index 0e428e3..fd6b470 100644
--- a/metron-platform/metron-parsers/README.md
+++ b/metron-platform/metron-parsers/README.md
@@ -44,6 +44,11 @@ There are two general types types of parsers:
       * `ALLOW` : Allow multidimensional maps
       * `ERROR` : Throw an error when a multidimensional map is encountered
     * `jsonpQuery` : A [JSON Path](#json_path) query string. If present, the 
result of the JSON Path query should be a list of messages. This is useful if 
you have a JSON document which contains a list or array of messages embedded in 
it, and you do not have another means of splitting the message.
+    * `wrapInEntityArray` : `"true" or "false"`. If `jsonQuery` is present and 
this flag is present and set to `"true"`, the incoming message will be wrapped 
in a JSON  entity and array.
+       for example:
+       `{"name":"value"},{"name2","value2}` will be wrapped as `{"message" : 
[{"name":"value"},{"name2","value2}]}`.
+       This is using the default value for `wrapEntityName` if that property 
is not set.
+    * `wrapEntityName` : Sets the name to use when wrapping JSON using 
`wrapInEntityArray`.  The `jsonpQuery` should reference this name.
     * A field called `timestamp` is expected to exist and, if it does not, 
then current time is inserted.  
 
 ## Parser Error Routing

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-parsers/src/main/config/zookeeper/parsers/jsonMapWrappedQuery.json
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-parsers/src/main/config/zookeeper/parsers/jsonMapWrappedQuery.json
 
b/metron-platform/metron-parsers/src/main/config/zookeeper/parsers/jsonMapWrappedQuery.json
new file mode 100644
index 0000000..3e960e0
--- /dev/null
+++ 
b/metron-platform/metron-parsers/src/main/config/zookeeper/parsers/jsonMapWrappedQuery.json
@@ -0,0 +1,5 @@
+{
+  "parserClassName":"org.apache.metron.parsers.json.JSONMapParser",
+  "sensorTopic":"jsonMapWrappedQuery",
+  "parserConfig": 
{"jsonpQuery":"$.foo","wrapInEntityArray":"true","wrapEntityName":"foo"}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-parsers/src/main/java/org/apache/metron/parsers/json/JSONMapParser.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-parsers/src/main/java/org/apache/metron/parsers/json/JSONMapParser.java
 
b/metron-platform/metron-parsers/src/main/java/org/apache/metron/parsers/json/JSONMapParser.java
index f5d67f9..0acc96c 100644
--- 
a/metron-platform/metron-parsers/src/main/java/org/apache/metron/parsers/json/JSONMapParser.java
+++ 
b/metron-platform/metron-parsers/src/main/java/org/apache/metron/parsers/json/JSONMapParser.java
@@ -35,6 +35,7 @@ import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.metron.common.utils.JSONUtils;
 import org.apache.metron.parsers.BasicParser;
@@ -87,10 +88,18 @@ public class JSONMapParser extends BasicParser {
 
   public static final String MAP_STRATEGY_CONFIG = "mapStrategy";
   public static final String JSONP_QUERY = "jsonpQuery";
+  public static final String WRAP_JSON = "wrapInEntityArray";
+  public static final String WRAP_ENTITY_NAME = "wrapEntityName";
+  public static final String DEFAULT_WRAP_ENTITY_NAME = "messages";
+
+  private static final String WRAP_START_FMT = "{ \"%s\" : [";
+  private static final String WRAP_END = "]}";
 
   private MapStrategy mapStrategy = MapStrategy.DROP;
   private transient TypeRef<List<Map<String, Object>>> typeRef = null;
   private String jsonpQuery = null;
+  private String wrapEntityName = DEFAULT_WRAP_ENTITY_NAME;
+  private boolean wrapJson = false;
 
 
   @Override
@@ -100,6 +109,20 @@ public class JSONMapParser extends BasicParser {
     if (config.containsKey(JSONP_QUERY)) {
       typeRef = new TypeRef<List<Map<String, Object>>>() { };
       jsonpQuery = (String) config.get(JSONP_QUERY);
+
+      if (!StringUtils.isBlank(jsonpQuery) && config.containsKey(WRAP_JSON)) {
+        Object wrapObject = config.get(WRAP_JSON);
+        if (wrapObject instanceof String) {
+          wrapJson = Boolean.valueOf((String)wrapObject);
+        } else if (wrapObject instanceof Boolean) {
+          wrapJson = (Boolean) config.get(WRAP_JSON);
+        }
+        String entityName = (String)config.get(WRAP_ENTITY_NAME);
+        if (!StringUtils.isBlank(entityName)) {
+          wrapEntityName = entityName;
+        }
+      }
+
       Configuration.setDefaults(new Configuration.Defaults() {
 
         private final JsonProvider jsonProvider = new JacksonJsonProvider();
@@ -147,9 +170,14 @@ public class JSONMapParser extends BasicParser {
       String originalString = new String(rawMessage);
       List<Map<String, Object>> messages = new ArrayList<>();
 
+      // if configured, wrap the json in an entity and array
+      if (wrapJson) {
+        originalString = wrapMessageJson(originalString);
+      }
+
       if (!StringUtils.isEmpty(jsonpQuery)) {
-        Object parsedObject = JsonPath.parse(new 
String(rawMessage)).read(jsonpQuery, typeRef);
-        if(parsedObject != null) {
+        Object parsedObject = JsonPath.parse(originalString).read(jsonpQuery, 
typeRef);
+        if (parsedObject != null) {
           messages.addAll((List<Map<String,Object>>)parsedObject);
         }
       } else {
@@ -192,4 +220,12 @@ public class JSONMapParser extends BasicParser {
     return ret;
   }
 
+  private String wrapMessageJson(String jsonMessage) {
+    String base = new 
StringBuilder(String.format(WRAP_START_FMT,wrapEntityName))
+            .append(jsonMessage).toString().trim();
+    if (base.endsWith(",")) {
+      base = base.substring(0, base.length() - 1);
+    }
+    return base + WRAP_END;
+  }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/JSONMapWrappedQueryIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/JSONMapWrappedQueryIntegrationTest.java
 
b/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/JSONMapWrappedQueryIntegrationTest.java
new file mode 100644
index 0000000..569e175
--- /dev/null
+++ 
b/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/JSONMapWrappedQueryIntegrationTest.java
@@ -0,0 +1,37 @@
+/**
+ * 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.parsers.integration;
+
+import org.apache.metron.parsers.integration.validation.SampleDataValidation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JSONMapWrappedQueryIntegrationTest extends ParserIntegrationTest {
+  @Override
+  String getSensorType() {
+    return "jsonMapWrappedQuery";
+  }
+
+  @Override
+  List<ParserValidation> getValidations() {
+    return new ArrayList<ParserValidation>() {{
+      add(new SampleDataValidation());
+    }};
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/ParserIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/ParserIntegrationTest.java
 
b/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/ParserIntegrationTest.java
index cd3d005..6b00a2b 100644
--- 
a/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/ParserIntegrationTest.java
+++ 
b/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/integration/ParserIntegrationTest.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -17,31 +17,19 @@
  */
 package org.apache.metron.parsers.integration;
 
-import com.google.common.base.Function;
 import org.apache.metron.TestConstants;
-import org.apache.metron.common.Constants;
-import 
org.apache.metron.enrichment.integration.components.ConfigUploadComponent;
-import org.apache.metron.integration.*;
-import org.apache.metron.integration.components.KafkaComponent;
-import org.apache.metron.integration.processors.KafkaMessageSet;
-import org.apache.metron.integration.components.ZKServerComponent;
-import org.apache.metron.integration.processors.KafkaProcessor;
+import org.apache.metron.integration.BaseIntegrationTest;
+import org.apache.metron.integration.ProcessorResult;
 import org.apache.metron.integration.utils.TestUtils;
-import 
org.apache.metron.parsers.integration.components.ParserTopologyComponent;
 import org.apache.metron.test.TestDataType;
 import org.apache.metron.test.utils.SampleDataUtils;
-import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 
-import javax.annotation.Nullable;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
-import java.util.*;
+import java.util.List;
 
 public abstract class ParserIntegrationTest extends BaseIntegrationTest {
   protected List<byte[]> inputMessages;
@@ -74,7 +62,7 @@ public abstract class ParserIntegrationTest extends 
BaseIntegrationTest {
     } else {
       List<ParserValidation> validations = getValidations();
       if (validations == null || validations.isEmpty()) {
-        buffer.append("No validations configured for sensorType " + sensorType 
+ ".  Dumping parsed messages").append("\n");
+        buffer.append("No validations configured for sensorType 
").append(sensorType).append(".  Dumping parsed messages").append("\n");
         dumpParsedMessages(outputMessages,buffer);
         Assert.fail(buffer.toString());
       } else {

http://git-wip-us.apache.org/repos/asf/metron/blob/6bac842d/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/json/JSONMapParserWrappedQueryTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/json/JSONMapParserWrappedQueryTest.java
 
b/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/json/JSONMapParserWrappedQueryTest.java
new file mode 100644
index 0000000..0da45dd
--- /dev/null
+++ 
b/metron-platform/metron-parsers/src/test/java/org/apache/metron/parsers/json/JSONMapParserWrappedQueryTest.java
@@ -0,0 +1,199 @@
+/**
+ * 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.parsers.json;
+
+import com.google.common.collect.ImmutableMap;
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.log4j.Level;
+import org.apache.metron.parsers.BasicParser;
+import org.apache.metron.test.utils.UnitTestHelper;
+import org.json.simple.JSONObject;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class JSONMapParserWrappedQueryTest {
+
+  /**
+   * { "name" : "foo1", "value" : "bar", "number" : 1.0 },
+   * { "name" : "foo2", "value" : "baz", "number" : 2.0 }
+   */
+  @Multiline
+  static String JSON_LIST;
+
+  /**
+   * { "name" : "foo1", "value" : "bar", "number" : 1.0 }
+   */
+  @Multiline
+  static String JSON_SINGLE;
+
+  /**
+   * { "name" : "foo2", "value" : "baz", "number" : 2.0 }
+   */
+  @Multiline
+  static String JSON_SINGLE2;
+
+  @Test
+  public void testHappyPath() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(new HashMap<String, Object>() {{
+      put(JSONMapParser.WRAP_JSON,true);
+      put(JSONMapParser.WRAP_ENTITY_NAME,"foo");
+      put(JSONMapParser.JSONP_QUERY, "$.foo");
+    }});
+    List<JSONObject> output = parser.parse(JSON_LIST.getBytes());
+    Assert.assertEquals(output.size(), 2);
+    //don't forget the timestamp field!
+    Assert.assertEquals(output.get(0).size(), 5);
+    JSONObject message = output.get(0);
+    Assert.assertEquals("foo1", message.get("name"));
+    Assert.assertEquals("bar", message.get("value"));
+    Assert.assertEquals(1.0, message.get("number"));
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+    Assert.assertNotNull(message.get("number"));
+    Assert.assertTrue(message.get("number") instanceof Number);
+
+    message = output.get(1);
+    Assert.assertEquals("foo2", message.get("name"));
+    Assert.assertEquals("baz", message.get("value"));
+    Assert.assertEquals(2.0, message.get("number"));
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+    Assert.assertNotNull(message.get("number"));
+    Assert.assertTrue(message.get("number") instanceof Number);
+
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void testInvalidJSONPathThrows() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(new HashMap<String, Object>() {{
+      put(JSONMapParser.JSONP_QUERY, "$$..$$SDSE$#$#.");
+    }});
+    List<JSONObject> output = parser.parse(JSON_LIST.getBytes());
+
+  }
+
+  @Test
+  public void testNoMatchesNoExceptions() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(new HashMap<String, Object>() {{
+      put(JSONMapParser.JSONP_QUERY, "$.foo");
+    }});
+    List<JSONObject> output = parser.parse(JSON_SINGLE.getBytes());
+    Assert.assertEquals(0, output.size());
+  }
+
+  /**
+   * {
+   * "foo" :
+   * [
+   * {
+   * "collection" : { "blah" : 7, "blah2" : "foo", "bigblah" : { "innerBlah" : 
"baz", "reallyInnerBlah" : { "color" : "grey" }}}
+   * },
+   * {
+   * "collection" : { "blah" : 8, "blah2" : "bar", "bigblah" : { "innerBlah" : 
"baz2", "reallyInnerBlah" : { "color" : "blue" }}}
+   * }
+   * ]
+   * }
+   */
+  @Multiline
+  static String collectionHandlingJSON;
+
+  @Test
+  public void testCollectionHandlingDrop() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(new HashMap<String, Object>() {{
+      put(JSONMapParser.JSONP_QUERY, "$.foo");
+    }});
+    List<JSONObject> output = parser.parse(collectionHandlingJSON.getBytes());
+    Assert.assertEquals(output.size(), 2);
+
+    //don't forget the timestamp field!
+    Assert.assertEquals(output.get(0).size(), 2);
+
+    JSONObject message = output.get(0);
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+
+    message = output.get(1);
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void testCollectionHandlingError() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(ImmutableMap
+        .of(JSONMapParser.MAP_STRATEGY_CONFIG, 
JSONMapParser.MapStrategy.ERROR.name(),
+            JSONMapParser.JSONP_QUERY, "$.foo"));
+    UnitTestHelper.setLog4jLevel(BasicParser.class, Level.FATAL);
+    parser.parse(collectionHandlingJSON.getBytes());
+    UnitTestHelper.setLog4jLevel(BasicParser.class, Level.ERROR);
+  }
+
+
+  @Test
+  public void testCollectionHandlingAllow() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(ImmutableMap
+        .of(JSONMapParser.MAP_STRATEGY_CONFIG, 
JSONMapParser.MapStrategy.ALLOW.name(),
+            JSONMapParser.JSONP_QUERY, "$.foo"));
+    List<JSONObject> output = parser.parse(collectionHandlingJSON.getBytes());
+    Assert.assertEquals(output.size(), 2);
+    Assert.assertEquals(output.get(0).size(), 3);
+    JSONObject message = output.get(0);
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+
+    Assert.assertEquals(output.get(1).size(), 3);
+    message = output.get(1);
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+  }
+
+  @Test
+  public void testCollectionHandlingUnfold() {
+    JSONMapParser parser = new JSONMapParser();
+    parser.configure(ImmutableMap
+        .of(JSONMapParser.MAP_STRATEGY_CONFIG, 
JSONMapParser.MapStrategy.UNFOLD.name(),
+            JSONMapParser.JSONP_QUERY, "$.foo"));
+    List<JSONObject> output = parser.parse(collectionHandlingJSON.getBytes());
+    Assert.assertEquals(output.size(), 2);
+    Assert.assertEquals(output.get(0).size(), 6);
+    JSONObject message = output.get(0);
+    Assert.assertEquals(message.get("collection.blah"), 7);
+    Assert.assertEquals(message.get("collection.blah2"), "foo");
+    Assert.assertEquals(message.get("collection.bigblah.innerBlah"), "baz");
+    
Assert.assertEquals(message.get("collection.bigblah.reallyInnerBlah.color"), 
"grey");
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+
+    Assert.assertEquals(output.get(1).size(), 6);
+    message = output.get(1);
+    Assert.assertEquals(message.get("collection.blah"), 8);
+    Assert.assertEquals(message.get("collection.blah2"), "bar");
+    Assert.assertEquals(message.get("collection.bigblah.innerBlah"), "baz2");
+    
Assert.assertEquals(message.get("collection.bigblah.reallyInnerBlah.color"), 
"blue");
+    Assert.assertNotNull(message.get("timestamp"));
+    Assert.assertTrue(message.get("timestamp") instanceof Number);
+  }
+}

Reply via email to