From 491d2b721c00fb97c833b92a5368ba0c23a4c155 Mon Sep 17 00:00:00 2001 From: Boaz Leskes Date: Fri, 5 Jul 2013 12:51:07 +0200 Subject: [PATCH] added support for a prefix wild card (*.field) in includes --- .../xcontent/support/XContentMapValues.java | 30 +++++++++---- .../support/XContentMapValuesTests.java | 42 +++++++++++++++++++ 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/xcontent/support/XContentMapValues.java b/src/main/java/org/elasticsearch/common/xcontent/support/XContentMapValues.java index acd6472c93e..82269f6d04b 100644 --- a/src/main/java/org/elasticsearch/common/xcontent/support/XContentMapValues.java +++ b/src/main/java/org/elasticsearch/common/xcontent/support/XContentMapValues.java @@ -164,29 +164,41 @@ public class XContentMapValues { sb.setLength(mark); continue; } - boolean exactIncludeMatch = false; - if (includes.length > 0) { - boolean atLeastOnOneIncludeMatched = false; + boolean exactIncludeMatch; + if (includes.length == 0) { + // implied match anything + exactIncludeMatch = true; + } else { + exactIncludeMatch = false; + boolean pathIsPrefixOfAnInclude = false; for (String include : includes) { - // check for prefix as well to see if we need to zero in, something like: obj1.arr1.* + // check for prefix matches as well to see if we need to zero in, something like: obj1.arr1.* or *.field // note, this does not work well with middle matches, like obj1.*.obj3 + if (include.charAt(0) == '*') { + if (Regex.simpleMatch(include, path)) { + exactIncludeMatch = true; + break; + } + pathIsPrefixOfAnInclude = true; + break; + } if (include.startsWith(path)) { if (include.length() == path.length()) { - atLeastOnOneIncludeMatched = true; exactIncludeMatch = true; break; } else if (include.length() > path.length() && include.charAt(path.length()) == '.') { // include might may match deeper paths. Dive deeper. - atLeastOnOneIncludeMatched = true; + pathIsPrefixOfAnInclude = true; break; } } if (Regex.simpleMatch(include, path)) { - atLeastOnOneIncludeMatched = true; + exactIncludeMatch = true; break; } } - if (!atLeastOnOneIncludeMatched) { + if (!pathIsPrefixOfAnInclude && !exactIncludeMatch) { + // skip subkeys, not interesting. sb.setLength(mark); continue; } @@ -206,7 +218,7 @@ public class XContentMapValues { // if we had an exact match, we want give deeper excludes their chance filter(list, innerInto, exactIncludeMatch ? Strings.EMPTY_ARRAY : includes, excludes, sb); into.put(entry.getKey(), innerInto); - } else { + } else if (exactIncludeMatch) { into.put(entry.getKey(), entry.getValue()); } sb.setLength(mark); diff --git a/src/test/java/org/elasticsearch/test/unit/common/xcontent/support/XContentMapValuesTests.java b/src/test/java/org/elasticsearch/test/unit/common/xcontent/support/XContentMapValuesTests.java index 715c3456ac3..d61e1ff819b 100644 --- a/src/test/java/org/elasticsearch/test/unit/common/xcontent/support/XContentMapValuesTests.java +++ b/src/test/java/org/elasticsearch/test/unit/common/xcontent/support/XContentMapValuesTests.java @@ -317,6 +317,48 @@ public class XContentMapValuesTests { assertThat(((Map) ((List) filteredMap.get("array")).get(1)).get("field").toString(), equalTo("value")); } + @Test + public void filterIncludesUsingStarPrefix() { + Map map = new HashMap(); + map.put("field", "value"); + map.put("obj", + new HashMap() {{ + put("field", "value"); + put("field2", "value2"); + }}); + map.put("n_obj", + new HashMap() {{ + put("n_field", "value"); + put("n_field2", "value2"); + }}); + + Map filteredMap = XContentMapValues.filter(map, new String[]{"*.field2"}, Strings.EMPTY_ARRAY); + assertThat(filteredMap.size(), equalTo(1)); + assertThat(filteredMap, hasKey("obj")); + assertThat(((Map) filteredMap.get("obj")).size(), equalTo(1)); + assertThat(((Map) filteredMap.get("obj")), hasKey("field2")); + + // only objects + filteredMap = XContentMapValues.filter(map, new String[]{"*.*"}, Strings.EMPTY_ARRAY); + assertThat(filteredMap.size(), equalTo(2)); + assertThat(filteredMap, hasKey("obj")); + assertThat(((Map) filteredMap.get("obj")).size(), equalTo(2)); + assertThat(filteredMap, hasKey("n_obj")); + assertThat(((Map) filteredMap.get("n_obj")).size(), equalTo(2)); + + + filteredMap = XContentMapValues.filter(map, new String[]{"*"}, new String[]{"*.*2"}); + assertThat(filteredMap.size(), equalTo(3)); + assertThat(filteredMap, hasKey("field")); + assertThat(filteredMap, hasKey("obj")); + assertThat(((Map) filteredMap.get("obj")).size(), equalTo(1)); + assertThat(((Map) filteredMap.get("obj")), hasKey("field")); + assertThat(filteredMap, hasKey("n_obj")); + assertThat(((Map) filteredMap.get("n_obj")).size(), equalTo(1)); + assertThat(((Map) filteredMap.get("n_obj")), hasKey("n_field")); + + } + @Test public void filterWithEmptyIncludesExcludes() { Map map = new HashMap();