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

com.nutanix.dp1.net.deserializers.NetDeserializerUtils Maven / Gradle / Ivy

package com.nutanix.dp1.net.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 NetDeserializerUtils {

  public static final String OBJECT_TYPE = "$objectType";
  public static final String 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);
    for (int i = 0; i < count; i++) {
      value.add(readValue(codec, node.get(i), packagePrefix, parameterizedClass));
    }
    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 = 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 NetObjectTypeTypedObject) {
            ((NetObjectTypeTypedObject) item).get$reserved().put("ETag",etagRef);
          }
        }
      }
      else if (value instanceof NetObjectTypeTypedObject) {
        ((NetObjectTypeTypedObject) 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