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

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

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.common.tools;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;

import com.redhat.ceylon.common.Backend;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.common.ModuleDescriptorReader;
import com.redhat.ceylon.common.ModuleSpec;
import com.redhat.ceylon.common.ModuleUtil;

/**
 * Class with helper methods for expanding a list of module names/specs
 * that possibly contain wildcards into an expanded list of actual modules
 * that were found on the file system
 * @author Tako Schotanus
 */
public abstract class ModuleWildcardsHelper {

    /**
     * Given a source directory and a list of ModuleSpecs
     * that possibly contain wildcards it returns a expanded list of
     * ModuleSpecs of modules that were actually found in the given
     * source directory. ModuleSpecs that didn't contain wildcards
     * are left alone (it's not checked if they exist or not).
     * If a Backend is passed expanded modules will be checked if
     * they support it (they either don't have a native annotation
     * or it is for the correct backend).
     * @param dirs The source directory
     * @param names The list of ModuleSpecs
     * @param forBackend The Backend for which we work or null
     * @return An expanded list of ModuleSpecs
     */
    public static List expandSpecWildcards(File dir, List modules, Backend forBackend) {
        List dirs = new ArrayList();
        dirs.add(dir);
        return expandSpecWildcards(dirs, modules, forBackend);
    }

    /**
     * Given a list of source directories and a list of ModuleSpecs
     * that possibly contain wildcards it returns a expanded list of
     * ModuleSpecs of modules that were actually found in the given
     * source directories. ModuleSpecs that didn't contain wildcards
     * are left alone (it's not checked if they exist or not).
     * If a Backend is passed expanded modules will be checked if
     * they support it (they either don't have a native annotation
     * or it is for the correct backend).
     * @param dirs The list of source directories
     * @param names The list of ModuleSpecs
     * @param forBackend The Backend for which we work or null
     * @return An expanded list of ModuleSpecs
     */
    public static List expandSpecWildcards(List dirs, List modules, Backend forBackend) {
        List result = new ArrayList(modules.size());
        for (ModuleSpec spec : modules) {
            List names = new ArrayList();
            expandWildcard(names, dirs, spec.getName(), forBackend);
            for (String name : names) {
                result.add(new ModuleSpec(spec.getNamespace(), name, spec.getVersion()));
            }
        }
        return result;
    }

    /**
     * Given a source directory and a list of module names
     * that possibly contain wildcards it returns a expanded list of
     * module names of modules that were actually found in the given
     * source directory. Module names that didn't contain wildcards
     * are left alone (it's not checked if they exist or not).
     * If a Backend is passed expanded modules will be checked if
     * they support it (they either don't have a native annotation
     * or it is for the correct backend).
     * @param dirs The source directory
     * @param names The list of module names
     * @param forBackend The Backend for which we work or null
     * @return An expanded list of module names
     */
    public static List expandWildcards(File dir, Collection modules, Backend forBackend) {
        List dirs = new ArrayList();
        dirs.add(dir);
        return expandWildcards(dirs, modules, forBackend);
    }

    /**
     * Given a list of source directories and a list of module names
     * that possibly contain wildcards it returns a expanded list of
     * module names of modules that were actually found in the given
     * source directories. Module names that didn't contain wildcards
     * are left alone (it's not checked if they exist or not).
     * If a Backend is passed expanded modules will be checked if
     * they support it (they either don't have a native annotation
     * or it is for the correct backend).
     * @param dirs The list of source directories
     * @param names The list of module names
     * @param forBackend The Backend for which we work or null
     * @return An expanded list of module names
     */
    public static List expandWildcards(Iterable dirs, Collection names, Backend forBackend) {
        List result = new ArrayList(names.size());
        for (String name : names) {
            expandWildcard(result, dirs, name, forBackend);
        }
        return result;
    }

    public static void expandWildcard(List result, Iterable dirs, String name, Backend forBackend) {
        if (name.endsWith("*")) {
            int p = name.lastIndexOf('.');
            String parentPath = ".";
            String namePrefix = "";
            if (p >= 0) {
                String parentName = name.substring(0, p);
                parentPath = parentName.replace('.', File.separatorChar);
                namePrefix = name.substring(p + 1, name.length() - 1);
            } else {
                namePrefix = name.substring(0, name.length() - 1);
            }
            Set modules = findModules(dirs, parentPath, namePrefix, forBackend);
            result.addAll(modules);
        } else {
            result.add(name);
        }
    }

    public static boolean isValidModuleDir(Iterable dirs, String name) {
        if (isModuleName(name)) {
            String path = name.replace('.', File.separatorChar);
            if (existsSourceSubDir(dirs, path)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isModuleName(String name) {
        String[] parts = name.split("\\.");
        for (String part : parts) {
            if (!isNamePart(part)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isNamePart(String part) {
        if (part.isEmpty()) {
            return false;
        }
        Matcher m = ModuleUtil.moduleIdPattern.matcher(part);
        return m.matches();
    }

    public static boolean onlyGlobArgs(List names) {
        for (String name : names) {
            if (!name.endsWith("*")) {
                return false;
            }
        }
        return true;
    }

    private static boolean existsSourceSubDir(Iterable dirs, String file) {
        for (File dir : dirs) {
            File subDir = new File(dir, file);
            if (subDir.isDirectory() && subDir.canRead()) {
                return true;
            }
        }
        return false;
    }

    private static Set findModules(Iterable dirs, String modPath, String prefix, Backend forBackend) {
        Set modules = new LinkedHashSet();
        for (File dir : dirs) {
            File modDir = new File(dir, modPath);
            if (modDir.isDirectory() && modDir.canRead()) {
                findModules(modules, dir, modDir, prefix, forBackend, true);
            }
        }
        return modules;
    }
    
    private static void findModules(Set modules, File root, File dir, String prefix, Backend forBackend, boolean first) {
        File descriptor = new File(dir, Constants.MODULE_DESCRIPTOR);
        if (descriptor.isFile()) {
            File modDir = FileUtil.relativeFile(root, dir);
            String modName = modDir.getPath().replace(File.separatorChar, '.');
            if (includeModule(modName, root, prefix, forBackend)) {
                modules.add(modName);
            }
        } else if (first || prefix == null || prefix.isEmpty()) {
            File[] files = dir.listFiles();
            for (File f : files) {
                if (f.isDirectory() && f.canRead() && isNamePart(f.getName())) {
                    findModules(modules, root, f, prefix, forBackend, false);
                } else if (f.isFile() && f.canRead()
                        && f.getName().endsWith(Constants.CEYLON_SUFFIX)
                        && (prefix == null || prefix.isEmpty())) {
                    modules.add("default");
                }
            }
        }
    }
    
    private static boolean includeModule(String name, File sourceRoot, String prefix, Backend forBackend) {
        if (prefix != null) {
            int p = name.lastIndexOf('.');
            String lastPart = (p >= 0) ? name.substring(p + 1) : name;
            if (!lastPart.startsWith(prefix)) {
                return false;
            }
        }
        if (forBackend != null) {
            try {
                ModuleDescriptorReader mdr = new ModuleDescriptorReader(name, sourceRoot);
                List backends = mdr.getModuleBackends();
                return backends.isEmpty() || backends.contains(forBackend.nativeAnnotation);
            } catch(ModuleDescriptorReader.NoSuchModuleException x) {
                x.printStackTrace();
            }
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy