All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.common.tools.SourceDependencyResolver Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/*
 * Copyright Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the authors tag. All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License version 2.
 * 
 * This particular file is subject to the "Classpath" exception as provided in the 
 * LICENSE file that accompanied this code.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */
package com.redhat.ceylon.common.tools;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

import com.redhat.ceylon.cmr.api.ModuleDependencyInfo;
import com.redhat.ceylon.cmr.api.ModuleVersionDetails;
import com.redhat.ceylon.common.Backends;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.common.ModuleUtil;
import com.redhat.ceylon.model.typechecker.model.ModelUtil;

/**
 * This class takes a list of source files and determines which modules
 * are referenced as dependencies by them that were not mentioned in the
 * original list.
 * 
 * @author Tako Schotanus ([email protected])
 */
public class SourceDependencyResolver {
    private final ModuleVersionReader moduleVersionReader;
    private final Iterable sourceDirs;
    private final Backends forBackends;
    
    private Set originalModules;
    private Set allModules;
    private Set additionalModules;
    
    public SourceDependencyResolver(ModuleVersionReader moduleVersionReader, Iterable sourceDirs, Backends forBackends) {
        this.moduleVersionReader = moduleVersionReader;
        this.sourceDirs = sourceDirs;
        this.forBackends = forBackends;
    }
    
    /**
     * Returns the list of modules as found in the list of sources
     * passed to traverseDependencies()
     * @return A list of ModuleVersionDetails
     */
    public Set getOriginalModules() {
        return originalModules;
    }

    /**
     * Returns the list of modules as found in the list of sources
     * passed to traverseDependencies() and the ones
     * that were found while traversing their dependencies
     * @return A list of ModuleVersionDetails
     */
    public Set getAllModules() {
        return allModules;
    }

    /**
     * Returns the list of dependent modules that were found while
     * traversing the list of sources passed to
     * traverseDependencies() that were not mentioned
     * in the original list of sources
     * @return A list of ModuleVersionDetails
     */
    public Set getAdditionalModules() {
        return additionalModules;
    }

    /**
     * Traverses the given sources finding all dependencies that have
     * their sources available in the source directories
     * @param sourceFiles Iterable of  pointing to sources
     * @return A boolean indicating if any additional modules were found
     */
    public boolean traverseDependencies(Iterable sourceFiles) {
        originalModules = collectModulesFromSources(sourceFiles);
        allModules = new HashSet(originalModules);
        for (ModuleVersionDetails module : originalModules) {
            collectModulesFromDependencies(allModules, module);
        }
        additionalModules = new HashSet(allModules);
        additionalModules.removeAll(originalModules);
        return !additionalModules.isEmpty();
    }

    // Recursively traverses and collects all dependencies from the
    // given module and adds their dependencies to the given set, but
    // only those that have locally available sources
    private void collectModulesFromDependencies(Set modules, String moduleName) {
        ModuleVersionDetails mvd = moduleVersionReader.fromSource(moduleName);
        if (mvd != null) {
            modules.add(mvd);
            collectModulesFromDependencies(modules, mvd);
        }
    }
    
    // Recursively traverses and collects all dependencies from the
    // given module and adds their dependencies to the given set, but
    // only those that have locally available sources
    private void collectModulesFromDependencies(Set modules, ModuleVersionDetails mvd) {
        for (ModuleDependencyInfo dep : mvd.getDependencies()) {
            if (dep.getNamespace() == null
                    && !modules.contains(dep)
                    && hasSources(dep.getName())
                    && ModelUtil.isForBackend(dep.getNativeBackends(), forBackends)) {
                collectModulesFromDependencies(modules, dep.getName());
            }
        }
    }
    
    // Determines if the given module has locally available sources
    private boolean hasSources(String moduleName) {
        for (File srcDir : sourceDirs) {
            File moduleDir = ModuleUtil.moduleToPath(srcDir, moduleName);
            if (moduleDir.isDirectory() && moduleDir.canRead()) {
                File descriptor = new File(moduleDir, Constants.MODULE_DESCRIPTOR);
                if (descriptor.isFile() && descriptor.canRead()) {
                    return true;
                }
            }
        }
        return false;
    }

    // Given the list of _all_ source files we return the list of module details
    private Set collectModulesFromSources(Iterable sourceFiles) {
        Set modules = new HashSet();
        Set descriptors = collectModuleDescriptorsFromSources(sourceFiles);
        for (File d : descriptors) {
            String moduleName = moduleNameFromDescriptorFile(d);
            ModuleVersionDetails mvd = moduleVersionReader.fromSource(moduleName);
            if (mvd != null) {
                modules.add(mvd);
            }
        }
        return modules;
    }
    
    // Given a descriptor File we return its module name
    private String moduleNameFromDescriptorFile(File descriptor) {
        String rel = FileUtil.relativeFile(sourceDirs, descriptor.getParentFile().getPath());
        return ModuleUtil.pathToModule(new File(rel));
    }

    // Given a list of source files returns only the module descriptors
    private Set collectModuleDescriptorsFromSources(Iterable sourceFiles) {
        Set files = new HashSet();
        for (File f : sourceFiles) {
            if (Constants.MODULE_DESCRIPTOR.equals(f.getName())) {
                files.add(f);
            }
        }
        return files;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy