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