Package org.netbeans.gradle.project.java.model.idea

Source Code of org.netbeans.gradle.project.java.model.idea.IdeaJavaModelUtils$ProjectClassPaths

package org.netbeans.gradle.project.java.model.idea;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gradle.tooling.model.DomainObjectSet;
import org.gradle.tooling.model.ExternalDependency;
import org.gradle.tooling.model.idea.IdeaContentRoot;
import org.gradle.tooling.model.idea.IdeaDependency;
import org.gradle.tooling.model.idea.IdeaModule;
import org.gradle.tooling.model.idea.IdeaModuleDependency;
import org.gradle.tooling.model.idea.IdeaProject;
import org.gradle.tooling.model.idea.IdeaSourceDirectory;
import org.jtrim.utils.ExceptionHelper;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.gradle.model.GenericProjectProperties;
import org.netbeans.gradle.model.java.JavaClassPaths;
import org.netbeans.gradle.model.java.JavaCompatibilityModel;
import org.netbeans.gradle.model.java.JavaOutputDirs;
import org.netbeans.gradle.model.java.JavaSourceGroup;
import org.netbeans.gradle.model.java.JavaSourceGroupName;
import org.netbeans.gradle.model.java.JavaSourceSet;
import org.netbeans.gradle.model.java.JavaTestModel;
import org.netbeans.gradle.model.util.CollectionUtils;
import org.netbeans.gradle.project.NbStrings;
import org.netbeans.gradle.project.java.model.JavaModelSource;
import org.netbeans.gradle.project.java.model.JavaProjectDependency;
import org.netbeans.gradle.project.java.model.JavaProjectReference;
import org.netbeans.gradle.project.java.model.NbJavaModel;
import org.netbeans.gradle.project.java.model.NbJavaModule;
import org.netbeans.gradle.project.java.model.NbListedDir;
import org.netbeans.gradle.project.properties.AbstractProjectProperties;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Lookup;

public final class IdeaJavaModelUtils {
    private static final Logger LOGGER = Logger.getLogger(IdeaJavaModelUtils.class.getName());

    public static NbJavaModel createEmptyModel(FileObject projectDir) {
        File projectDirAsFile = FileUtil.toFile(projectDir);
        if (projectDirAsFile == null) {
            throw new IllegalStateException("Project directory does not exist.");
        }
        return createEmptyModel(projectDirAsFile, Lookup.EMPTY);
    }

    public static NbJavaModel createEmptyModel(File projectDir) {
        ExceptionHelper.checkNotNullArgument(projectDir, "projectDir");

        return createEmptyModel(projectDir, Lookup.EMPTY);
    }

    private static File getDefaultBuildDir(File projectDir) {
        return new File(projectDir, "build");
    }


    private static File getDefaultMainClasses(File projectDir) {
        File classesDir = new File(getDefaultBuildDir(projectDir), "classes");
        return new File(classesDir, "main");
    }

    private static File getDefaultMainClasses(IdeaModule module) {
        File moduleDir = tryGetModuleDir(module);
        return moduleDir != null ? getDefaultMainClasses(moduleDir) : null;
    }

    public static File tryGetModuleDir(IdeaModule module) {
        DomainObjectSet<? extends IdeaContentRoot> contentRoots = module.getContentRoots();
        return contentRoots.isEmpty() ? null : contentRoots.getAt(0).getRootDirectory();
    }

    public static IdeaModule tryFindMainModule(File projectDir, IdeaProject ideaModel) {
        for (IdeaModule module: ideaModel.getModules()) {
            File moduleDir = tryGetModuleDir(module);
            if (moduleDir != null && moduleDir.equals(projectDir)) {
                return module;
            }
        }
        return null;
    }

    private static NbJavaModel createUnreliableModel(
            NbJavaModule mainModule,
            Map<? extends File, ? extends JavaProjectDependency> possibleDependencies) {
        return NbJavaModel.createModel(JavaModelSource.COMPATIBLE_API, mainModule, possibleDependencies);
    }

