public ImageSpec buildSpecModel()

in plugins/core-plugin/src/main/java/com/google/cloud/teleport/plugin/model/TemplateDefinitions.java [110:334]


  public ImageSpec buildSpecModel(boolean validateFlag) {

    if (validateFlag) {
      validate(templateAnnotation);
    }

    ImageSpec imageSpec = new ImageSpec();

    SdkInfo sdkInfo = new SdkInfo();

    // Xlang templates require the java language.
    if (templateAnnotation.type() == TemplateType.XLANG) {
      sdkInfo.setLanguage("JAVA");
    } else {
      sdkInfo.setLanguage(templateAnnotation.type().toString());
    }

    imageSpec.setSdkInfo(sdkInfo);

    imageSpec = updateStreamingModeRelatedDefaultEnvironment(imageSpec);

    ImageSpecMetadata metadata = new ImageSpecMetadata();
    metadata.setInternalName(templateAnnotation.name());
    metadata.setName(templateAnnotation.displayName());
    metadata.setDescription(
        List.of(templateAnnotation.description()).stream().collect(Collectors.joining("\n\n")));
    metadata.setCategory(
        new ImageSpecCategory(
            templateAnnotation.category().getName(),
            templateAnnotation.category().getDisplayName()));
    metadata.setModule(getClassModule());
    metadata.setDocumentationLink(templateAnnotation.documentation());
    metadata.setGoogleReleased(
        templateAnnotation.documentation() != null
            && templateAnnotation.documentation().contains("cloud.google.com"));
    metadata.setHidden(templateAnnotation.hidden());
    metadata.setPreview(templateAnnotation.preview());
    metadata.setRequirements(Arrays.asList(templateAnnotation.requirements()));

    metadata.setStreaming(templateAnnotation.streaming());
    metadata.setSupportsAtLeastOnce(templateAnnotation.supportsAtLeastOnce());
    metadata.setSupportsExactlyOnce(templateAnnotation.supportsExactlyOnce());

    metadata.setDefaultStreamingMode(templateAnnotation.defaultStreamingMode().toString());

    metadata.setAdditionalDocumentation(
        Arrays.stream(templateAnnotation.additionalDocumentation())
            .map(
                block ->
                    new ImageSpecAdditionalDocumentation(
                        block.name(), Arrays.asList(block.content())))
            .collect(Collectors.toList()));

    if (templateAnnotation.placeholderClass() != null
        && templateAnnotation.placeholderClass() != void.class) {
      metadata.setMainClass(templateAnnotation.placeholderClass().getName());
    } else {
      metadata.setMainClass(templateClass.getName());
    }

    LOG.info(
        "Processing template for class {}. Template name: {}",
        templateClass,
        templateAnnotation.name());

    List<MethodDefinitions> methodDefinitions = new ArrayList<>();

    int order = 0;
    Map<Class<?>, Integer> classOrder = new HashMap<>();

    Class<?> optionsClass = templateAnnotation.optionsClass();
    if (optionsClass == void.class) {
      optionsClass = templateClass;
    }

    if (templateAnnotation.optionsOrder() != null) {
      for (Class<?> options : templateAnnotation.optionsOrder()) {
        classOrder.putIfAbsent(options, order++);
      }
    }

    // If blocks were defined, go through each block's option class
    if (templateAnnotation.blocks()[0] != void.class) {
      try {
        List<ExecutionBlock> executionBlocks = AutoTemplate.buildExecutionBlocks(templateClass);
        for (ExecutionBlock block : executionBlocks) {
          classOrder.putIfAbsent(block.getBlockInstance().getOptionsClass(), order++);
        }
        optionsClass =
            AutoTemplate.createNewOptionsClass(
                executionBlocks,
                templateClass.getClassLoader(),
                AutoTemplate.getDlqInstance(templateClass));
      } catch (Exception e) {
        throw new RuntimeException("Error parsing template blocks", e);
      }
    }

    classOrder.putIfAbsent(optionsClass, order++);

    Set<String> parameterNames = new HashSet<>();

    Method[] methods = optionsClass.getMethods();
    for (Method method : methods) {
      method.setAccessible(true);

      // Ignore the method if it contains @TemplateIgnoreParameter
      if (method.getAnnotation(TemplateIgnoreParameter.class) != null) {
        continue;
      }

      classOrder.putIfAbsent(method.getDeclaringClass(), order++);

      Annotation parameterAnnotation = MetadataUtils.getParameterAnnotation(method);
      if (parameterAnnotation == null) {

        boolean runtime = false;

        TemplateCreationParameters creationParameters =
            method.getAnnotation(TemplateCreationParameters.class);
        String methodName = method.getName();
        if (creationParameters != null) {
          for (TemplateCreationParameter creationParameterCandidate : creationParameters.value()) {

            if (creationParameterCandidate.template().equals(templateAnnotation.name())
                || StringUtils.isEmpty(creationParameterCandidate.template())) {
              runtime = true;

              if (StringUtils.isNotEmpty(creationParameterCandidate.value())) {
                metadata
                    .getRuntimeParameters()
                    .put(
                        getParameterNameFromMethod(methodName), creationParameterCandidate.value());
              }
            }
          }
        }

        TemplateCreationParameter creationParameter =
            method.getAnnotation(TemplateCreationParameter.class);
        if (creationParameter != null) {
          runtime = true;

          if (StringUtils.isNotEmpty(creationParameter.value())) {
            metadata
                .getRuntimeParameters()
                .put(getParameterNameFromMethod(methodName), creationParameter.value());
          }
        }

        // Ignore non-annotated params in this criteria (non-options params)
        if (runtime
            || methodName.startsWith("set")
            || IGNORED_FIELDS.contains(methodName)
            || method.getDeclaringClass().getName().startsWith("org.apache.beam.sdk")
            || method.getDeclaringClass().getName().startsWith("org.apache.beam.runners")
            || method.getReturnType() == void.class
            || IGNORED_DECLARING_CLASSES.contains(method.getDeclaringClass().getSimpleName())) {
          continue;
        }

        if (validateFlag) {
          validate(method);
        }

        continue;
      }

      methodDefinitions.add(new MethodDefinitions(method, parameterAnnotation, classOrder));
    }

    Set<String> skipOptionsSet = Set.of(templateAnnotation.skipOptions());
    Set<String> optionalOptionsSet = Set.of(templateAnnotation.optionalOptions());
    Collections.sort(methodDefinitions);

    for (MethodDefinitions method : methodDefinitions) {
      Annotation parameterAnnotation = method.getTemplateParameter();
      ImageSpecParameter parameter =
          getImageSpecParameter(
              method.getDefiningMethod().getName(),
              method.getDefiningMethod(),
              parameterAnnotation);

      if (skipOptionsSet.contains(parameter.getName())) {
        continue;
      }
      if (optionalOptionsSet.contains(parameter.getName())) {
        parameter.setOptional(true);
      }

      // Set the default value, if any
      Object defaultVal = getDefault(method.getDefiningMethod());
      if (defaultVal != null) {
        parameter.setDefaultValue(String.valueOf(defaultVal));
      }

      if (parameterNames.add(parameter.getName())) {
        metadata.getParameters().add(parameter);
      } else {
        LOG.warn(
            "Parameter {} was already added for the Template {}, skipping repetition.",
            parameter.getName(),
            templateAnnotation.name());
      }
    }

    boolean isFlex = StringUtils.isNotEmpty(templateAnnotation.flexContainerName());
    metadata.setFlexTemplate(isFlex);

    imageSpec.setAdditionalUserLabel(
        "goog-dataflow-provided-template-name", templateAnnotation.name().toLowerCase());
    imageSpec.setAdditionalUserLabel(
        "goog-dataflow-provided-template-type", isFlex ? "flex" : "classic");
    imageSpec.setImage("gcr.io/{project-id}/" + templateAnnotation.flexContainerName());
    imageSpec.setMetadata(metadata);

    metadata.setUdfSupport(
        metadata.getParameters().stream()
            .anyMatch(
                parameter ->
                    parameter.getName().contains("javascriptTextTransformGcsPath")
                        || parameter.getName().contains("javascriptTextTransformFunctionName")));

    return imageSpec;
  }