blob: da041c5f8ee7e9ad6aa7370005bf1209e53d53d4 [file] [log] [blame]
/*
* 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.
*/
package org.apache.streams.util;
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.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import com.github.wnameless.json.flattener.JsonFlattener;
import com.github.wnameless.json.unflattener.JsonUnflattener;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.core.JsonFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Class transforms nested properties of activities, actors, objects, etc...
*/
public class PropertyUtil {
private static final PropertyUtil INSTANCE = new PropertyUtil(new ObjectMapper());
public static PropertyUtil getInstance() {
return INSTANCE;
}
public static PropertyUtil getInstance(ObjectMapper mapper) {
return new PropertyUtil(mapper);
}
private ObjectMapper mapper;
public PropertyUtil(ObjectMapper mapper) {
this.mapper = mapper;
}
public Map<String, Object> flattenToMap(ObjectNode object) {
return flattenToMap(mapper, object);
}
public ObjectNode flattenToObjectNode(ObjectNode object) {
return flattenToObjectNode(mapper, object);
}
public ObjectNode unflattenMap(Map<String, Object> object) {
return unflattenMap(mapper, object);
}
public ObjectNode unflattenObjectNode(ObjectNode object) {
return unflattenObjectNode(mapper, object);
}
public static Map<String, Object> flattenToMap(ObjectMapper mapper, ObjectNode object) {
Map<String, Object> flatObject;
try {
flatObject = mapper.readValue(JsonFlattener.flatten(mapper.writeValueAsString(object)), Map.class);
} catch( Exception ex ) {
return null;
}
return flatObject;
}
public static ObjectNode flattenToObjectNode(ObjectMapper mapper, ObjectNode object) {
ObjectNode flatObjectNode;
try {
flatObjectNode = mapper.readValue(JsonFlattener.flatten(mapper.writeValueAsString(object)), ObjectNode.class);
} catch( Exception ex ) {
return null;
}
return flatObjectNode;
}
public static ObjectNode unflattenMap(ObjectMapper mapper, Map<String, Object> object) {
ObjectNode unflatObjectNode;
try {
unflatObjectNode = mapper.readValue(JsonUnflattener.unflatten(mapper.writeValueAsString(object)), ObjectNode.class);
} catch( Exception ex ) {
return null;
}
return unflatObjectNode;
}
public static ObjectNode unflattenObjectNode(ObjectMapper mapper, ObjectNode object) {
ObjectNode unflatObjectNode;
try {
unflatObjectNode = mapper.readValue(JsonUnflattener.unflatten(mapper.writeValueAsString(object)), ObjectNode.class);
} catch( Exception ex ) {
return null;
}
return unflatObjectNode;
}
/**
* merge parent and child properties maps.
* @param content ObjectNode
* @param parent ObjectNode
* @return merged ObjectNode
*/
public static ObjectNode mergeProperties(ObjectNode content, ObjectNode parent) {
ObjectNode merged = parent.deepCopy();
Iterator<Map.Entry<String, JsonNode>> fields = content.fields();
for ( ; fields.hasNext(); ) {
Map.Entry<String, JsonNode> field = fields.next();
String fieldId = field.getKey();
if( merged.get(fieldId) != null ) {
if( merged.get(fieldId).getNodeType().equals(JsonNodeType.OBJECT)) {
merged.put(fieldId, mergeProperties(field.getValue().deepCopy(), (ObjectNode)merged.get(fieldId)));
} else if ( merged.get(fieldId).getNodeType().equals(JsonNodeType.ARRAY)) {
merged.put(fieldId, mergeArrays(((ArrayNode)field.getValue()), ((ArrayNode)merged.get(fieldId))));
} else {
merged.put(fieldId, content.get(fieldId));
}
} else {
merged.put(fieldId, content.get(fieldId));
}
}
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
* @param parent ArrayNode
* @return merged ArrayNode
*/
private static ArrayNode mergeArrays(ArrayNode content, ArrayNode parent) {
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;
}
}