Package org.netbeans.gradle.project.java.query

Source Code of org.netbeans.gradle.project.java.query.GradleProjectSources$GradleSourceGroup

package org.netbeans.gradle.project.java.query;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import org.jtrim.cancel.Cancellation;
import org.jtrim.cancel.CancellationToken;
import org.jtrim.concurrent.CancelableTask;
import org.jtrim.utils.ExceptionHelper;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.api.queries.SharabilityQuery;
import org.netbeans.gradle.model.java.JavaSourceGroupName;
import org.netbeans.gradle.model.util.CollectionUtils;
import org.netbeans.gradle.project.NbGradleProject;
import org.netbeans.gradle.project.NbStrings;
import org.netbeans.gradle.project.java.JavaExtension;
import org.netbeans.gradle.project.java.JavaModelChangeListener;
import org.netbeans.gradle.project.java.model.JavaSourceGroupID;
import org.netbeans.gradle.project.java.model.NamedSourceRoot;
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.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.ChangeSupport;

public final class GradleProjectSources implements Sources, JavaModelChangeListener {
    private static final Logger LOGGER = Logger.getLogger(GradleProjectSources.class.getName());

    private static final SourceGroup[] NO_SOURCE_GROUPS = new SourceGroup[0];

    private final JavaExtension javaExt;
    private final ChangeSupport changeSupport;

    private volatile Map<String, SourceGroup[]> currentGroups;

    private final AtomicBoolean hasScanned;
    private final AtomicReference<Object> scanRequestId;

    public GradleProjectSources(JavaExtension javaExt) {
        ExceptionHelper.checkNotNullArgument(javaExt, "javaExt");

        this.javaExt = javaExt;
        this.changeSupport = new ChangeSupport(this);
        this.currentGroups = Collections.emptyMap();
        this.hasScanned = new AtomicBoolean(false);
        this.scanRequestId = new AtomicReference<>(null);

        javaExt.getSourceDirsHandler().addDirsCreatedListener(new Runnable() {
            @Override
            public void run() {
                scanForSources();
            }
        });
    }

    public static SourceGroup tryCreateSourceGroup(NamedSourceRoot root) {
        File sourceDir = root.getRoot();

        if (sourceDir.isDirectory()) {
            FileObject groupRoot = FileUtil.toFileObject(sourceDir);
            if (groupRoot != null) {
                return new GradleSourceGroup(groupRoot, root.getDisplayName());
            }
        }
        return null;
    }

    public static SourceGroup tryCreateSourceGroup(NbListedDir root) {
        File sourceDir = root.getDirectory();

        if (sourceDir.isDirectory()) {
            FileObject groupRoot = FileUtil.toFileObject(sourceDir);
            if (groupRoot != null) {
                return new GradleSourceGroup(groupRoot, root.getName());
            }
        }
        return null;
    }

    private static <K, V> void addToMultiMap(K key, V value, Map<K, List<V>> map) {
        List<V> sourceGroupList = map.get(key);
        if (sourceGroupList == null) {
            sourceGroupList = new LinkedList<>();
            map.put(key, sourceGroupList);
        }

        sourceGroupList.add(value);
    }

    private static Map<String, List<SourceGroup>> findSourceGroupsOfModule(
            NbJavaModule module) {
        Map<String, List<SourceGroup>> result = new HashMap<>(8);

        for (NamedSourceRoot root: module.getNamedSourceRoots()) {
            SourceGroup newGroup = tryCreateSourceGroup(root);
            if (newGroup == null) {
                continue;
            }

            JavaSourceGroupID groupID = root.getGroupID();

            if (groupID.getGroupName() == JavaSourceGroupName.RESOURCES) {
                addToMultiMap(JavaProjectConstants.SOURCES_TYPE_RESOURCES, newGroup, result);
            }
            else {
                addToMultiMap(JavaProjectConstants.SOURCES_TYPE_JAVA, newGroup, result);
                if (groupID.isTest()) {
                    addToMultiMap(JavaProjectConstants.SOURCES_HINT_TEST, newGroup, result);
                }

                // TODO: Consider "SOURCES_TYPE_GROOVY" and "SOURCES_TYPE_SCALA", "SOURCES_TYPE_ANTLR"
            }
        }

        for (NbListedDir listedDir: module.getListedDirs()) {
            SourceGroup newGroup = tryCreateSourceGroup(listedDir);
            if (newGroup != null) {
                addToMultiMap(JavaProjectConstants.SOURCES_TYPE_RESOURCES, newGroup, result);
            }
        }

        return result;
    }

