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.startup;
020
021import com.google.common.flogger.FluentLogger;
022import java.nio.file.Path;
023import java.util.Optional;
024import org.jdrupes.builder.api.FileResource;
025import org.jdrupes.builder.api.FileTree;
026import static org.jdrupes.builder.api.Intent.*;
027import org.jdrupes.builder.api.Masked;
028import org.jdrupes.builder.core.AbstractProject;
029import org.jdrupes.builder.core.ResourceCollector;
030import org.jdrupes.builder.java.ClasspathScanner;
031import org.jdrupes.builder.java.JavaCompiler;
032import org.jdrupes.builder.java.JavaResourceTree;
033import org.jdrupes.builder.java.JavaSourceFile;
034import static org.jdrupes.builder.java.JavaTypes.*;
035
036/// The JDrupes Builder project for compiling the user's JDrupes Builder
037/// project.
038///
039public class BootstrapBuild extends AbstractProject implements Masked {
040
041    private static final FluentLogger logger = FluentLogger.forEnclosingClass();
042
043    /// Instantiates a new bootstrap project.
044    ///
045    @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
046    public BootstrapBuild() {
047        super(parent(BootstrapRoot.class), jdbldDirectory());
048
049        // Add this (the builder) to the class path. (Build extensions
050        // will be added by the bootstrap launcher, because we don't have
051        // access to the properties file here.)
052        var jcp = Path.of(System.getProperty("java.class.path"))
053            .toAbsolutePath().toString();
054        logger.atFine().log("Using java.class.path %s as base for"
055            + " builder project compilation", jcp);
056        dependency(Consume, new ClasspathScanner(this).path(jcp));
057
058        // Collect directories with "build configuration", derive source
059        // trees and use as java sources.
060        var bldrDirs = FileTree.of(rootProject(), rootProject().directory(),
061            "**/" + context().jdbldDirectory().toString()).withDirectories();
062        addExcludes(bldrDirs);
063        var srcTrees = bldrDirs.stream().map(r -> FileTree.of(
064            this, r.path().resolve("src"), JavaSourceFile.class, "**/*.java"));
065        generator(JavaCompiler::new).addSources(srcTrees);
066
067        // Add resources
068        var resourceTrees = bldrDirs.stream()
069            .map(r -> JavaResourceTree.of(this,
070                r.path().resolve("resources"), "**/*"));
071        generator(new ResourceCollector<>(this, JavaResourceTreeType)
072            .add(resourceTrees));
073    }
074
075    private void addExcludes(FileTree<FileResource> bldrDirs) {
076        for (var dir : Optional.ofNullable(context().commandLine()
077            .getOptionValues("B-x")).orElse(new String[0])) {
078            bldrDirs.exclude(dir);
079        }
080    }
081
082}