public static void setValue()

in mapper-processor/src/main/java/com/datastax/oss/driver/internal/mapper/processor/util/generation/GeneratedCodePatterns.java [224:368]


  public static void setValue(
      CodeBlock cqlName,
      PropertyType type,
      CodeBlock valueExtractor,
      String targetName,
      CodeBlock.Builder methodBuilder,
      BindableHandlingSharedCode enclosingClass,
      boolean useNullSavingStrategy,
      boolean useLeniency) {

    if (type instanceof PropertyType.Simple) {
      TypeName typeName = ((PropertyType.Simple) type).typeName;
      String primitiveAccessor = GeneratedCodePatterns.PRIMITIVE_ACCESSORS.get(typeName);
      if (primitiveAccessor != null) {
        // Primitive type: use dedicated setter, since it is optimized to avoid boxing.
        //     target = target.setInt("length", entity.getLength());
        methodBuilder.addStatement(
            "$1L = $1L.set$2L($3L, $4L)",
            targetName,
            primitiveAccessor,
            cqlName,
            valueExtractor); // null saving strategy for primitiveSet does not apply
      } else if (typeName instanceof ClassName) {
        // Unparameterized class: use the generic, class-based setter.
        //     target = target.set("id", entity.getId(), UUID.class);
        generateSetWithClass(
            cqlName, valueExtractor, targetName, methodBuilder, typeName, useNullSavingStrategy);
      } else {
        // Parameterized type: create a constant and use the GenericType-based setter.
        //     private static final GenericType<List<String>> GENERIC_TYPE =
        //         new GenericType<List<String>>(){};
        //     target = target.set("names", entity.getNames(), GENERIC_TYPE);
        // Note that lists, sets and maps of unparameterized classes also fall under that
        // category. Their setter creates a GenericType under the hood, so there's no performance
        // advantage in calling them instead of the generic set().
        generateParameterizedSet(
            cqlName,
            valueExtractor,
            targetName,
            methodBuilder,
            typeName,
            enclosingClass,
            useNullSavingStrategy);
      }
    } else if (type instanceof PropertyType.SingleEntity) {
      ClassName entityClass = ((PropertyType.SingleEntity) type).entityName;
      // Other entity class: the CQL column is a mapped UDT. Example of generated code:
      //     Dimensions value = entity.getDimensions();
      //     if (value != null) {
      //       UserDefinedType udtType = (UserDefinedType) target.getType("dimensions");
      //       UdtValue udtValue = udtType.newValue();
      //       dimensionsHelper.set(value, udtValue);
      //       target = target.setUdtValue("dimensions", udtValue);
      //     }

      // Generate unique names for our temporary variables. Note that they are local so we don't
      // strictly need class-wide uniqueness, but it's simpler to reuse the NameIndex
      String udtTypeName = enclosingClass.getNameIndex().uniqueField("udtType");
      String udtValueName = enclosingClass.getNameIndex().uniqueField("udtValue");
      String valueName = enclosingClass.getNameIndex().uniqueField("value");

      methodBuilder
          .addStatement("$T $L = $L", entityClass, valueName, valueExtractor)
          .beginControlFlow("if ($L != null)", valueName)
          .addStatement(
              "$1T $2L = ($1T) $3L.getType($4L)",
              UserDefinedType.class,
              udtTypeName,
              targetName,
              cqlName)
          .addStatement("$T $L = $L.newValue()", UdtValue.class, udtValueName, udtTypeName);
      String childHelper = enclosingClass.addEntityHelperField(entityClass);
      methodBuilder
          // driver doesn't have the ability to send partial UDT, unset values values will be
          // serialized to null - set NullSavingStrategy.DO_NOT_SET explicitly
          .addStatement(
              "$L.set($L, $L,  $T.$L, $L)",
              childHelper,
              valueName,
              udtValueName,
              NullSavingStrategy.class,
              NullSavingStrategy.DO_NOT_SET,
              useLeniency ? "lenient" : false)
          .addStatement("$1L = $1L.setUdtValue($2L, $3L)", targetName, cqlName, udtValueName);
      if (useNullSavingStrategy) {
        methodBuilder.nextControlFlow(
            "else if ($L == $T.$L)",
            NULL_SAVING_STRATEGY,
            NullSavingStrategy.class,
            NullSavingStrategy.SET_TO_NULL);
      } else {
        methodBuilder.nextControlFlow("else");
      }
      methodBuilder
          .addStatement("$1L = $1L.setUdtValue($2L, null)", targetName, cqlName)
          .endControlFlow();
    } else {
      // Collection of other entity class(es): the CQL column is a collection of mapped UDTs
      // Build a copy of the value, encoding all entities into UdtValue instances on the fly.
      String mappedCollectionName = enclosingClass.getNameIndex().uniqueField("mappedCollection");
      String rawCollectionName = enclosingClass.getNameIndex().uniqueField("rawCollection");
      methodBuilder
          .addStatement("$T $L = $L", type.asTypeName(), mappedCollectionName, valueExtractor)
          .beginControlFlow("if ($L != null)", mappedCollectionName);

      CodeBlock currentCqlType = CodeBlock.of("$L.getType($L)", targetName, cqlName);
      CodeBlock.Builder udtTypesBuilder = CodeBlock.builder();
      CodeBlock.Builder conversionCodeBuilder = CodeBlock.builder();
      convertEntitiesIntoUdts(
          mappedCollectionName,
          rawCollectionName,
          type,
          currentCqlType,
          udtTypesBuilder,
          conversionCodeBuilder,
          enclosingClass,
          useLeniency);

      methodBuilder
          .add(udtTypesBuilder.build())
          .add(conversionCodeBuilder.build())
          .addStatement(
              "$1L = $1L.set($2L, $3L, $4L)",
              targetName,
              cqlName,
              rawCollectionName,
              enclosingClass.addGenericTypeConstant(type.asRawTypeName()));
      if (useNullSavingStrategy) {
        methodBuilder.nextControlFlow(
            "else if ($L == $T.$L)",
            NULL_SAVING_STRATEGY,
            NullSavingStrategy.class,
            NullSavingStrategy.SET_TO_NULL);
      } else {
        methodBuilder.nextControlFlow("else");
      }
      methodBuilder
          .addStatement(
              "$1L = $1L.set($2L, null, $3L)",
              targetName,
              cqlName,
              enclosingClass.addGenericTypeConstant(type.asRawTypeName()))
          .endControlFlow();
    }
  }