blob: ec185d28681c6f690d3e747566433fa49820cb45 [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
* 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.atlas.utils;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.atlas.model.notification.EntityNotification;
import org.apache.atlas.model.notification.EntityNotification.EntityNotificationType;
import org.apache.atlas.model.notification.HookNotification;
import org.apache.atlas.model.notification.HookNotification.HookNotificationType;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.v1.model.instance.Struct;
import org.apache.atlas.v1.model.notification.EntityNotificationV1;
import org.apache.atlas.v1.model.notification.HookNotificationV1.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.text.ParseException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class AtlasJson {
private static final Logger LOG = LoggerFactory.getLogger(AtlasJson.class);
private static final ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
private static final ObjectMapper mapperV1 = new ObjectMapper()
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
static {
SimpleModule atlasSerDeModule = new SimpleModule("AtlasSerDe", new Version(1, 0, 0, null));
atlasSerDeModule.addSerializer(Date.class, new DateSerializer());
atlasSerDeModule.addDeserializer(Date.class, new DateDeserializer());
atlasSerDeModule.addDeserializer(HookNotification.class, new HookNotificationDeserializer());
atlasSerDeModule.addDeserializer(EntityNotification.class, new EntityNotificationDeserializer());
mapperV1.registerModule(atlasSerDeModule);
}
public static String toJson(Object obj) {
String ret;
try {
ret = mapper.writeValueAsString(obj);
}catch (IOException e){
LOG.error("AtlasJson.toJson()", e);
ret = null;
}
return ret;
}
public static <T> T fromJson(String jsonStr, Class<T> type) {
T ret;
try {
ret = mapper.readValue(jsonStr, type);
}catch (IOException e){
LOG.error("AtlasType.fromJson()", e);
ret = null;
}
return ret;
}
public static String toV1Json(Object obj) {
String ret;
try {
ret = mapperV1.writeValueAsString(obj);
}catch (IOException e){
LOG.error("AtlasType.toV1Json()", e);
ret = null;
}
return ret;
}
public static <T> T fromV1Json(String jsonStr, Class<T> type) {
T ret;
try {
ret = mapperV1.readValue(jsonStr, type);
if (ret instanceof Struct) {
((Struct) ret).normalize();
}
}catch (IOException e){
LOG.error("AtlasType.fromV1Json()", e);
ret = null;
}
return ret;
}
public static <T> T fromV1Json(String jsonStr, TypeReference<T> type) {
T ret;
try {
ret = mapperV1.readValue(jsonStr, type);
}catch (IOException e){
LOG.error("AtlasType.toV1Json()", e);
ret = null;
}
return ret;
}
public static ObjectNode createV1ObjectNode() {
return mapperV1.createObjectNode();
}
public static ObjectNode createV1ObjectNode(String key, Object value) {
ObjectNode ret = mapperV1.createObjectNode();
ret.putPOJO(key, value);
return ret;
}
public static ArrayNode createV1ArrayNode() {
return mapperV1.createArrayNode();
}
public static ArrayNode createV1ArrayNode(Collection<?> array) {
ArrayNode ret = mapperV1.createArrayNode();
for (Object elem : array) {
ret.addPOJO(elem);
}
return ret;
}
public static JsonNode parseToV1JsonNode(String json) throws IOException {
JsonNode jsonNode = mapperV1.readTree(json);
return jsonNode;
}
public static ArrayNode parseToV1ArrayNode(String json) throws IOException {
JsonNode jsonNode = mapperV1.readTree(json);
if (jsonNode instanceof ArrayNode) {
return (ArrayNode)jsonNode;
}
throw new IOException("not an array");
}
public static ArrayNode parseToV1ArrayNode(Collection<String> jsonStrings) throws IOException {
ArrayNode ret = createV1ArrayNode();
for (String json : jsonStrings) {
JsonNode jsonNode = mapperV1.readTree(json);
ret.add(jsonNode);
}
return ret;
}
static class DateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
if (value != null) {
jgen.writeString(AtlasBaseTypeDef.DATE_FORMATTER.format(value));
}
}
}
static class DateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser parser, DeserializationContext context) throws IOException {
Date ret = null;
String value = parser.readValueAs(String.class);
if (value != null) {
try {
ret = AtlasBaseTypeDef.DATE_FORMATTER.parse(value);
} catch (ParseException excp) {
}
}
return ret;
}
}
static class HookNotificationDeserializer extends JsonDeserializer<HookNotification> {
@Override
public HookNotification deserialize(JsonParser parser, DeserializationContext context) throws IOException {
HookNotification ret = null;
ObjectCodec mapper = parser.getCodec();
TreeNode root = mapper.readTree(parser);
JsonNode typeNode = root != null ? (JsonNode) root.get("type") : null;
String strType = typeNode != null ? typeNode.asText() : null;
HookNotificationType notificationType = strType != null ? HookNotificationType.valueOf(strType) : null;
if (notificationType != null) {
switch (notificationType) {
case TYPE_CREATE:
case TYPE_UPDATE:
ret = mapper.treeToValue(root, TypeRequest.class);
break;
case ENTITY_CREATE:
ret = mapper.treeToValue(root, EntityCreateRequest.class);
break;
case ENTITY_PARTIAL_UPDATE:
ret = mapper.treeToValue(root, EntityPartialUpdateRequest.class);
break;
case ENTITY_FULL_UPDATE:
ret = mapper.treeToValue(root, EntityUpdateRequest.class);
break;
case ENTITY_DELETE:
ret = mapper.treeToValue(root, EntityDeleteRequest.class);
break;
}
}
return ret;
}
}
static class EntityNotificationDeserializer extends JsonDeserializer<EntityNotification> {
@Override
public EntityNotification deserialize(JsonParser parser, DeserializationContext context) throws IOException {
EntityNotification ret = null;
ObjectCodec mapper = parser.getCodec();
TreeNode root = mapper.readTree(parser);
JsonNode typeNode = root != null ? (JsonNode) root.get("type") : null;
String strType = typeNode != null ? typeNode.asText() : null;
EntityNotificationType notificationType = strType != null ? EntityNotificationType.valueOf(strType) : EntityNotificationType.ENTITY_NOTIFICATION_V1;
if (root != null) {
switch (notificationType) {
case ENTITY_NOTIFICATION_V1:
ret = mapper.treeToValue(root, EntityNotificationV1.class);
break;
}
}
return ret;
}
}
}