diff --git a/plugins/ingest/src/main/java/org/elasticsearch/ingest/Data.java b/plugins/ingest/src/main/java/org/elasticsearch/ingest/Data.java index c64b8865607..827d17483a3 100644 --- a/plugins/ingest/src/main/java/org/elasticsearch/ingest/Data.java +++ b/plugins/ingest/src/main/java/org/elasticsearch/ingest/Data.java @@ -21,9 +21,7 @@ package org.elasticsearch.ingest; import org.elasticsearch.common.Strings; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * Represents the data and meta data (like id and type) of a single document that is going to be indexed. @@ -62,16 +60,9 @@ public final class Data { String[] pathElements = Strings.splitStringToArray(path, '.'); assert pathElements.length > 0; - Map innerMap = document; - for (int i = 0; i < pathElements.length - 1; i++) { - Object obj = innerMap.get(pathElements[i]); - if (obj instanceof Map) { - @SuppressWarnings("unchecked") - Map stringObjectMap = (Map) obj; - innerMap = stringObjectMap; - } else { - return null; - } + Map innerMap = getParent(pathElements); + if (innerMap == null) { + return null; } String leafKey = pathElements[pathElements.length - 1]; @@ -96,7 +87,29 @@ public final class Data { } String[] pathElements = Strings.splitStringToArray(path, '.'); assert pathElements.length > 0; + Map innerMap = getParent(pathElements); + if (innerMap == null) { + return false; + } + String leafKey = pathElements[pathElements.length - 1]; + return innerMap.containsKey(leafKey); + } + public void removeProperty(String path) { + if (path == null || path.length() == 0) { + return; + } + String[] pathElements = Strings.splitStringToArray(path, '.'); + assert pathElements.length > 0; + + Map parent = getParent(pathElements); + if (parent != null) { + String leafKey = pathElements[pathElements.length - 1]; + parent.remove(leafKey); + } + } + + private Map getParent(String[] pathElements) { Map innerMap = document; for (int i = 0; i < pathElements.length - 1; i++) { Object obj = innerMap.get(pathElements[i]); @@ -105,12 +118,10 @@ public final class Data { Map stringObjectMap = (Map) obj; innerMap = stringObjectMap; } else { - return false; + return null; } } - - String leafKey = pathElements[pathElements.length - 1]; - return innerMap.containsKey(leafKey); + return innerMap; } /** @@ -136,6 +147,8 @@ public final class Data { @SuppressWarnings("unchecked") Map stringObjectMap = (Map) object; inner = stringObjectMap; + } else if (object == null ) { + throw new IllegalArgumentException("cannot add field to null parent, [" + Map.class.getName() + "] expected instead."); } else { throw new IllegalArgumentException("cannot add field to parent [" + pathElement + "] of type [" + object.getClass().getName() + "], [" + Map.class.getName() + "] expected instead."); } diff --git a/plugins/ingest/src/test/java/org/elasticsearch/ingest/DataTests.java b/plugins/ingest/src/test/java/org/elasticsearch/ingest/DataTests.java index cf230d1c299..5179a468b58 100644 --- a/plugins/ingest/src/test/java/org/elasticsearch/ingest/DataTests.java +++ b/plugins/ingest/src/test/java/org/elasticsearch/ingest/DataTests.java @@ -36,10 +36,10 @@ public class DataTests extends ESTestCase { public void setData() { Map document = new HashMap<>(); document.put("foo", "bar"); - document.put("foo_null", null); document.put("int", 123); Map innerObject = new HashMap<>(); innerObject.put("buzz", "hello world"); + innerObject.put("foo_null", null); document.put("fizz", innerObject); data = new Data("index", "type", "id", document); } @@ -50,7 +50,7 @@ public class DataTests extends ESTestCase { } public void testGetPropertyValueNullValue() { - assertThat(data.getPropertyValue("foo_null", Object.class), nullValue()); + assertThat(data.getPropertyValue("fizz.foo_null", Object.class), nullValue()); } public void testSimpleGetPropertyValueTypeMismatch() { @@ -106,7 +106,7 @@ public class DataTests extends ESTestCase { } public void testHasPropertyValueNullValue() { - assertTrue(data.hasPropertyValue("foo_null")); + assertTrue(data.hasPropertyValue("fizz.foo_null")); } public void testHasPropertyValueEmpty() { @@ -162,6 +162,15 @@ public class DataTests extends ESTestCase { } } + public void testSetPropertyValueOnExistingNullParent() { + try { + data.setPropertyValue("fizz.foo_null.test", "bar"); + fail("add field should have failed"); + } catch(IllegalArgumentException e) { + assertThat(e.getMessage(), equalTo("cannot add field to null parent, [java.util.Map] expected instead.")); + } + } + public void testSetPropertyValueNullName() { try { data.setPropertyValue(null, "bar"); @@ -180,6 +189,47 @@ public class DataTests extends ESTestCase { } } + public void testRemoveProperty() { + data.removeProperty("foo"); + assertThat(data.getDocument().size(), equalTo(2)); + assertThat(data.getDocument().containsKey("foo"), equalTo(false)); + } + + public void testRemoveInnerProperty() { + data.removeProperty("fizz.buzz"); + assertThat(data.getDocument().size(), equalTo(3)); + assertThat(data.getDocument().get("fizz"), instanceOf(Map.class)); + @SuppressWarnings("unchecked") + Map map = (Map)data.getDocument().get("fizz"); + assertThat(map.size(), equalTo(1)); + assertThat(map.containsKey("buzz"), equalTo(false)); + + data.removeProperty("fizz.foo_null"); + assertThat(map.size(), equalTo(0)); + assertThat(data.getDocument().size(), equalTo(3)); + assertThat(data.getDocument().containsKey("fizz"), equalTo(true)); + } + + public void testRemoveNonExistingProperty() { + data.removeProperty("does_not_exist"); + assertThat(data.getDocument().size(), equalTo(3)); + } + + public void testRemoveExistingParentTypeMismatch() { + data.removeProperty("foo.test"); + assertThat(data.getDocument().size(), equalTo(3)); + } + + public void testRemoveNullProperty() { + data.removeProperty(null); + assertThat(data.getDocument().size(), equalTo(3)); + } + + public void testRemoveEmptyProperty() { + data.removeProperty(""); + assertThat(data.getDocument().size(), equalTo(3)); + } + public void testEqualsAndHashcode() throws Exception { String index = randomAsciiOfLengthBetween(1, 10); String type = randomAsciiOfLengthBetween(1, 10);