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.report; 017 018import de.cuioss.benchmarking.common.config.BenchmarkType; 019import de.cuioss.benchmarking.common.model.BenchmarkData; 020import de.cuioss.tools.logging.CuiLogger; 021 022import java.io.IOException; 023import java.io.InputStream; 024import java.nio.file.Files; 025import java.nio.file.Path; 026import java.nio.file.StandardCopyOption; 027 028import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Files.Html.*; 029import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Files.Support.*; 030import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Report.Templates.NOT_FOUND_FORMAT; 031import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Report.Templates.PATH_PREFIX; 032import static de.cuioss.benchmarking.common.util.BenchmarkingLogMessages.INFO; 033 034/** 035 * Generates HTML reports by creating a data JSON file and copying templates. 036 * <p> 037 * This generator now works in conjunction with ReportDataGenerator to: 038 * <ol> 039 * <li>Generate a standardized benchmark-data.json file with all report data</li> 040 * <li>Copy HTML templates that load and render the JSON data</li> 041 * </ol> 042 * <p> 043 * Templates use JavaScript to dynamically load and display the JSON data, 044 * making the system more maintainable and flexible. 045 */ 046public class ReportGenerator { 047 048 private static final CuiLogger LOGGER = new CuiLogger(ReportGenerator.class); 049 private final ReportDataGenerator dataGenerator; 050 051 /** 052 * Creates a ReportGenerator. 053 */ 054 public ReportGenerator() { 055 this.dataGenerator = new ReportDataGenerator(); 056 } 057 058 /** 059 * Generates the main index page and benchmark data. 060 * 061 * @param benchmarkData the benchmark data to generate reports from 062 * @param benchmarkType the type of benchmark being processed 063 * @param outputDir the output directory for HTML files 064 * @throws IOException if writing files fails 065 */ 066 public void generateIndexPage(BenchmarkData benchmarkData, BenchmarkType benchmarkType, String outputDir) throws IOException { 067 // First generate the data file 068 dataGenerator.generateDataFile(benchmarkData, benchmarkType, outputDir); 069 070 // Then copy the index template 071 LOGGER.info(INFO.GENERATING_INDEX_PAGE, 0); 072 copyTemplate(INDEX, outputDir); 073 074 Path indexFile = Path.of(outputDir).resolve(INDEX); 075 LOGGER.info(INFO.INDEX_PAGE_GENERATED, indexFile); 076 } 077 078 /** 079 * Generates the trends page. 080 * 081 * @param outputDir the output directory for HTML files 082 * @throws IOException if writing HTML files fails 083 */ 084 public void generateTrendsPage(String outputDir) throws IOException { 085 LOGGER.info(INFO.GENERATING_TRENDS_PAGE); 086 087 // Copy the trends template 088 copyTemplate(TRENDS, outputDir); 089 090 Path trendsFile = Path.of(outputDir).resolve(TRENDS); 091 LOGGER.info(INFO.TRENDS_PAGE_GENERATED, trendsFile); 092 } 093 094 /** 095 * Generates the detailed visualizer page. 096 * 097 * @param outputDir the output directory for HTML files 098 * @throws IOException if writing HTML files fails 099 */ 100 public void generateDetailedPage(String outputDir) throws IOException { 101 LOGGER.info(INFO.GENERATING_REPORTS); 102 103 // Copy the detailed template 104 copyTemplate(DETAILED, outputDir); 105 106 Path detailedFile = Path.of(outputDir).resolve(DETAILED); 107 LOGGER.info(INFO.DETAILED_PAGE_GENERATED, detailedFile); 108 } 109 110 /** 111 * Copies all necessary support files (CSS, JS, etc.) to the output directory. 112 * 113 * @param outputDir the output directory 114 * @throws IOException if copying files fails 115 */ 116 public void copySupportFiles(String outputDir) throws IOException { 117 Path outputPath = Path.of(outputDir); 118 Files.createDirectories(outputPath); 119 120 // Copy CSS file 121 copyTemplate(REPORT_STYLES_CSS, outputDir); 122 123 // Copy the data loader JavaScript 124 copyTemplate(DATA_LOADER_JS, outputDir); 125 126 // Copy robots.txt and sitemap if needed 127 copyTemplate(ROBOTS_TXT, outputDir); 128 copyTemplate(SITEMAP_XML, outputDir); 129 } 130 131 /** 132 * Copies a template file from resources to the output directory. 133 * 134 * @param templateName the name of the template file 135 * @param outputDir the output directory 136 * @throws IOException if copying fails 137 */ 138 private void copyTemplate(String templateName, String outputDir) throws IOException { 139 Path outputPath = Path.of(outputDir); 140 Files.createDirectories(outputPath); 141 142 String resourcePath = PATH_PREFIX + templateName; 143 try (InputStream is = getClass().getResourceAsStream(resourcePath)) { 144 if (is == null) { 145 throw new IOException(NOT_FOUND_FORMAT.formatted(resourcePath)); 146 } 147 Path targetFile = outputPath.resolve(templateName); 148 Files.copy(is, targetFile, StandardCopyOption.REPLACE_EXISTING); 149 } 150 } 151 152}