    public static NbJavaModel createEmptyModel(File projectDir, Lookup otherModels) {
        String name = projectDir.getName();
        String level = AbstractProjectProperties.getSourceLevelFromPlatform(JavaPlatform.getDefault());

        GenericProjectProperties properties = new GenericProjectProperties(name, name, projectDir);
        JavaCompatibilityModel compatibilityModel = new JavaCompatibilityModel(level, level);

        NbJavaModule result = new NbJavaModule(
                properties,
                compatibilityModel,
                Collections.<JavaSourceSet>emptyList(),
                Collections.<NbListedDir>emptyList(),
                JavaTestModel.getDefaulTestModel(projectDir)
        );

        return createUnreliableModel(result,
                Collections.<File, JavaProjectDependency>emptyMap());
    }

    private static Collection<JavaSourceGroup> fromIdeaSourceRoots(Collection<? extends IdeaSourceDirectory> roots) {
        Map<JavaSourceGroupName, List<File>> sourceRootMap
                = new EnumMap<>(JavaSourceGroupName.class);

        for (IdeaSourceDirectory root: roots) {
            File dir = root.getDirectory();
            String name = dir.getName().toLowerCase(Locale.US);

            JavaSourceGroupName choice;
            if (name.startsWith("resource")) {
                choice = JavaSourceGroupName.RESOURCES;
            }
            else if ("groovy".equals(name)) {
                choice = JavaSourceGroupName.GROOVY;
            }
            else if ("scala".equals(name)) {
                choice = JavaSourceGroupName.SCALA;
            }
            else {
                choice = JavaSourceGroupName.JAVA;
            }

            List<File> rootsList = sourceRootMap.get(choice);
            if (rootsList == null) {
                rootsList = new LinkedList<>();
                sourceRootMap.put(choice, rootsList);
            }
            rootsList.add(dir);
        }

        List<JavaSourceGroup> result = new ArrayList<>(sourceRootMap.size());
        for (Map.Entry<JavaSourceGroupName, List<File>> entry: sourceRootMap.entrySet()) {
            result.add(new JavaSourceGroup(entry.getKey(), entry.getValue()));
        }
        return result;
    }

    private static List<JavaSourceSet> parseSourceSets(
            IdeaModule module,
            File projectDir,
            Map<String, IdeaDependencyBuilder> cache) {

        ProjectClassPaths classPaths = fetchAllDependencies(module, cache);
        File buildOutputDir = getDefaultBuildDir(projectDir);
        File classesDir = new File(buildOutputDir, "classes");
        File resourcesDir = new File(buildOutputDir, "resources");

        JavaOutputDirs mainOutputs = new JavaOutputDirs(
                new File(classesDir, JavaSourceSet.NAME_MAIN),
                new File(resourcesDir, JavaSourceSet.NAME_MAIN),
                Collections.<File>emptyList());

        JavaSourceSet.Builder main
                = new JavaSourceSet.Builder(JavaSourceSet.NAME_MAIN, mainOutputs);
        main.setClasspaths(classPaths.main);

        JavaOutputDirs testOutputs = new JavaOutputDirs(
                new File(classesDir, JavaSourceSet.NAME_TEST),
                new File(resourcesDir, JavaSourceSet.NAME_TEST),
                Collections.<File>emptyList());

        JavaSourceSet.Builder test
                = new JavaSourceSet.Builder(JavaSourceSet.NAME_TEST, testOutputs);
        test.setClasspaths(classPaths.test);

        int mainSourceRootCount = 0;
        int testSourceRootCount = 0;

        for (IdeaContentRoot contentRoot: module.getContentRoots()) {
            for (JavaSourceGroup group: fromIdeaSourceRoots(contentRoot.getSourceDirectories())) {
                main.addSourceGroup(group);
                mainSourceRootCount += group.getSourceRoots().size();
            }
            for (JavaSourceGroup group: fromIdeaSourceRoots(contentRoot.getTestDirectories())) {
                test.addSourceGroup(group);
                testSourceRootCount += group.getSourceRoots().size();
            }
        }

        List<JavaSourceSet> result = new ArrayList<>(2);
        if (mainSourceRootCount > 0) {
            result.add(main.create());
        }
        if (testSourceRootCount > 0) {
            result.add(test.create());
        }
        return result;
    }

