All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.java.com.nutanix.dp1.mic.deserializers.MicDeserializerUtils Maven / Gradle / Ivy

The newest version!
package com.nutanix.dp1.mic.deserializers;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class MicDeserializerUtils {

  public static final String OBJECT_TYPE = "$objectType";
  public static final String OBJECT_VERSION = "$fv";
  public static final String LEGACY_FQ_OBJECT_TYPE = "$fqObjectType";
  public static final String RESERVED = "$reserved";
  public static final String API_MINOR_VERSION = "minorVersion";
  private static final String DOT = ".";

  private static final String VERSION_REGEX = String.format("(.*\\.)?(v\\d+\\.r\\d+\\.(?<%s>[a|b]\\d+)?)(\\.(.*))?", API_MINOR_VERSION);
  private static final Pattern VERSION_PATTERN = Pattern.compile(VERSION_REGEX);

  public static Class getObjectTypedType(JsonNode node, String packagePrefix) throws ClassNotFoundException {
    JsonNodeType nodeType = node.getNodeType();
    if (!JsonNodeType.OBJECT.equals(node.getNodeType())) {
      log.error("Cannot get object-typed type from node of type {}", nodeType);
      throw new IllegalArgumentException(String.format("Cannot get object-typed type from node of type %s", nodeType));
    }
    JsonNode objectTypeNode = node.get(OBJECT_TYPE);
    if (objectTypeNode == null) {
      log.error("No $objectType present in object for deserialization");
      throw new IllegalArgumentException("No $objectType present in object for deserialization");
    }
    String objectTypeFromNode = objectTypeNode.textValue();
    String objectType = StringUtils.isEmpty(packagePrefix) ? objectTypeFromNode
                                                           : packagePrefix.concat(DOT).concat(objectTypeFromNode);
    return Class.forName(objectType);
  }

  private static Class getType(JsonNode node, String packagePrefix) throws ClassNotFoundException {
    log.debug("Inferring java type of json node {}", node);
    JsonNodeType nodeType = node.getNodeType();
    if (JsonNodeType.STRING.equals(nodeType)) {
      return String.class;
    }
    if (JsonNodeType.NUMBER.equals(nodeType)) {
      return Number.class;
    }
    if (JsonNodeType.BOOLEAN.equals(nodeType)) {
      return Boolean.class;
    }
    if (JsonNodeType.ARRAY.equals(nodeType)) {
      return List.class;
    }
    if (!JsonNodeType.OBJECT.equals(nodeType)) {
      log.error("Cannot deserialize node of type {}", nodeType);
      throw new IllegalArgumentException(String.format("Cannot deserialize node of type %s", nodeType));
    }
    if (node.get(OBJECT_TYPE) == null) {
      // OBJECT node without $objectType can only be Map
      return Map.class;
    }
    return getObjectTypedType(node, packagePrefix);
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  public static List readArrayNode(ObjectCodec codec, JsonNode node,
                                   String packagePrefix, Class parameterizedClass) throws IOException, ClassNotFoundException {
    List value = new ArrayList();
    int count = node.size();
    log.debug("Processing {} children of array type node", count);
    Class type = null;
    for (int i = 0; i < count; i++) {
      if (i == 0) {
        type = parameterizedClass != null ? parameterizedClass : getType(node.get(0), packagePrefix);
      }
      value.add(readValue(codec, node.get(i), packagePrefix, type));
    }
    return value;
  }


  @SuppressWarnings({"unchecked", "rawtypes"})
  public static Map readMapNode(ObjectCodec codec, JsonNode node,
                                String packagePrefix) throws IOException, ClassNotFoundException {
    Map value = new LinkedHashMap<>();
    Iterator> mapIterator = node.fields();
    while (mapIterator.hasNext()) {
      java.util.Map.Entry mapEntry = mapIterator.next();
      log.debug("Processing key {} of map type node", mapEntry.getKey());
      value.put(mapEntry.getKey(), readValue(codec, mapEntry.getValue(), packagePrefix,null));
    }
    return value;
  }

  public static Object readValue(ObjectCodec codec, JsonNode node,
                                 String packagePrefix, Class parameterizedClass) throws IOException, ClassNotFoundException {
    Class type = null;
    if (parameterizedClass != null) {
      type = parameterizedClass;
    }
    else {
      type = getType(node, packagePrefix);
    }
    if ((List.class).equals(type)) {
      //we will handle parameterized types at a sub-level later
      return readArrayNode(codec, node, packagePrefix, null);
    }
    if ((Map.class).equals(type)) {
      return readMapNode(codec, node, packagePrefix);
    }
    return readValue(codec, node, type);
  }

  public static Object readValue(ObjectCodec codec, JsonNode node, Class type) throws IOException {
    JsonParser parser;
    final String VALUE = "value";
    if (Enum.class.isAssignableFrom(type) && node.has(VALUE)) {
      parser = node.get(VALUE).traverse();
    } else {
      parser = node.traverse();
    }

    parser.setCodec(codec);
    return parser.readValueAs(type);
  }

  public static Object handleEtag(Object value, Map reservedMap) {
    if (reservedMap.containsKey("ETag")) {
      Object etagRef = reservedMap.get("ETag");
      if (value instanceof List && ((List)value).size()>0) {
        for (Object item : ((List)value)) {
          if (item instanceof MicObjectTypeTypedObject) {
            ((MicObjectTypeTypedObject) item).get$reserved().put("ETag",etagRef);
          }
        }
      }
      else if (value instanceof MicObjectTypeTypedObject) {
        ((MicObjectTypeTypedObject) value).get$reserved().put("ETag",etagRef);
      }
    }
    return value;
  }

  public static String getMinorVersion(String name) {
    Matcher matcher = VERSION_PATTERN.matcher(name);
    if (!matcher.matches()) {
      return null;
    }
    String minorVersion = matcher.group(API_MINOR_VERSION);
    if (StringUtils.isBlank(minorVersion)) {
      return null;
    }
    return minorVersion;
  }

  public static boolean classNameEquals(String name, String targetClassName) {
    return name.substring(name.lastIndexOf(".")+1).equals(targetClassName);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy