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 java.nio.file.Path;
022import java.util.Optional;
023import java.util.logging.Logger;
024import org.jdrupes.builder.api.FileResource;
025import org.jdrupes.builder.api.FileTree;
026import static org.jdrupes.builder.api.Intend.*;
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    /// The log.
042    protected final Logger log = Logger.getLogger(getClass().getName());
043
044    /// Instantiates a new bootstrap project.
045    ///
046    @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
047    public BootstrapBuild() {
048        super(parent(BootstrapRoot.class), jdbldDirectory());
049
050        // Add this (the builder) to the class path. (Build extensions
051        // will be added by the bootstrap launcher, because we don't have
052        // access to the properties file here.)
053        var jcp = Path.of(System.getProperty("java.class.path"))
054            .toAbsolutePath().toString();
055        log.fine(() -> "Using java.class.path " + jcp
056            + " for builder project compilation");
057        dependency(Consume, new ClasspathScanner(this, jcp));
058
059        // Collect directories with "build configuration", derive source
060        // trees and use as java sources.
061        var bldrDirs
062            = newResource(new ResourceType<FileTree<FileResource>>() {},
063                Path.of("").toAbsolutePath(),
064                "**/" + context().jdbldDirectory().toString())
065                    .withDirectories();
066        addExcludes(bldrDirs);
067        var srcTrees = bldrDirs.stream()
068            .map(r -> newResource(JavaSourceTreeType, r.path().resolve("src"),
069                "**/*.java"));
070        generator(JavaCompiler::new).addSources(srcTrees);
071
072        // Add resources
073        var resourceTrees = bldrDirs.stream()
074            .map(r -> newResource(JavaResourceTreeType,
075                r.path().resolve("resources"), "**/*"));
076        generator(new ResourceCollector<>(this, JavaResourceTreeType)
077            .add(resourceTrees));
078    }
079
080    private void addExcludes(FileTree<FileResource> bldrDirs) {
081        for (var dir : Optional.ofNullable(context().commandLine()
082            .getOptionValues("B-x")).orElse(new String[0])) {
083            bldrDirs.exclude(dir);
084        }
085    }
086
087}