protected GenericType inspectType()

in core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/registry/CachingCodecRegistry.java [331:406]


  protected GenericType<?> inspectType(@NonNull Object value, @Nullable DataType cqlType) {
    if (value instanceof List) {
      List<?> list = (List<?>) value;
      if (list.isEmpty()) {
        // Empty collections are always encoded the same way, so any element type will do
        // in the absence of a CQL type. When the CQL type is known, we try to infer the best Java
        // type.
        return cqlType == null ? JAVA_TYPE_FOR_EMPTY_LISTS : inferJavaTypeFromCqlType(cqlType);
      } else {
        Object firstElement = list.get(0);
        if (firstElement == null) {
          throw new IllegalArgumentException(
              "Can't infer list codec because the first element is null "
                  + "(note that CQL does not allow null values in collections)");
        }
        GenericType<?> elementType =
            inspectType(
                firstElement, cqlType == null ? null : ((ContainerType) cqlType).getElementType());
        return GenericType.listOf(elementType);
      }
    } else if (value instanceof Set) {
      Set<?> set = (Set<?>) value;
      if (set.isEmpty()) {
        return cqlType == null ? JAVA_TYPE_FOR_EMPTY_SETS : inferJavaTypeFromCqlType(cqlType);
      } else {
        Object firstElement = set.iterator().next();
        if (firstElement == null) {
          throw new IllegalArgumentException(
              "Can't infer set codec because the first element is null "
                  + "(note that CQL does not allow null values in collections)");
        }
        GenericType<?> elementType =
            inspectType(
                firstElement, cqlType == null ? null : ((SetType) cqlType).getElementType());
        return GenericType.setOf(elementType);
      }
    } else if (value instanceof Map) {
      Map<?, ?> map = (Map<?, ?>) value;
      if (map.isEmpty()) {
        return cqlType == null ? JAVA_TYPE_FOR_EMPTY_MAPS : inferJavaTypeFromCqlType(cqlType);
      } else {
        Map.Entry<?, ?> firstEntry = map.entrySet().iterator().next();
        Object firstKey = firstEntry.getKey();
        Object firstValue = firstEntry.getValue();
        if (firstKey == null || firstValue == null) {
          throw new IllegalArgumentException(
              "Can't infer map codec because the first key and/or value is null "
                  + "(note that CQL does not allow null values in collections)");
        }
        GenericType<?> keyType =
            inspectType(firstKey, cqlType == null ? null : ((MapType) cqlType).getKeyType());
        GenericType<?> valueType =
            inspectType(firstValue, cqlType == null ? null : ((MapType) cqlType).getValueType());
        return GenericType.mapOf(keyType, valueType);
      }
    } else if (value instanceof CqlVector) {
      CqlVector<?> vector = (CqlVector<?>) value;
      if (vector.isEmpty()) {
        return cqlType == null ? JAVA_TYPE_FOR_EMPTY_CQLVECTORS : inferJavaTypeFromCqlType(cqlType);
      } else {
        Object firstElement = vector.iterator().next();
        if (firstElement == null) {
          throw new IllegalArgumentException(
              "Can't infer vector codec because the first element is null "
                  + "(note that CQL does not allow null values in collections)");
        }
        GenericType<?> elementType =
            inspectType(
                firstElement, cqlType == null ? null : ((VectorType) cqlType).getElementType());
        return GenericType.vectorOf(elementType);
      }
    } else {
      // There's not much more we can do
      return GenericType.of(value.getClass());
    }
  }