    private static ProjectClassPaths fetchAllDependencies(
            IdeaModule module,
            Map<String, IdeaDependencyBuilder> cache) {

        IdeaDependencyBuilder result = new IdeaDependencyBuilder();
        fetchAllDependencies(module, result, Collections.<String>emptySet(), cache);

        JavaClassPaths mainClassPath = new JavaClassPaths(result.mainCompile, result.mainRuntime);
        JavaClassPaths testClassPath = new JavaClassPaths(result.testCompile, result.testRuntime);
        return new ProjectClassPaths(mainClassPath, testClassPath);
    }

    private static void fetchAllDependencies(
            IdeaModule module,
            IdeaDependencyBuilder result,
            Set<String> projectsToSkip,
            Map<String, IdeaDependencyBuilder> cache) {

        String uniqueProjectName = module.getGradleProject().getPath();

        if (projectsToSkip.contains(uniqueProjectName)) {
            return;
        }

        IdeaDependencyBuilder parsed = cache.get(uniqueProjectName);
        if (parsed != null) {
            result.setFrom(parsed);
            return;
        }

        File defaultMainBuildDir = getDefaultMainClasses(module);
        if (defaultMainBuildDir != null) {
            result.addTestCompile(defaultMainBuildDir);
        }

        Set<String> nextProjectsToSkip = null;

        for (IdeaDependency dependency: module.getDependencies()) {
            String scope = dependency.getScope().getScope();
            IdeaDependencyType dependencyType = IdeaDependencyType.fromIdeaScope(scope);

            if (dependency instanceof IdeaModuleDependency) {
                if (nextProjectsToSkip == null) {
                    nextProjectsToSkip = new HashSet<>(projectsToSkip);
                    nextProjectsToSkip.add(uniqueProjectName);
                }

                IdeaModule moduleDep = ((IdeaModuleDependency)dependency).getDependencyModule();

                IdeaDependencyBuilder subDependencies = new IdeaDependencyBuilder();
                fetchAllDependencies(moduleDep, subDependencies, nextProjectsToSkip, cache);

                File mainBuildDir = getDefaultMainClasses(moduleDep);
                if (mainBuildDir != null) {
                    result.add(dependencyType, mainBuildDir);
                }
                result.addAll(dependencyType, subDependencies);
            }
            else if (dependency instanceof ExternalDependency) {
                ExternalDependency externalDep = (ExternalDependency)dependency;
                result.add(dependencyType, externalDep.getFile());
            }
            else {
                LOGGER.log(Level.WARNING, "Unknown dependency: {0}", dependency);
            }
        }

        cache.put(uniqueProjectName, result);
    }

    private static NbListedDir findWebAppDir(Collection<JavaSourceSet> sources) {
        for (JavaSourceSet sourceSet: sources) {
            for (JavaSourceGroup sourceGroup: sourceSet.getSourceGroups()) {
                for (File sourceRoot: sourceGroup.getSourceRoots()) {
                    File parent = sourceRoot.getParentFile();
                    if (parent != null) {
                        File webapp = new File(parent, "webapp");
                        if (webapp.isDirectory()) {
                            return new NbListedDir(NbStrings.getWebPages(), webapp);
                        }
                    }
                }
            }
        }

        return null;
    }

    private static List<NbListedDir> lookupListedDirs(Collection<JavaSourceSet> sources) {
        List<NbListedDir> result = new LinkedList<>();

        NbListedDir webAppDir = findWebAppDir(sources);
        if (webAppDir != null) {
            result.add(webAppDir);
        }

        return result;
    }