    private Map<String, SourceGroup[]> findSourceGroups(JavaExtension javaExt) {
        NbJavaModel projectModel = javaExt.getCurrentModel();
        NbJavaModule mainModule = projectModel.getMainModule();

        Map<String, List<SourceGroup>> moduleSources = findSourceGroupsOfModule(mainModule);

        Map<String, SourceGroup[]> result = CollectionUtils.newHashMap(moduleSources.size());
        for (Map.Entry<String, List<SourceGroup>> entry: moduleSources.entrySet()) {
            List<SourceGroup> entryValue = entry.getValue();
            result.put(entry.getKey(), entryValue.toArray(new SourceGroup[entryValue.size()]));
        }

        SourceGroup[] sources = result.get(JavaProjectConstants.SOURCES_TYPE_JAVA);
        if (sources != null && sources.length > 0) {
            result.put(JavaProjectConstants.SOURCES_HINT_MAIN, new SourceGroup[]{sources[0]});
        }

        result.put(Sources.TYPE_GENERIC, getGenericGroup());

        return result;
    }

    @Override
    public void onModelChange() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                scanForSources();
            }
        });
    }

    public void scanForSources() {
        scanForSources(false);
    }

    public void ensureScanForSources() {
        scanForSources(true);
    }

    private void scanForSources(boolean initialScan) {
        if (initialScan) {
            if (!hasScanned.compareAndSet(false, true)) {
                return;
            }
        }

        final Object requestId = new Object();
        if (!scanRequestId.compareAndSet(null, requestId)) {
            return;
        }

        hasScanned.set(true);
        NbGradleProject.PROJECT_PROCESSOR.execute(Cancellation.UNCANCELABLE_TOKEN, new CancelableTask() {
            @Override
            public void execute(CancellationToken cancelToken) {
                scanRequestId.compareAndSet(requestId, null);

                Map<String, SourceGroup[]> groups = findSourceGroups(javaExt);

                currentGroups = groups;
                LOGGER.log(Level.FINE, "Location of the sources of {0} has been updated.", javaExt.getName());

                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        changeSupport.fireChange();
                    }
                });
            }
        }, null);
    }

    private SourceGroup[] getGenericGroup() {
        return new SourceGroup[]{
            new GradleSourceGroup(javaExt.getProjectDirectory())
        };
    }

    @Override
    public SourceGroup[] getSourceGroups(String type) {
        ensureScanForSources();

        SourceGroup[] foundGroup = currentGroups.get(type);
        if (foundGroup == null && Sources.TYPE_GENERIC.equals(type)) {
            return getGenericGroup();
        }
        else {
            return foundGroup != null ? foundGroup.clone() : NO_SOURCE_GROUPS;
        }
    }

    @Override
    public void addChangeListener(ChangeListener listener) {
        changeSupport.addChangeListener(listener);
    }

    @Override
    public void removeChangeListener(ChangeListener listener) {
        changeSupport.removeChangeListener(listener);
    }

    private static class GradleSourceGroup implements SourceGroup {
        private final FileObject location;
        private final PropertyChangeSupport changes;
        private final String displayName;

        public GradleSourceGroup(FileObject location) {
            this(location, NbStrings.getSrcPackageCaption());
        }

        public GradleSourceGroup(FileObject location, String displayName) {
            this.location = location;
            this.displayName = displayName;
            this.changes = new PropertyChangeSupport(this);
        }

        @Override
        public FileObject getRootFolder() {
            return location;
        }

        @Override
        public String getName() {
            String locationStr = location.getPath();
            return locationStr.length() > 0 ? locationStr : "generic";
        }

        @Override
        public String getDisplayName() {
            return displayName;
        }

        @Override
        public Icon getIcon(boolean opened) {
            return null;
        }

        @Override
        public boolean contains(FileObject file) {
            if (file == location) {
                return true;
            }

            if (FileUtil.getRelativePath(location, file) == null) {
                return false;
            }

            URI f = file.toURI();

            // else MIXED, UNKNOWN, or SHARABLE; or not a disk file
            return f == null || SharabilityQuery.getSharability(f) != SharabilityQuery.Sharability.NOT_SHARABLE;
        }

        @Override
        public void addPropertyChangeListener(PropertyChangeListener l) {
            changes.addPropertyChangeListener(l);
        }

        @Override
        public void removePropertyChangeListener(PropertyChangeListener l) {
            changes.removePropertyChangeListener(l);
        }

        @Override
        public String toString() {
            return "GradleSources.Group[name=" + getName() + ",rootFolder=" + getRootFolder() + "]";
        }
    }
}
TOP

Related Classes of org.netbeans.gradle.project.java.query.GradleProjectSources$GradleSourceGroup

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.