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.io.File;
022import java.nio.file.Path;
023import java.util.Collection;
024import java.util.Collections;
025import java.util.stream.Stream;
026import org.jdrupes.builder.api.Project;
027import org.jdrupes.builder.api.Resource;
028import org.jdrupes.builder.api.ResourceRequest;
029import org.jdrupes.builder.core.AbstractGenerator;
030import static org.jdrupes.builder.java.JavaTypes.*;
031
032/// Provides [ClassTree]s or [LibraryJarFile]s from a given classpath.
033///
034public class ClasspathScanner extends AbstractGenerator {
035
036    private String path;
037
038    /// Instantiates a new classpath generator. The path needs to be
039    /// set with [#path].
040    ///
041    /// @param project the project
042    ///
043    public ClasspathScanner(Project project) {
044        super(project);
045        path = "";
046    }
047
048    /// Sets the path. The `path` is a list of directories or jar
049    /// files separated by the system's path separator. Relative
050    /// paths are resolved against the project's directory.
051    ///
052    /// @param path the path
053    /// @return the classpath scanner
054    ///
055    public ClasspathScanner path(String path) {
056        this.path = path;
057        return this;
058    }
059
060    @Override
061    protected <T extends Resource> Collection<T>
062            doProvide(ResourceRequest<T> requested) {
063        if (!requested.accepts(CodeContributionType)) {
064            return Collections.emptyList();
065        }
066
067        @SuppressWarnings("unchecked")
068        var result = (Collection<T>) Stream.of(path.split(File.pathSeparator))
069            .map(Path::of).map(p -> project().directory().resolve(p)).map(p -> {
070                if (p.toFile().isDirectory()) {
071                    return ClassTree.of(project(), p.toAbsolutePath());
072                } else {
073                    return LibraryJarFile.of(p.toAbsolutePath());
074                }
075            }).filter(e -> requested.accepts(e.type())).toList();
076        return result;
077    }
078
079}