    private static NbJavaModule tryParseModule(IdeaModule module,
            Map<String, IdeaDependencyBuilder> cache) {
        String uniqueName = module.getGradleProject().getPath();

        File moduleDir = tryGetModuleDir(module);
        if (moduleDir == null) {
            LOGGER.log(Level.WARNING, "Unable to find the project directory: {0}", uniqueName);
            return null;
        }

        List<JavaSourceSet> sourceSets = parseSourceSets(module, moduleDir, cache);

        String defaultLevel = AbstractProjectProperties.getSourceLevelFromPlatform(JavaPlatform.getDefault());

        String sourceLevel = module.getProject().getLanguageLevel().getLevel();
        sourceLevel = sourceLevel != null
                ? sourceLevel.replace("JDK_", "").replace("_", ".")
                : defaultLevel;

        String targetLevel = module.getProject().getJdkName();
        if (targetLevel == null) targetLevel = defaultLevel;

        sourceLevel = sourceLevel.trim();
        targetLevel = targetLevel.trim();

        String scriptDisplayName = module.getName();
        if (scriptDisplayName == null) scriptDisplayName = "";

        GenericProjectProperties properties = new GenericProjectProperties(scriptDisplayName, uniqueName, moduleDir);
        JavaCompatibilityModel compatibilityModel = new JavaCompatibilityModel(sourceLevel, targetLevel);

        List<NbListedDir> listedDirs = lookupListedDirs(sourceSets);
        JavaTestModel testModel = JavaTestModel.getDefaulTestModel(moduleDir);

        return new NbJavaModule(properties, compatibilityModel, sourceSets, listedDirs, testModel);
    }

    public static Map<File, NbJavaModel> parseFromIdeaModel(File projectDir, IdeaProject ideaModel) throws IOException {
        IdeaModule mainModule = tryFindMainModule(projectDir, ideaModel);
        if (mainModule == null) {
            throw new IOException("Unable to find the main project in the model.");
        }

        DomainObjectSet<? extends IdeaModule> modules = ideaModel.getModules();
        int modulesCount = modules.size();

        Map<String, IdeaDependencyBuilder> cache = CollectionUtils.newHashMap(modulesCount);

        Map<File, NbJavaModule> parsedModules = CollectionUtils.newHashMap(modulesCount);
        for (IdeaModule module: modules) {
            NbJavaModule parsedModule = tryParseModule(module, cache);
            if (parsedModule != null) {
                parsedModules.put(parsedModule.getModuleDir(), parsedModule);
            }
        }

        if (!parsedModules.containsKey(projectDir)) {
            throw new IOException("Unable to parse the main project from the model.");
        }

        Map<File, JavaProjectReference> asDependency = CollectionUtils.newHashMap(modulesCount);
        Map<File, JavaProjectDependency> outputDirToProject = CollectionUtils.newHashMap(modulesCount);

        for (NbJavaModule module: parsedModules.values()) {
            File moduleDir = module.getModuleDir();
            JavaProjectReference projectRef = new JavaProjectReference(moduleDir, module);
            asDependency.put(moduleDir, projectRef);

            for (JavaSourceSet sourceSet: module.getSources()) {
                File classesDir = sourceSet.getOutputDirs().getClassesDir();
                String sourceSetName = sourceSet.getName();

                outputDirToProject.put(classesDir, new JavaProjectDependency(sourceSetName, projectRef));
            }
        }

        Map<File, NbJavaModel> result = CollectionUtils.newHashMap(modulesCount);
        for (NbJavaModule module: parsedModules.values()) {
            if (module.getSources().isEmpty()) {
                LOGGER.log(Level.INFO,
                        "Disabling the Java extension because there are no sources: {0}",
                        module.getProperties().getProjectDir());
            }
            else {
                NbJavaModel model = createUnreliableModel(module, outputDirToProject);
                result.put(module.getModuleDir(), model);
            }
        }
        return result;
    }

    private static class ProjectClassPaths {
        public final JavaClassPaths main;
        public final JavaClassPaths test;

        public ProjectClassPaths(JavaClassPaths main, JavaClassPaths test) {
            assert main != null;
            assert test != null;

            this.main = main;
            this.test = test;
        }
    }

    private static class IdeaDependencyBuilder {
        private Set<File> mainCompile;
        private Set<File> mainRuntime;
        private Set<File> testCompile;
        private Set<File> testRuntime;

        public IdeaDependencyBuilder() {
            this.mainCompile = new LinkedHashSet<>();
            this.mainRuntime = new LinkedHashSet<>();
            this.testCompile = new LinkedHashSet<>();
            this.testRuntime = new LinkedHashSet<>();
        }

