001/* 002 * JDrupes Builder 003 * Copyright (C) 2025 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.java; 020 021import java.nio.file.Path; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.List; 025import java.util.Locale; 026import java.util.Optional; 027import java.util.logging.Level; 028import java.util.stream.Stream; 029import javax.tools.Diagnostic; 030import javax.tools.DiagnosticCollector; 031import javax.tools.JavaFileObject; 032import org.jdrupes.builder.api.Project; 033import org.jdrupes.builder.core.AbstractGenerator; 034 035/// A base class for generators that invoke java tools. 036/// 037public abstract class JavaTool extends AbstractGenerator { 038 039 private final List<String> options = new ArrayList<>(); 040 041 /// Instantiates a new java tool. 042 /// 043 /// @param project the project 044 /// 045 public JavaTool(Project project) { 046 super(project); 047 } 048 049 /// Adds the given options. 050 /// 051 /// @param options the options 052 /// @return the javadoc 053 /// 054 public JavaTool options(Stream<String> options) { 055 this.options.addAll(options.toList()); 056 return this; 057 } 058 059 /// Adds the given options. 060 /// 061 /// @param options the options 062 /// @return the javadoc 063 /// 064 public JavaTool options(String... options) { 065 this.options.addAll(Arrays.asList(options)); 066 return this; 067 } 068 069 /// Return the options. 070 /// 071 /// @return the stream 072 /// 073 public List<String> options() { 074 return options; 075 } 076 077 /// Find the argument for the given option. As some options are 078 /// allows in different styles, several names can be specified. 079 /// 080 /// @param names the names 081 /// @return the optional 082 /// 083 public Optional<String> optionArgument(String... names) { 084 var itr = options.iterator(); 085 if (itr.hasNext()) { 086 String opt = itr.next(); 087 if (Arrays.stream(names).anyMatch(opt::equals) && itr.hasNext()) { 088 return Optional.of(itr.next()); 089 } 090 } 091 return Optional.empty(); 092 } 093 094 /// Log diagnostic. 095 /// 096 /// @param diagnostic the diagnostic 097 /// 098 protected void logDiagnostic( 099 Diagnostic<? extends JavaFileObject> diagnostic) { 100 String msg; 101 if (diagnostic.getSource() == null) { 102 msg = diagnostic.getMessage(Locale.ENGLISH); 103 } else { 104 msg = String.format("%s:%d: %s", 105 project().rootProject().directory().relativize( 106 Path.of(diagnostic.getSource().toUri().getPath())), 107 diagnostic.getLineNumber(), 108 diagnostic.getMessage(null)); 109 } 110 Level level = switch (diagnostic.getKind()) { 111 case ERROR -> Level.SEVERE; 112 case WARNING -> Level.WARNING; 113 case MANDATORY_WARNING -> Level.WARNING; 114 default -> Level.INFO; 115 }; 116 log.log(level, () -> msg); 117 } 118 119 /// Log diagnostics. 120 /// 121 /// @param diagnostics the diagnostics 122 /// 123 protected void 124 logDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) { 125 for (var diagnostic : diagnostics.getDiagnostics()) { 126 logDiagnostic(diagnostic); 127 } 128 } 129}