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