        public void addAll(IdeaDependencyType type, IdeaDependencyBuilder dependencies) {
            switch (type) {
                case COMPILE:
                    addMainCompile(dependencies);
                    break;
                case PROVIDED_COMPILE:
                    addMainProvidedCompile(dependencies);
                    break;
                case RUNTIME:
                    addMainRuntime(dependencies);
                    break;
                case TEST_COMPILE:
                    addTestCompile(dependencies);
                    break;
                case TEST_RUNTIME:
                    addTestRuntime(dependencies);
                    break;
                default:
                    LOGGER.log(Level.WARNING, "Unknown dependency type: {0}", type);
                    break;
            }
        }

        public void addMainCompile(IdeaDependencyBuilder dependencies) {
            addMainCompile(dependencies.mainCompile);
            addMainRuntime(dependencies.mainRuntime);
        }

        public void addMainProvidedCompile(IdeaDependencyBuilder dependencies) {
            addMainProvidedCompile(dependencies.mainCompile);
            addMainRuntime(dependencies.mainRuntime);
        }

        public void addMainRuntime(IdeaDependencyBuilder dependencies) {
            addMainRuntime(dependencies.mainRuntime);
        }

        public void addTestCompile(IdeaDependencyBuilder dependencies) {
            addTestCompile(dependencies.mainCompile);
            addTestRuntime(dependencies.mainRuntime);
        }

        public void addTestRuntime(IdeaDependencyBuilder dependencies) {
            addTestRuntime(dependencies.mainRuntime);
        }

        public void addAll(IdeaDependencyType type, Collection<File> files) {
            switch (type) {
                case COMPILE:
                    addMainCompile(files);
                    break;
                case PROVIDED_COMPILE:
                    addMainProvidedCompile(files);
                    break;
                case RUNTIME:
                    addMainRuntime(files);
                    break;
                case TEST_COMPILE:
                    addTestCompile(files);
                    break;
                case TEST_RUNTIME:
                    addTestRuntime(files);
                    break;
                default:
                    LOGGER.log(Level.WARNING, "Unknown dependency type: {0}", type);
                    break;
            }
        }

        public void addMainCompile(Collection<File> files) {
            mainCompile.addAll(files);
            mainRuntime.addAll(files);
            testCompile.addAll(files);
            testRuntime.addAll(files);
        }

        public void addMainProvidedCompile(Collection<File> files) {
            mainCompile.addAll(files);
            testCompile.addAll(files);
        }

        public void addMainRuntime(Collection<File> files) {
            mainRuntime.addAll(files);
            testRuntime.addAll(files);
        }

        public void addTestCompile(Collection<File> files) {
            testCompile.addAll(files);
            testRuntime.addAll(files);
        }

        public void addTestRuntime(Collection<File> files) {
            testRuntime.addAll(files);
        }

        public void add(IdeaDependencyType type, File file) {
            switch (type) {
                case COMPILE:
                    addMainCompile(file);
                    break;
                case PROVIDED_COMPILE:
                    addMainProvidedCompile(file);
                    break;
                case RUNTIME:
                    addMainRuntime(file);
                    break;
                case TEST_COMPILE:
                    addTestCompile(file);
                    break;
                case TEST_RUNTIME:
                    addTestRuntime(file);
                    break;
                default:
                    LOGGER.log(Level.WARNING, "Unknown dependency type: {0}", type);
                    break;
            }
        }

        public void addMainCompile(File file) {
            mainCompile.add(file);
            mainRuntime.add(file);
            testCompile.add(file);
            testRuntime.add(file);
        }

        public void addMainProvidedCompile(File file) {
            mainCompile.add(file);
            testCompile.add(file);
        }

        public void addMainRuntime(File file) {
            mainRuntime.add(file);
            testRuntime.add(file);
        }

        public void addTestCompile(File file) {
            testCompile.add(file);
            testRuntime.add(file);
        }

        public void addTestRuntime(File file) {
            testRuntime.add(file);
        }

        public void setFrom(IdeaDependencyBuilder other) {
            this.mainCompile = other.mainCompile;
            this.mainRuntime = other.mainRuntime;
            this.testCompile = other.testCompile;
            this.testRuntime = other.testRuntime;
        }
    }

    private IdeaJavaModelUtils() {
        throw new AssertionError();
    }
}
TOP

Related Classes of org.netbeans.gradle.project.java.model.idea.IdeaJavaModelUtils$ProjectClassPaths

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.