resolves STREAMS-588
fixes streams-examples / .. / TwitterFollowNeo4j
by adding a way to clear zero-size objects, empty arrays, and null / empty values out of objects en-route to neo4j
diff --git a/streams-contrib/streams-persist-neo4j/src/main/java/org/apache/streams/neo4j/CypherQueryGraphHelper.java b/streams-contrib/streams-persist-neo4j/src/main/java/org/apache/streams/neo4j/CypherQueryGraphHelper.java
index 3256691..dc6efeb 100644
--- a/streams-contrib/streams-persist-neo4j/src/main/java/org/apache/streams/neo4j/CypherQueryGraphHelper.java
+++ b/streams-contrib/streams-persist-neo4j/src/main/java/org/apache/streams/neo4j/CypherQueryGraphHelper.java
@@ -124,6 +124,7 @@
String query = createVertex.render();
ObjectNode object = MAPPER.convertValue(activityObject, ObjectNode.class);
+ object = PropertyUtil.getInstance(MAPPER).cleanProperties(object);
Map<String, Object> props = PropertyUtil.getInstance(MAPPER).flattenToMap(object);
Pair<String, Map<String, Object>> queryPlusParameters = new Pair(createVertex.render(), props);
@@ -171,6 +172,7 @@
String query = mergeVertex.render();
ObjectNode object = MAPPER.convertValue(activityObject, ObjectNode.class);
+ object = PropertyUtil.getInstance(MAPPER).cleanProperties(object);
Map<String, Object> props = PropertyUtil.getInstance(MAPPER).flattenToMap(object);
LOGGER.debug("mergeVertexRequest: ({},{})", query, props);
@@ -191,6 +193,7 @@
Pair queryPlusParameters = new Pair(null, new HashMap<>());
ObjectNode object = MAPPER.convertValue(activity, ObjectNode.class);
+ object = PropertyUtil.getInstance(MAPPER).cleanProperties(object);
Map<String, Object> props = PropertyUtil.getInstance(MAPPER).flattenToMap(object);
ST mergeEdge = new ST(createEdgeStatementTemplate);
@@ -221,6 +224,7 @@
Pair queryPlusParameters = new Pair(null, new HashMap<>());
ObjectNode object = MAPPER.convertValue(activity, ObjectNode.class);
+ object = PropertyUtil.getInstance(MAPPER).cleanProperties(object);
Map<String, Object> props = PropertyUtil.getInstance(MAPPER).flattenToMap(object);
ST mergeEdge = new ST(createEdgeStatementTemplate);
diff --git a/streams-examples/streams-examples-local/pom.xml b/streams-examples/streams-examples-local/pom.xml
index 11bd321..9987df3 100644
--- a/streams-examples/streams-examples-local/pom.xml
+++ b/streams-examples/streams-examples-local/pom.xml
@@ -41,7 +41,7 @@
<module>elasticsearch-hdfs</module>
<module>elasticsearch-reindex</module>
<module>mongo-elasticsearch-sync</module>
- <!--<module>twitter-follow-neo4j</module>-->
+ <module>twitter-follow-neo4j</module>
<module>twitter-history-elasticsearch</module>
<module>twitter-userstream-elasticsearch</module>
</modules>
diff --git a/streams-examples/streams-examples-local/twitter-follow-neo4j/pom.xml b/streams-examples/streams-examples-local/twitter-follow-neo4j/pom.xml
index 2e47cf6..366343d 100644
--- a/streams-examples/streams-examples-local/twitter-follow-neo4j/pom.xml
+++ b/streams-examples/streams-examples-local/twitter-follow-neo4j/pom.xml
@@ -26,8 +26,8 @@
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>streams-twitter-follow-neo4j</artifactId>
- <name>twitter-follow-neo4j</name>
+ <artifactId>streams-example-twitter-follow-neo4j</artifactId>
+ <name>streams-example-twitter-follow-neo4j</name>
<description>
Collects friend or follower connections for a set of twitter users to build a graph database in neo4j.
@@ -188,6 +188,16 @@
<dependencies>
<dependency>
<groupId>org.apache.streams</groupId>
+ <artifactId>streams-config</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.streams</groupId>
+ <artifactId>streams-runtime-local</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.streams</groupId>
<artifactId>streams-persist-neo4j</artifactId>
<version>${project.version}</version>
</dependency>
@@ -253,4 +263,90 @@
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>dockerITs</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ <property>
+ <name>skipITs</name>
+ <value>false</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <configuration combine.self="override">
+ <watchInterval>500</watchInterval>
+ <logDate>default</logDate>
+ <verbose>true</verbose>
+ <autoPull>on</autoPull>
+ <images>
+ <image>
+ <name>neo4j</name>
+ <alias>neo4j</alias>
+ <run>
+ <env>
+ <NEO4J_AUTH>none</NEO4J_AUTH>
+ </env>
+ <namingStrategy>none</namingStrategy>
+ <ports>
+ <port>${http.host}:${http.port}:7474</port>
+ <port>${tcp.host}:${tcp.port}:7687</port>
+ </ports>
+ <portPropertyFile>neo4j.properties</portPropertyFile>
+ <wait>
+ <http>
+ <url>http://${http.host}:${http.port}</url>
+ <method>GET</method>
+ <status>200</status>
+ </http>
+ <time>30000</time>
+ <kill>1000</kill>
+ <shutdown>500</shutdown>
+ </wait>
+ <log>
+ <enabled>true</enabled>
+ <date>default</date>
+ <color>cyan</color>
+ </log>
+ </run>
+ <watch>
+ <mode>none</mode>
+ </watch>
+ </image>
+
+ </images>
+ </configuration>
+ <executions>
+ <execution>
+ <id>start</id>
+ <goals>
+ <goal>start</goal>
+ </goals>
+ <phase>
+ pre-integration-test
+ </phase>
+ </execution>
+ <execution>
+ <id>stop</id>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ <phase>
+ post-integration-test
+ </phase>
+ </execution>
+ </executions>
+
+ </plugin>
+
+ </plugins>
+ </build>
+
+ </profile>
+ </profiles>
+
</project>
diff --git a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/java/org/apache/streams/example/TwitterFollowNeo4j.java b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/java/org/apache/streams/example/TwitterFollowNeo4j.java
index e268c22..03d1330 100644
--- a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/java/org/apache/streams/example/TwitterFollowNeo4j.java
+++ b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/java/org/apache/streams/example/TwitterFollowNeo4j.java
@@ -31,7 +31,7 @@
import org.apache.streams.local.builders.LocalStreamBuilder;
import org.apache.streams.neo4j.Neo4jConfiguration;
import org.apache.streams.neo4j.bolt.Neo4jBoltPersistWriter;
-import org.apache.streams.twitter.TwitterFollowingConfiguration;
+import org.apache.streams.twitter.config.TwitterFollowingConfiguration;
import org.apache.streams.twitter.converter.TwitterDocumentClassifier;
import org.apache.streams.twitter.converter.TwitterFollowActivityConverter;
import org.apache.streams.twitter.provider.TwitterFollowingProvider;
@@ -54,7 +54,7 @@
private TwitterFollowNeo4jConfiguration config;
public TwitterFollowNeo4j() {
- this(new ComponentConfigurator<>(TwitterFollowNeo4jConfiguration.class).detectConfiguration());
+ this(new StreamsConfigurator<>(TwitterFollowNeo4jConfiguration.class).detectCustomConfiguration());
}
public TwitterFollowNeo4j(TwitterFollowNeo4jConfiguration config) {
@@ -79,9 +79,7 @@
Neo4jBoltPersistWriter graphPersistWriter = new Neo4jBoltPersistWriter(neo4jConfiguration);
graphPersistWriter.prepare(neo4jConfiguration);
- LocalRuntimeConfiguration localRuntimeConfiguration =
- StreamsJacksonMapper.getInstance().convertValue(StreamsConfigurator.detectConfiguration(), LocalRuntimeConfiguration.class);
- StreamBuilder builder = new LocalStreamBuilder(localRuntimeConfiguration);
+ StreamBuilder builder = new LocalStreamBuilder();
builder.newPerpetualStream(TwitterFollowingProvider.class.getCanonicalName(), followingProvider);
builder.addStreamsProcessor(TypeConverterProcessor.class.getCanonicalName(), converter, 1, TwitterFollowingProvider.class.getCanonicalName());
diff --git a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/jsonschema/TwitterFollowNeo4jConfiguration.json b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/jsonschema/TwitterFollowNeo4jConfiguration.json
index e2b3386..23deacc 100644
--- a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/jsonschema/TwitterFollowNeo4jConfiguration.json
+++ b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/main/jsonschema/TwitterFollowNeo4jConfiguration.json
@@ -6,8 +6,13 @@
"type": "object",
"javaType" : "org.apache.streams.example.TwitterFollowNeo4jConfiguration",
"javaInterfaces": ["java.io.Serializable"],
+ "extends": {
+ "$comment": "Absolute $ref: http://streams.apache.org/streams-runtimes/streams-runtime-local/LocalRuntimeConfiguration.json",
+ "$ref": "../../../../../../streams-runtimes/streams-runtime-local/src/main/jsonschema/LocalRuntimeConfiguration.json"
+ },
+ "additionalProperties": false,
"properties": {
- "twitter": { "javaType": "org.apache.streams.twitter.TwitterFollowingConfiguration", "type": "object", "required": true },
+ "twitter": { "javaType": "org.apache.streams.twitter.config.TwitterFollowingConfiguration", "type": "object", "required": true },
"neo4j": { "javaType": "org.apache.streams.neo4j.Neo4jConfiguration", "type": "object", "required": true }
}
}
\ No newline at end of file
diff --git a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/java/org/apache/streams/example/test/TwitterFollowNeo4jIT.java b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/java/org/apache/streams/example/test/TwitterFollowNeo4jIT.java
index 75e56bb..52cb7ee 100644
--- a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/java/org/apache/streams/example/test/TwitterFollowNeo4jIT.java
+++ b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/java/org/apache/streams/example/test/TwitterFollowNeo4jIT.java
@@ -19,6 +19,7 @@
package org.apache.streams.example.test;
import org.apache.streams.config.ComponentConfigurator;
+import org.apache.streams.config.StreamsConfigurator;
import org.apache.streams.core.StreamsResultSet;
import org.apache.streams.example.TwitterFollowNeo4j;
import org.apache.streams.example.TwitterFollowNeo4jConfiguration;
@@ -43,8 +44,11 @@
import java.io.File;
import java.io.IOException;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.testng.Assert.assertTrue;
-
/**
* TwitterFollowNeo4jIT is an integration test for TwitterFollowNeo4j.
*/
@@ -63,12 +67,7 @@
@BeforeClass
public void prepareTest() throws IOException {
- Config reference = ConfigFactory.load();
- File conf = new File("target/test-classes/TwitterFollowNeo4jIT.conf");
- assertTrue(conf.exists());
- Config testResourceConfig = ConfigFactory.parseFileAnySyntax(conf, ConfigParseOptions.defaults().setAllowMissing(false));
- Config typesafe = testResourceConfig.withFallback(reference).resolve();
- testConfiguration = new ComponentConfigurator<>(TwitterFollowNeo4jConfiguration.class).detectConfiguration(typesafe);
+ testConfiguration = new StreamsConfigurator<>(TwitterFollowNeo4jConfiguration.class).detectCustomConfiguration();
testClient = Neo4jBoltClient.getInstance(testConfiguration.getNeo4j());
Session session = testClient.client().session();
@@ -89,18 +88,18 @@
Neo4jReaderConfiguration vertexReaderConfiguration= MAPPER.convertValue(testConfiguration.getNeo4j(), Neo4jReaderConfiguration.class);
vertexReaderConfiguration.setQuery("MATCH (v) return v");
Neo4jBoltPersistReader vertexReader = new Neo4jBoltPersistReader(vertexReaderConfiguration);
- vertexReader.prepare(null);
+ vertexReader.prepare(vertexReaderConfiguration);
StreamsResultSet vertexResultSet = vertexReader.readAll();
LOGGER.info("Total Read: {}", vertexResultSet.size() );
- assertTrue(vertexResultSet.size() > 100);
+ assertThat(vertexResultSet.size(), greaterThan(100));
Neo4jReaderConfiguration edgeReaderConfiguration= MAPPER.convertValue(testConfiguration.getNeo4j(), Neo4jReaderConfiguration.class);
edgeReaderConfiguration.setQuery("MATCH (s)-[r]->(d) return r");
Neo4jBoltPersistReader edgeReader = new Neo4jBoltPersistReader(edgeReaderConfiguration);
- edgeReader.prepare(null);
+ edgeReader.prepare(edgeReaderConfiguration);
StreamsResultSet edgeResultSet = edgeReader.readAll();
LOGGER.info("Total Read: {}", edgeResultSet.size() );
- assertTrue(edgeResultSet.size() == vertexResultSet.size()-1);
+ assertThat(edgeResultSet.size(), equalTo(vertexResultSet.size()-1));
}
diff --git a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/resources/TwitterFollowNeo4jIT.conf b/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/resources/TwitterFollowNeo4jIT.conf
deleted file mode 100644
index d54a50c..0000000
--- a/streams-examples/streams-examples-local/twitter-follow-neo4j/src/test/resources/TwitterFollowNeo4jIT.conf
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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
-#
-# 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.
-include "../../../../../twitter.conf"
-include "../../../../../neo4j.properties"
-twitter {
- debug = true
- ids_only = false
- endpoint = "friends"
- info = [
- 18055613
- ]
- twitter.max_items = 200
-}
-neo4j {
- scheme = "tcp"
- hosts += ${neo4j.tcp.host}
- port = ${neo4j.tcp.port}
-}
-taskTimeoutMs = 60000
\ No newline at end of file
diff --git a/streams-util/src/main/java/org/apache/streams/util/PropertyUtil.java b/streams-util/src/main/java/org/apache/streams/util/PropertyUtil.java
index 63678f6..4ea46fd 100644
--- a/streams-util/src/main/java/org/apache/streams/util/PropertyUtil.java
+++ b/streams-util/src/main/java/org/apache/streams/util/PropertyUtil.java
@@ -27,6 +27,7 @@
import com.github.wnameless.json.flattener.JsonFlattener;
import com.github.wnameless.json.unflattener.JsonUnflattener;
import org.apache.commons.lang3.StringUtils;
+import org.codehaus.jackson.JsonFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -140,6 +141,42 @@
return merged;
}
+ public ObjectNode cleanProperties(ObjectNode content) {
+ return cleanProperties(mapper, content);
+ }
+
+ public static ObjectNode cleanProperties(ObjectMapper mapper, ObjectNode content) {
+
+ ObjectNode cleaned = mapper.createObjectNode();
+
+ Iterator<Map.Entry<String, JsonNode>> fields = content.fields();
+ for ( ; fields.hasNext(); ) {
+ Map.Entry<String, JsonNode> field = fields.next();
+ String fieldId = field.getKey();
+ if( field.getValue() != null && !field.getValue().getNodeType().equals(JsonNodeType.NULL)) {
+ if( field.getValue().getNodeType().equals(JsonNodeType.OBJECT)) {
+ ObjectNode clean = cleanProperties(mapper, field.getValue().deepCopy());
+ if( clean != null && clean.size() > 0 ) {
+ cleaned.put(fieldId, clean);
+ }
+ } else if ( field.getValue().getNodeType().equals(JsonNodeType.ARRAY)) {
+ ArrayNode clean = cleanArray((ArrayNode)field.getValue());
+ if( clean != null && clean.size() > 0 ) {
+ cleaned.put(fieldId, clean);
+ }
+ } else if ( field.getValue().getNodeType().equals(JsonNodeType.STRING)) {
+ String value = content.get(fieldId).asText();
+ if( value != null && StringUtils.isNotBlank(value)) {
+ cleaned.put(fieldId, value);
+ }
+ } else {
+ cleaned.put(fieldId, field.getValue());
+ }
+ }
+ }
+ return cleaned;
+ }
+
/**
* merge two arrays.
* @param content ArrayNode
@@ -150,4 +187,26 @@
return parent.deepCopy().addAll(content);
}
+ /**
+ * clean an array.
+ * @param content ArrayNode
+ * @return cleaned ArrayNode
+ */
+ private static ArrayNode cleanArray(ArrayNode content) {
+ if( content.size() == 0) return null;
+ Iterator<JsonNode> items = content.iterator();
+ for ( ; items.hasNext(); ) {
+ JsonNode item = items.next();
+ if( item == null ) items.remove();
+ if( item.getNodeType().equals(JsonNodeType.OBJECT)) {
+ if( item.size() == 0 ) items.remove();
+ }
+ if( item.getNodeType().equals(JsonNodeType.ARRAY)) {
+ if( item.size() == 0 ) items.remove();
+ }
+ }
+ if( content.size() == 0) return null;
+ else return content;
+ }
+
}
diff --git a/streams-util/src/test/java/org/apache/streams/util/test/PropertyUtilTest.java b/streams-util/src/test/java/org/apache/streams/util/test/PropertyUtilTest.java
index fdba3f0..ae292dd 100644
--- a/streams-util/src/test/java/org/apache/streams/util/test/PropertyUtilTest.java
+++ b/streams-util/src/test/java/org/apache/streams/util/test/PropertyUtilTest.java
@@ -19,14 +19,20 @@
package org.apache.streams.util.test;
import org.apache.streams.util.PropertyUtil;
-import org.apache.streams.util.schema.SchemaUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.testng.Assert.assertTrue;
+
/**
* Unit Test for PropertyUtil.
*/
@@ -37,20 +43,39 @@
String flatJson = "{\"a.b\": \"ab\", \"c.d\": \"cd\", \"a.e\": \"ae\", \"c.f\": \"cf\"}";
@Test
+ public void testFlattenToMap() throws Exception {
+ PropertyUtil propertyUtil = PropertyUtil.getInstance();
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode node = mapper.createObjectNode();
+ node.put("objectType", "post");
+ node.putArray("links").add("link1");
+ node.putObject("actor").put("id", "leftId").putObject("author").put("id", "authorId");
+ node.putObject("extensions");
+ Map flattenedMap = propertyUtil.flattenToMap(node);
+ assertThat(flattenedMap.size(), equalTo(5));
+ assertThat(flattenedMap.get("actor.id"), notNullValue());
+ assertThat(flattenedMap.get("actor.author.id"), notNullValue());
+ assertThat(flattenedMap.get("objectType"), equalTo("post"));
+ assertThat(flattenedMap.get("links"), nullValue());
+ assertThat(flattenedMap.get("links[0]"), notNullValue());
+ assertThat(flattenedMap.get("extensions"), notNullValue());
+ }
+
+ @Test
public void testUnflattenObjectNode() throws Exception {
PropertyUtil propertyUtil = PropertyUtil.getInstance();
ObjectNode flatNode = mapper.readValue(flatJson, ObjectNode.class);
ObjectNode unflattenedNode = propertyUtil.unflattenObjectNode(flatNode);
- assert(unflattenedNode.size() == 2);
- assert(unflattenedNode.get("a") != null);
- assert(unflattenedNode.get("b") == null);
- assert(unflattenedNode.get("c") != null);
- assert(unflattenedNode.get("a").size() == 2);
- assert(unflattenedNode.get("a").get("b").asText().equals("ab"));
- assert(unflattenedNode.get("a").get("e").asText().equals("ae"));
- assert(unflattenedNode.get("c").size() == 2);
- assert(unflattenedNode.get("c").get("d").asText().equals("cd"));
- assert(unflattenedNode.get("c").get("f").asText().equals("cf"));
+ assertThat(unflattenedNode.size(), equalTo(2));
+ assertThat(unflattenedNode.get("a"), notNullValue());
+ assertThat(unflattenedNode.get("b"), nullValue());
+ assertThat(unflattenedNode.get("c"), notNullValue());
+ assertThat(unflattenedNode.get("a").size(), equalTo(2));
+ assertThat(unflattenedNode.get("a").get("b").asText(), equalTo("ab"));
+ assertThat(unflattenedNode.get("a").get("e").asText(), equalTo("ae"));
+ assertThat(unflattenedNode.get("c").size(), equalTo(2));
+ assertThat(unflattenedNode.get("c").get("d").asText(), equalTo("cd"));
+ assertThat(unflattenedNode.get("c").get("f").asText(), equalTo("cf"));
}
@Test
@@ -64,17 +89,44 @@
right.putArray("links").add("link2");
right.putObject("actor").put("id", "rightId").putObject("image").put("url", "http://url.com");
JsonNode merged = PropertyUtil.mergeProperties(left, right);
- assert( merged.has("objectType"));
- assert( merged.has("actor"));
- assert( merged.has("links"));
- assert( (merged.get("links")).size() == 2);
- assert( merged.get("actor").has("id"));
- assert( merged.get("actor").get("id").asText().equals("leftId"));
- assert( merged.get("actor").has("author"));
- assert( merged.get("actor").get("author").has("id"));
- assert( merged.get("actor").has("image"));
- assert( merged.get("actor").get("image").has("url"));
+ assertTrue(merged.has("objectType"));
+ assertTrue(merged.has("actor"));
+ assertTrue(merged.has("links"));
+ assertThat((merged.get("links")).size(), equalTo(2));
+ assertTrue(merged.get("actor").has("id"));
+ assertThat(merged.get("actor").get("id").asText(), equalTo("leftId"));
+ assertTrue(merged.get("actor").has("author"));
+ assertTrue(merged.get("actor").get("author").has("id"));
+ assertTrue(merged.get("actor").has("image"));
+ assertTrue(merged.get("actor").get("image").has("url"));
}
+
+ @Test
+ public void testCleanProperties() throws Exception {
+ PropertyUtil propertyUtil = PropertyUtil.getInstance();
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode node = mapper.createObjectNode();
+ String nullid = null;
+ node.put("id", nullid);
+ node.put("objectType", "post");
+ node.putArray("links").add("link1");
+ node.putArray("urls");
+ node.putObject("actor").put("id", "leftId").putObject("author").put("id", "authorId");
+ node.putObject("object").put("id", "").put("name", "O");
+ node.putObject("target").put("id", "");
+ node.putObject("extensions");
+ ObjectNode cleaned = propertyUtil.cleanProperties(node);
+ assertThat(cleaned.has("id"), equalTo(false));
+ assertThat(cleaned.has("objectType"), equalTo(true));
+ assertThat(cleaned.has("links"), equalTo(true));
+ assertThat(cleaned.has("urls"), equalTo(false));
+ assertThat(cleaned.has("actor"), equalTo(true));
+ assertThat(cleaned.get("actor").size(), equalTo(2));
+ assertThat(cleaned.has("object"), equalTo(true));
+ assertThat(cleaned.get("object").size(), equalTo(1));
+ assertThat(cleaned.has("target"), equalTo(false));
+ assertThat(cleaned.has("extensions"), equalTo(false));
+ }
}