001/*
002 * Copyright © 2025 CUI-OpenSource-Software (info@cuioss.de)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.cuioss.benchmarking.common.config;
017
018import de.cuioss.tools.logging.CuiLogger;
019import org.openjdk.jmh.results.format.ResultFormatType;
020
021import java.io.File;
022
023import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Files.Directories;
024import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Integration.Jmh;
025import static de.cuioss.benchmarking.common.util.BenchmarkingLogMessages.WARN.UNKNOWN_RESULT_FORMAT;
026
027/**
028 * Configuration for benchmark report generation.
029 * Contains all report-specific settings that control how benchmark results
030 * are processed and presented.
031 * 
032 * <p>Example usage:
033 * <pre>{@code
034 * var reportConfig = ReportConfiguration.builder()
035 *     .withBenchmarkType(BenchmarkType.MICRO)
036 *     .withThroughputBenchmarkName("measureThroughput")
037 *     .withLatencyBenchmarkName("measureAverageTime")
038 *     .withResultsDirectory("target/benchmark-results")
039 *     .build();
040 * }</pre>
041 * 
042 */
043public record ReportConfiguration(
044BenchmarkType benchmarkType,
045String throughputBenchmarkName,
046String latencyBenchmarkName,
047String resultsDirectory,
048String resultFile,
049ResultFormatType resultFormat,
050String projectName
051) {
052    private static final CuiLogger LOGGER = new CuiLogger(ReportConfiguration.class);
053
054
055    /**
056     * Creates a builder with default values.
057     * 
058     * @return a new builder with default values
059     */
060    public static Builder builder() {
061        return new Builder();
062    }
063
064    /**
065     * Creates a builder from this configuration.
066     * 
067     * @return a new builder initialized with this configuration's values
068     */
069    public Builder toBuilder() {
070        return new Builder()
071                .withBenchmarkType(benchmarkType)
072                .withThroughputBenchmarkName(throughputBenchmarkName)
073                .withLatencyBenchmarkName(latencyBenchmarkName)
074                .withResultsDirectory(resultsDirectory)
075                .withResultFile(resultFile)
076                .withResultFormat(resultFormat)
077                .withProjectName(projectName);
078    }
079
080    /**
081     * Gets the result file path, generating one if not explicitly set.
082     * Creates the results directory if it doesn't exist.
083     * 
084     * @return the result file path
085     */
086    public String getOrCreateResultFile() {
087        if (resultFile != null) {
088            return resultFile;
089        }
090
091        // Create results directory if it doesn't exist
092        File dir = new File(resultsDirectory);
093        if (!dir.exists()) {
094            boolean created = dir.mkdirs();
095            if (!created) {
096                // Directory already exists or could not be created
097                // Log warning if needed, but continue with default path
098            }
099        }
100
101        // Generate result file name based on benchmark type
102        String typePrefix = benchmarkType != null ? benchmarkType.name().toLowerCase() : "benchmark";
103        return resultsDirectory + "/" + typePrefix + "-result.json";
104    }
105
106    /**
107     * Builder for ReportConfiguration.
108     */
109    public static class Builder {
110        private BenchmarkType benchmarkType;
111        private String throughputBenchmarkName;
112        private String latencyBenchmarkName;
113        private String resultsDirectory = Directories.RESULTS_DIR;
114        private String resultFile;
115        private ResultFormatType resultFormat = parseResultFormat(System.getProperty(Jmh.RESULT_FORMAT, "JSON"));
116        private String projectName;
117
118        public Builder withBenchmarkType(BenchmarkType type) {
119            this.benchmarkType = type;
120            return this;
121        }
122
123        public Builder withThroughputBenchmarkName(String name) {
124            this.throughputBenchmarkName = name;
125            return this;
126        }
127
128        public Builder withLatencyBenchmarkName(String name) {
129            this.latencyBenchmarkName = name;
130            return this;
131        }
132
133        public Builder withResultsDirectory(String dir) {
134            this.resultsDirectory = dir;
135            return this;
136        }
137
138        public Builder withResultFile(String file) {
139            this.resultFile = file;
140            return this;
141        }
142
143        public Builder withResultFormat(ResultFormatType format) {
144            this.resultFormat = format;
145            return this;
146        }
147
148        public Builder withProjectName(String name) {
149            this.projectName = name;
150            return this;
151        }
152
153        /**
154         * Builds the configuration.
155         * 
156         * @return the built configuration
157         * @throws IllegalArgumentException if required fields are not set
158         */
159        public ReportConfiguration build() {
160            // Validate required fields
161            if (benchmarkType == null) {
162                throw new IllegalArgumentException("Benchmark type must be set");
163            }
164            if (throughputBenchmarkName == null || throughputBenchmarkName.isBlank()) {
165                throw new IllegalArgumentException("Throughput benchmark name must be set");
166            }
167            if (latencyBenchmarkName == null || latencyBenchmarkName.isBlank()) {
168                throw new IllegalArgumentException("Latency benchmark name must be set");
169            }
170
171            return new ReportConfiguration(
172                    benchmarkType,
173                    throughputBenchmarkName,
174                    latencyBenchmarkName,
175                    resultsDirectory,
176                    resultFile,
177                    resultFormat,
178                    projectName
179            );
180        }
181
182        private static ResultFormatType parseResultFormat(String format) {
183            return switch (format.toUpperCase()) {
184                case "JSON" -> ResultFormatType.JSON;
185                case "CSV" -> ResultFormatType.CSV;
186                case "SCSV" -> ResultFormatType.SCSV;
187                case "LATEX" -> ResultFormatType.LATEX;
188                case "TEXT" -> ResultFormatType.TEXT;
189                default -> {
190                    LOGGER.warn(UNKNOWN_RESULT_FORMAT, format);
191                    yield ResultFormatType.JSON;
192                }
193            };
194        }
195    }
196}