Repository: metron
Updated Branches:
  refs/heads/master 0d1923f83 -> cf7043c59


http://git-wip-us.apache.org/repos/asf/metron/blob/cf7043c5/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResult.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResult.java
 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResult.java
new file mode 100644
index 0000000..ae4f9bd
--- /dev/null
+++ 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResult.java
@@ -0,0 +1,51 @@
+/**
+ * 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.indexing.dao.search;
+
+import java.util.Map;
+
+public class SearchResult {
+
+  private String id;
+  private Map<String, Object> source;
+  private float score;
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public Map<String, Object> getSource() {
+    return source;
+  }
+
+  public void setSource(Map<String, Object> source) {
+    this.source = source;
+  }
+
+  public float getScore() {
+    return score;
+  }
+
+  public void setScore(float score) {
+    this.score = score;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/cf7043c5/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortField.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortField.java
 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortField.java
new file mode 100644
index 0000000..a3473fc
--- /dev/null
+++ 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortField.java
@@ -0,0 +1,39 @@
+/**
+ * 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.indexing.dao.search;
+
+public class SortField {
+  private String field;
+  private SortOrder sortOrder;
+
+  public String getField() {
+    return field;
+  }
+
+  public void setField(String field) {
+    this.field = field;
+  }
+
+  public SortOrder getSortOrder() {
+    return sortOrder;
+  }
+
+  public void setSortOrder(String sortOrder) {
+    this.sortOrder = SortOrder.fromString(sortOrder);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/cf7043c5/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortOrder.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortOrder.java
 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortOrder.java
new file mode 100644
index 0000000..fde3279
--- /dev/null
+++ 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SortOrder.java
@@ -0,0 +1,41 @@
+/**
+ * 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.indexing.dao.search;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum SortOrder {
+  @JsonProperty("desc")
+  DESC("desc"),
+  @JsonProperty("asc")
+  ASC("asc");
+
+  private String sortOrder;
+
+  SortOrder(String sortOrder) {
+    this.sortOrder = sortOrder;
+  }
+
+  public String getSortOrder() {
+    return sortOrder;
+  }
+
+  public static SortOrder fromString(String order) {
+    return SortOrder.valueOf(order.toUpperCase());
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/cf7043c5/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryDao.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryDao.java
 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryDao.java
new file mode 100644
index 0000000..444a9da
--- /dev/null
+++ 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryDao.java
@@ -0,0 +1,142 @@
+/**
+ * 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.indexing.dao;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Iterables;
+import org.apache.metron.common.Constants;
+import org.apache.metron.common.utils.JSONUtils;
+import org.apache.metron.indexing.dao.search.*;
+
+import java.io.IOException;
+import java.util.*;
+
+public class InMemoryDao implements IndexDao {
+  public static Map<String, List<String>> BACKING_STORE = new HashMap<>();
+  private AccessConfig config;
+
+  @Override
+  public SearchResponse search(SearchRequest searchRequest) throws 
InvalidSearchException {
+    if(config.getMaxSearchResults() != null && searchRequest.getSize() > 
config.getMaxSearchResults()) {
+      throw new InvalidSearchException("Search result size must be less than " 
+ config.getMaxSearchResults());
+    }
+    List<SearchResult> response = new ArrayList<>();
+    for(String index : searchRequest.getIndices()) {
+      String i = null;
+      for(String storedIdx : BACKING_STORE.keySet()) {
+        if(storedIdx.equals(index) || storedIdx.startsWith(index + "_")) {
+          i = storedIdx;
+        }
+      }
+      if(i == null) {
+        continue;
+      }
+      for (String doc : BACKING_STORE.get(i)) {
+        Map<String, Object> docParsed = parse(doc);
+        if (isMatch(searchRequest.getQuery(), docParsed)) {
+          SearchResult result = new SearchResult();
+          result.setSource(docParsed);
+          result.setScore((float) Math.random());
+          result.setId(docParsed.getOrDefault(Constants.GUID, 
UUID.randomUUID()).toString());
+          response.add(result);
+        }
+      }
+    }
+
+    if(searchRequest.getSort().size() != 0) {
+      Collections.sort(response, sorted(searchRequest.getSort()));
+    }
+    SearchResponse ret = new SearchResponse();
+    List<SearchResult> finalResp = new ArrayList<>();
+    int maxSize = config.getMaxSearchResults() == 
null?searchRequest.getSize():config.getMaxSearchResults();
+    for(int i = searchRequest.getFrom();i < response.size()&& finalResp.size() 
<= maxSize;++i) {
+      finalResp.add(response.get(i));
+    }
+    ret.setTotal(response.size());
+    ret.setResults(finalResp);
+    return ret;
+  }
+
+
+  private static class ComparableComparator implements Comparator<Comparable>  
{
+    SortOrder order = null;
+    public ComparableComparator(SortOrder order) {
+      this.order = order;
+    }
+    @Override
+    public int compare(Comparable o1, Comparable o2) {
+      int result = ComparisonChain.start().compare(o1, o2).result();
+      return order == SortOrder.ASC?result:-1*result;
+    }
+  }
+
+  private static Comparator<SearchResult> sorted(final List<SortField> fields) 
{
+    return (o1, o2) -> {
+      ComparisonChain chain = ComparisonChain.start();
+      for(SortField field : fields) {
+        Comparable f1 = (Comparable) o1.getSource().get(field.getField());
+        Comparable f2 = (Comparable) o2.getSource().get(field.getField());
+        chain = chain.compare(f1, f2, new 
ComparableComparator(field.getSortOrder()));
+      }
+      return chain.result();
+    };
+  }
+
+  private static boolean isMatch(String query, Map<String, Object> doc) {
+    if(query.equals("*")) {
+      return true;
+    }
+    if(query.contains(":")) {
+      Iterable<String> splits = Splitter.on(":").split(query.trim());
+      String field = Iterables.getFirst(splits, "");
+      String val = Iterables.getLast(splits, "");
+      Object o = doc.get(field);
+      if(o == null) {
+        return false;
+      }
+      else {
+        return o.equals(val);
+      }
+    }
+    return false;
+  }
+
+  private static Map<String, Object> parse(String doc) {
+    try {
+      return JSONUtils.INSTANCE.load(doc, new TypeReference<Map<String, 
Object>>() {});
+    } catch (IOException e) {
+      throw new IllegalStateException(e.getMessage(), e);
+    }
+
+  }
+
+  @Override
+  public void init(Map<String, Object> globalConfig, AccessConfig config) {
+    this.config = config;
+  }
+
+  public static void load(Map<String, List<String>> backingStore) {
+    BACKING_STORE = backingStore;
+  }
+
+  public static void clear() {
+    BACKING_STORE.clear();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/cf7043c5/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/IndexingDaoIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/IndexingDaoIntegrationTest.java
 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/IndexingDaoIntegrationTest.java
new file mode 100644
index 0000000..8b5baef
--- /dev/null
+++ 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/IndexingDaoIntegrationTest.java
@@ -0,0 +1,255 @@
+/**
+ * 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.indexing.dao;
+
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.metron.common.utils.JSONUtils;
+import org.apache.metron.indexing.dao.search.InvalidSearchException;
+import org.apache.metron.indexing.dao.search.SearchRequest;
+import org.apache.metron.indexing.dao.search.SearchResponse;
+import org.apache.metron.indexing.dao.search.SearchResult;
+import org.apache.metron.integration.InMemoryComponent;
+import org.json.simple.parser.ParseException;
+import org.junit.*;
+
+import java.util.List;
+
+public abstract class IndexingDaoIntegrationTest {
+  /**
+   * [
+   * {"source:type": "bro", "ip_src_addr":"192.168.1.1", "ip_src_port": 8010, 
"timestamp":1, "rejected":true},
+   * {"source:type": "bro" "ip_src_addr":"192.168.1.2", "ip_src_port": 8009, 
"timestamp":2, "rejected":false},
+   * {"source:type": "bro" "ip_src_addr":"192.168.1.3", "ip_src_port": 8008, 
"timestamp":3, "rejected":true},
+   * {"source:type": "bro" "ip_src_addr":"192.168.1.4", "ip_src_port": 8007, 
"timestamp":4, "rejected":false},
+   * {"source:type": "bro" "ip_src_addr":"192.168.1.5", "ip_src_port": 8006, 
"timestamp":5, "rejected":true}
+   * ]
+   */
+  @Multiline
+  public static String broData;
+
+  /**
+   * [
+   * {"source:type": "snort" "ip_src_addr":"192.168.1.6", "ip_src_port": 8005, 
"timestamp":6, "is_alert":false},
+   * {"source:type": "snort" "ip_src_addr":"192.168.1.1", "ip_src_port": 8004, 
"timestamp":7, "is_alert":true},
+   * {"source:type": "snort" "ip_src_addr":"192.168.1.7", "ip_src_port": 8003, 
"timestamp":8, "is_alert":false},
+   * {"source:type": "snort" "ip_src_addr":"192.168.1.1", "ip_src_port": 8002, 
"timestamp":9, "is_alert":true},
+   * {"source:type": "snort" "ip_src_addr":"192.168.1.8", "ip_src_port": 8001, 
"timestamp":10, "is_alert":false}
+   * ]
+   */
+  @Multiline
+  public static String snortData;
+
+  /**
+   * {
+   * "indices": ["bro", "snort"],
+   * "query": "*",
+   * "from": 0,
+   * "size": 10,
+   * "sort": [
+   *   {
+   *     "field": "timestamp",
+   *     "sortOrder": "desc"
+   *   }
+   * ]
+   * }
+   */
+  @Multiline
+  public static String allQuery;
+
+  /**
+   * {
+   * "indices": ["bro", "snort"],
+   * "query": "ip_src_addr:192.168.1.1",
+   * "from": 0,
+   * "size": 10,
+   * "sort": [
+   *   {
+   *     "field": "timestamp",
+   *     "sortOrder": "desc"
+   *   }
+   * ]
+   * }
+   */
+  @Multiline
+  public static String filterQuery;
+
+  /**
+   * {
+   * "indices": ["bro", "snort"],
+   * "query": "*",
+   * "from": 0,
+   * "size": 10,
+   * "sort": [
+   *   {
+   *     "field": "ip_src_port",
+   *     "sortOrder": "asc"
+   *   }
+   * ]
+   * }
+   */
+  @Multiline
+  public static String sortQuery;
+
+  /**
+   * {
+   * "indices": ["bro", "snort"],
+   * "query": "*",
+   * "from": 4,
+   * "size": 3,
+   * "sort": [
+   *   {
+   *     "field": "timestamp",
+   *     "sortOrder": "desc"
+   *   }
+   * ]
+   * }
+   */
+  @Multiline
+  public static String paginationQuery;
+
+  /**
+   * {
+   * "indices": ["bro"],
+   * "query": "*",
+   * "from": 0,
+   * "size": 10,
+   * "sort": [
+   *   {
+   *     "field": "timestamp",
+   *     "sortOrder": "desc"
+   *   }
+   * ]
+   * }
+   */
+  @Multiline
+  public static String indexQuery;
+
+  /**
+   * {
+   * "indices": ["bro", "snort"],
+   * "query": "*",
+   * "from": 0,
+   * "size": 101,
+   * "sort": [
+   *   {
+   *     "field": "timestamp",
+   *     "sortOrder": "desc"
+   *   }
+   * ]
+   * }
+   */
+  @Multiline
+  public static String exceededMaxResultsQuery;
+
+  protected IndexDao dao;
+  protected InMemoryComponent indexComponent;
+
+  @Before
+  public void setup() throws Exception {
+    indexComponent = startIndex();
+    loadTestData();
+    dao = createDao();
+  }
+
+  @Test
+  public void test() throws Exception {
+    //All Query Testcase
+    {
+      SearchRequest request = JSONUtils.INSTANCE.load(allQuery, 
SearchRequest.class);
+      SearchResponse response = dao.search(request);
+      Assert.assertEquals(10, response.getTotal());
+      List<SearchResult> results = response.getResults();
+      for(int i = 0;i < 5;++i) {
+        Assert.assertEquals("snort", 
results.get(i).getSource().get("source:type"));
+        Assert.assertEquals(10-i, results.get(i).getSource().get("timestamp"));
+      }
+      for(int i = 5;i < 10;++i) {
+        Assert.assertEquals("bro", 
results.get(i).getSource().get("source:type"));
+        Assert.assertEquals(10-i, results.get(i).getSource().get("timestamp"));
+      }
+    }
+    //Filter test case
+    {
+      SearchRequest request = JSONUtils.INSTANCE.load(filterQuery, 
SearchRequest.class);
+      SearchResponse response = dao.search(request);
+      Assert.assertEquals(3, response.getTotal());
+      List<SearchResult> results = response.getResults();
+      Assert.assertEquals("snort", 
results.get(0).getSource().get("source:type"));
+      Assert.assertEquals(9, results.get(0).getSource().get("timestamp"));
+      Assert.assertEquals("snort", 
results.get(1).getSource().get("source:type"));
+      Assert.assertEquals(7, results.get(1).getSource().get("timestamp"));
+      Assert.assertEquals("bro", 
results.get(2).getSource().get("source:type"));
+      Assert.assertEquals(1, results.get(2).getSource().get("timestamp"));
+    }
+    //Sort test case
+    {
+      SearchRequest request = JSONUtils.INSTANCE.load(sortQuery, 
SearchRequest.class);
+      SearchResponse response = dao.search(request);
+      Assert.assertEquals(10, response.getTotal());
+      List<SearchResult> results = response.getResults();
+      for(int i = 8001;i < 8011;++i) {
+        Assert.assertEquals(i, 
results.get(i-8001).getSource().get("ip_src_port"));
+      }
+    }
+    //pagination test case
+    {
+      SearchRequest request = JSONUtils.INSTANCE.load(paginationQuery, 
SearchRequest.class);
+      SearchResponse response = dao.search(request);
+      Assert.assertEquals(10, response.getTotal());
+      List<SearchResult> results = response.getResults();
+      Assert.assertEquals(3, results.size());
+      Assert.assertEquals("snort", 
results.get(0).getSource().get("source:type"));
+      Assert.assertEquals(6, results.get(0).getSource().get("timestamp"));
+      Assert.assertEquals("bro", 
results.get(1).getSource().get("source:type"));
+      Assert.assertEquals(5, results.get(1).getSource().get("timestamp"));
+      Assert.assertEquals("bro", 
results.get(2).getSource().get("source:type"));
+      Assert.assertEquals(4, results.get(2).getSource().get("timestamp"));
+    }
+    //Index query
+    {
+      SearchRequest request = JSONUtils.INSTANCE.load(indexQuery, 
SearchRequest.class);
+      SearchResponse response = dao.search(request);
+      Assert.assertEquals(5, response.getTotal());
+      List<SearchResult> results = response.getResults();
+      for(int i = 5,j=0;i > 0;i--,j++) {
+        Assert.assertEquals("bro", 
results.get(j).getSource().get("source:type"));
+        Assert.assertEquals(i, results.get(j).getSource().get("timestamp"));
+      }
+    }
+    //Exceeded maximum results query
+    {
+      SearchRequest request = JSONUtils.INSTANCE.load(exceededMaxResultsQuery, 
SearchRequest.class);
+      try {
+        dao.search(request);
+        Assert.fail("Exception expected, but did not come.");
+      }
+      catch(InvalidSearchException ise) {
+        Assert.assertEquals("Search result size must be less than 100", 
ise.getMessage());
+      }
+    }
+  }
+
+  @After
+  public void stop() throws Exception {
+    indexComponent.stop();
+  }
+
+  protected abstract IndexDao createDao() throws Exception;
+  protected abstract InMemoryComponent startIndex() throws Exception;
+  protected abstract void loadTestData() throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/cf7043c5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 5079655..5d64019 100644
--- a/pom.xml
+++ b/pom.xml
@@ -111,6 +111,7 @@
         <global_maven_version>[3.3.1,)</global_maven_version>
         <global_kryo_version>3.0.3</global_kryo_version>
         <global_kryo_serializers_version>0.38</global_kryo_serializers_version>
+        <global_reflections_version>0.9.10</global_reflections_version>
         <argLine></argLine>
     </properties>
 

Reply via email to