@Override
  public JType apply(String nodeName,
                     JsonNode node,
                     JsonNode parent,
                     JPackage _package,
                     Schema schema) {
    if (node.has("enum")) return null;
    JsonNode allOf = node.get("allOf");
    JsonNode anyOf = node.get("anyOf");
    JsonNode oneOf = node.get("oneOf");
    Set<String> typeNames = null;

    ArrayNode arrayNode = null;
    String arrayNodeName = null;
    if (anyOf != null && anyOf.isArray() && anyOf.size() > 1 && oneOf == null && allOf == null) {
      arrayNodeName = "anyOf";
      arrayNode = (ArrayNode)anyOf;
    }
    else if (oneOf != null && oneOf.isArray() && oneOf.size() > 1 && anyOf == null && allOf == null) {
      arrayNodeName = "oneOf";
      arrayNode = (ArrayNode)oneOf;
    }
    else {
      typeNames = getTypeNames(node);
      typeNames.remove("array");
      typeNames.remove("object");
    }
    Map<String, List<ResolvedType>> resolved;
    if (arrayNode != null) {
      resolved = preprocess(arrayNode, arrayNodeName, schema);
    }
    else {
      if (typeNames.size() <= 1) {
        return null;
      }
      var fromCache = ruleFactory.getPrimitiveTypeFromCache(nodeName, typeNames);
      if (fromCache != null) {
        return fromCache;
      }
      resolved = new HashMap<>();
      for (String type : typeNames) {
        resolved.computeIfAbsent(type, (k) -> new ArrayList<>()).add(new ResolvedPrimitiveType(type));
      }
    }
    if (schema.getJavaType() != null) {
      return schema.getJavaType();
    }
    JsonNode lenientDeserializerNode = node.get("javaLenientDeserialize");
    boolean lenientDeserialize = lenientDeserializerNode != null && lenientDeserializerNode.asBoolean(false);

    if (resolved.entrySet().stream().anyMatch(entry -> !"object".equals(entry.getKey()) && entry.getValue().size() > 1)) {
      ruleFactory.getLogger()
        .error("Only one kind of non-object type can be specified within " + arrayNodeName + ". Error for : " + nodeName);
      return null;
    }
    if (resolved.containsKey(null)) {
      ruleFactory.getLogger().error("One of " + arrayNodeName + " branches has unspecified type. Error for : " + nodeName);
      return null;
    }

    JClass objectsSuperType = null;
    JDefinedClass wrapperClass = null;
    if (resolved.keySet().size() > 1) {
      wrapperClass = createClass(nodeName, node, _package, false);
      Map<String, Object> map = new HashMap<>();
      map.put("tokens", new HashSet<>(resolved.keySet()));
      wrapperClass.metadata = map;
      schema.setJavaTypeIfEmpty(wrapperClass);
      if (typeNames != null) {
        ruleFactory.storePrimitiveTypeInCache(nodeName, typeNames, wrapperClass);
      }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    List<ResolvedClassType> objects = (List<ResolvedClassType>)(List)resolved.get("object");
    if (objects != null) {
      if (objects.size() == 1) {
        ResolvedClassType obj = objects.get(0);
        objectsSuperType = (JClass)obj.generate(ruleFactory, nodeName + "-object", arrayNode, _package);
        schema.setJavaTypeIfEmpty(objectsSuperType);
      }
      else if (objects.size() > 1) {
        String determinantPropertyName = findDeterminantField(objects);
        final JDefinedClass superType;
        if (determinantPropertyName != null) {
          // Enum based deserialization
          superType = createClass(nodeName + "-base", node, _package, true);
          schema.setJavaTypeIfEmpty(superType);
          generateEnumClass(nodeName, schema, objects, determinantPropertyName, superType);
          Map<String, JType> subTypes =
            generateEnumBasedSubTypes(nodeName, arrayNode, objects, determinantPropertyName, superType, _package);
          annotateWithEnumBasedSubtypes(superType, subTypes, determinantPropertyName);
        }
        else if (suitableForDeductionBased(objects)) {
          // Deduction based deserialization
          superType = createClass(nodeName + "-base", node, _package, true);
          schema.setJavaTypeIfEmpty(superType);
          List<JType> subTypes = generateDeductionBasedSubTypes(nodeName, arrayNode, objects, superType, _package);
          annotateWithDeductionBasedSubtypes(superType, subTypes);
        }
        else {
          ruleFactory.getLogger().error("No way to deduct object deserialization target through required properties: " + nodeName);
          return null;
        }
        objectsSuperType = superType;
      }
    }
    Map<String, JClass> generatedTypes = new LinkedHashMap<>();
    for (Map.Entry<String, List<ResolvedType>> listEntry : resolved.entrySet()) {
      if (listEntry.getKey().equals("object")) {
        generatedTypes.put("object", objectsSuperType);
      }
      else {
        generatedTypes.put(listEntry.getKey(),
                           (JClass)listEntry.getValue().get(0).generate(ruleFactory, nodeName, arrayNode, wrapperClass));
      }
    }
    if (wrapperClass != null) {
      if (generatedTypes.size() == 2 && generatedTypes.get("array") != null) {
        JType arrayType = generatedTypes.get("array");
        Pair<JType, JClass> arrayItemType = unpackArrayItemClass(arrayType);
        if (arrayItemType != null) {
          Map.Entry<String, List<ResolvedType>> entry = resolved.entrySet().stream()
            .filter(e -> !e.getKey().equals("array")).findFirst().orElseThrow();
          JType itemType;
          if (entry.getKey().equals("object")) {
            itemType = objectsSuperType;
          }
          else {
            itemType = entry.getValue().get(0).generate(ruleFactory, nodeName, arrayNode, wrapperClass);
          }
          if (itemType != null && itemType.equals(arrayItemType.getRight())) {
            generateDeserializeIntoArray(wrapperClass, entry.getKey(), arrayItemType, lenientDeserialize);
            return wrapperClass;
          }
        }
      }
      generateDeserializeIntoValueProperty(wrapperClass, generatedTypes, node);
      return wrapperClass;
    }
    return schema.getJavaType();
  }
@Override
  public JType apply(String nodeName,
                     JsonNode node,
                     JsonNode parent,
                     JPackage _package,
                     Schema schema)