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

com.swirlds.config.processor.ConstantClassFactory Maven / Gradle / Ivy

Go to download

Swirlds is a software platform designed to build fully-distributed applications that harness the power of the cloud without servers. Now you can develop applications with fairness in decision making, speed, trust and reliability, at a fraction of the cost of traditional server-based platforms.

There is a newer version: 0.56.5
Show newest version
/*
 * Copyright (C) 2023-2024 Hedera Hashgraph, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.swirlds.config.processor;

import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import com.swirlds.config.api.ConfigProperty;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.IOException;
import java.io.Writer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import javax.lang.model.element.Modifier;
import javax.tools.JavaFileObject;

/**
 * Utilities for creating constant class files from {@link ConfigDataRecordDefinition} instances.
 * Its methods should be accessed statically, and it should not be instantiated.
 */
public final class ConstantClassFactory {

    /**
     * Property name of:
     * {@link ConfigProperty#defaultValue()}
     */
    public static final String DEFAULT_VALUE = "defaultValue";

    /**
     * private constructor to prevent instantiation
     */
    private ConstantClassFactory() {}

    /**
     * Processes a given {@link ConfigDataRecordDefinition} and writes a corresponding constant class file.
     *
     * @param configDataRecordDefinition The record definition to be processed. Must not be {@code null}.
     * @param constantsSourceFile The Java file object where the constant class should be written. Must not be {@code null}.
     *
     * @throws IOException If an error occurs while writing the constant class.
     */
    public static void doWork(
            @NonNull final ConfigDataRecordDefinition configDataRecordDefinition,
            @NonNull final JavaFileObject constantsSourceFile)
            throws IOException {

        Objects.requireNonNull(configDataRecordDefinition, "configDataRecordDefinition must not be null");
        Objects.requireNonNull(constantsSourceFile, "constantsSourceFile must not be null");

        final String originalRecordClassName =
                configDataRecordDefinition.packageName() + "." + configDataRecordDefinition.simpleClassName();

        TypeSpec.Builder constantsClassBuilder = TypeSpec.classBuilder(
                        configDataRecordDefinition.simpleClassName() + ConfigProcessorConstants.CONSTANTS_CLASS_SUFFIX)
                .addModifiers(Modifier.FINAL, Modifier.PUBLIC)
                .addJavadoc(
                        "Constraints constants for all the property names that are part of {@link $L}. Generated by {@code $L} on $L.\n@see $L\n",
                        originalRecordClassName,
                        ConstantClassFactory.class.getName(),
                        DateTimeFormatter.ISO_DATE_TIME.format(LocalDateTime.now()),
                        originalRecordClassName);

        configDataRecordDefinition.propertyDefinitions().forEach(propertyDefinition -> {
            final String name = toConstantName(
                    propertyDefinition.name().replace(configDataRecordDefinition.configDataName() + ".", ""));

            try {

                FieldSpec fieldSpec = FieldSpec.builder(
                                String.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                        .initializer("$S", propertyDefinition.name())
                        .addJavadoc(
                                "Name of the {@link $L#$L} property\n@see $L#$L\n",
                                originalRecordClassName,
                                propertyDefinition.fieldName(),
                                originalRecordClassName,
                                propertyDefinition.fieldName())
                        .build();
                constantsClassBuilder.addField(fieldSpec);
            } catch (Exception e) {
                throw new IllegalArgumentException(
                        "Error processing record:"
                                + configDataRecordDefinition.simpleClassName() + " field:"
                                + propertyDefinition.fieldName() + " annotation value:\"" + propertyDefinition.name()
                                + "\" cannot be used as a valid constant name. Check if should be a " + DEFAULT_VALUE
                                + " instead.",
                        e);
            }
        });

        TypeSpec constantsClass = constantsClassBuilder.build();
        JavaFile javaFile = JavaFile.builder(configDataRecordDefinition.packageName(), constantsClass)
                .build();

        try (Writer writer = constantsSourceFile.openWriter()) {
            javaFile.writeTo(writer);
        }
    }

    /**
     * Converts a property name into a constant name. The conversion is based on changing from camel case to snake case
     *
     * @param propertyName The property name to be converted. Must not be {@code null}.
     *
     * @return The converted constant name. Never {@code null}.
     */
    @NonNull
    public static String toConstantName(@NonNull final String propertyName) {
        Objects.requireNonNull(propertyName, "propertyName must not be null");

        final StringBuilder builder = new StringBuilder();
        for (int i = 0; i < propertyName.length(); i++) {
            final char character = propertyName.charAt(i);
            if (i > 0 && Character.isUpperCase(character)) {
                builder.append("_");
                builder.append(character);
            } else {
                builder.append(Character.toUpperCase(character));
            }
        }
        return builder.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy