| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.groovy.grailsproject; |
| |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| import javax.swing.Icon; |
| import javax.swing.event.ChangeListener; |
| import org.netbeans.api.java.project.JavaProjectConstants; |
| import org.netbeans.api.project.ProjectManager; |
| import org.netbeans.api.project.Sources; |
| import org.netbeans.api.project.SourceGroup; |
| import org.netbeans.api.queries.SharabilityQuery; |
| import org.netbeans.api.queries.VisibilityQuery; |
| import org.netbeans.modules.groovy.support.api.GroovySources; |
| import org.openide.filesystems.FileChangeAdapter; |
| import org.openide.filesystems.FileEvent; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileRenameEvent; |
| import org.openide.filesystems.FileStateInvalidException; |
| import org.openide.filesystems.FileSystem; |
| import org.openide.filesystems.FileUtil; |
| import org.openide.util.ChangeSupport; |
| import org.openide.util.Exceptions; |
| import org.openide.util.NbBundle; |
| |
| /** |
| * |
| * @author Martin Adamek |
| */ |
| public class GrailsSources extends FileChangeAdapter implements Sources { |
| |
| // those are dirs in project root we already know and create specific source groups |
| public static final List KNOWN_FOLDERS = Arrays.asList( |
| "docs", // NOI18N |
| "grails-app", // NOI18N |
| "lib", // NOI18N |
| "scripts", // NOI18N |
| "src", // NOI18N |
| "test", // NOI18N |
| "web-app" // NOI18N |
| ); |
| |
| // those are dirs in grails-app root we already know and create specific source groups |
| public static final List KNOWN_FOLDERS_IN_GRAILS_APP = Arrays.asList( |
| "conf", // NOI18N |
| "controllers", // NOI18N |
| "domain", // NOI18N |
| "i18n", // NOI18N |
| "services", // NOI18N |
| "taglib", // NOI18N |
| "utils", // NOI18N |
| "views" // NOI18N |
| ); |
| |
| public static final List KNOWN_OR_IGNORED_FOLDERS_IN_TEST = Arrays.asList( |
| "unit", // NOI18N |
| "integration", // NOI18N |
| "reports" // NOI18N |
| ); |
| |
| // these are working folders that we should hide from the project tree: |
| public static final List IGNORED_FOLDERS_IN_GRAILS_APP = Arrays.asList( |
| "target", // NOI18N |
| "gradle" // NOI18N |
| ); |
| |
| private final FileObject projectDir; |
| |
| private final GrailsProject project; |
| |
| private final ChangeSupport changeSupport = new ChangeSupport(this); |
| |
| private GrailsSources(GrailsProject project) { |
| this.project = project; |
| this.projectDir = project.getProjectDirectory(); |
| } |
| |
| static GrailsSources create(GrailsProject project) { |
| GrailsSources sources = new GrailsSources(project); |
| sources.startFSListener(); |
| return sources; |
| } |
| |
| private void startFSListener () { |
| try { |
| FileSystem fs = projectDir.getFileSystem(); |
| fs.addFileChangeListener(FileUtil.weakFileChangeListener(this, fs)); |
| } catch (FileStateInvalidException x) { |
| Exceptions.printStackTrace(x); |
| } |
| } |
| |
| public SourceGroup[] getSourceGroups(String type) { |
| List<Group> result = new ArrayList<Group>(); |
| if (Sources.TYPE_GENERIC.equals(type)) { |
| addGroup(projectDir, projectDir.getName(), result); |
| } else if (JavaProjectConstants.SOURCES_TYPE_JAVA.equals(type)) { |
| addGroup(SourceCategoryType.SRC_JAVA, "LBL_SrcJava", result); |
| } else if (GroovySources.SOURCES_TYPE_GROOVY.equals(type)) { |
| addGroup(SourceCategoryType.GRAILSAPP_CONF, "LBL_grails-app_conf", result); |
| addGroup(SourceCategoryType.GRAILSAPP_CONTROLLERS, "LBL_grails-app_controllers", result); |
| addGroup(SourceCategoryType.GRAILSAPP_DOMAIN, "LBL_grails-app_domain", result); |
| addGroup(SourceCategoryType.GRAILSAPP_SERVICES, "LBL_grails-app_services", result); |
| addGroup(SourceCategoryType.GRAILSAPP_TAGLIB, "LBL_grails-app_taglib", result); |
| addGroup(SourceCategoryType.GRAILSAPP_UTILS, "LBL_grails-app_utils", result); |
| addGroup(SourceCategoryType.SCRIPTS, "LBL_scripts", result); |
| addGroup(SourceCategoryType.SRC_GROOVY, "LBL_SrcGroovy", result); |
| addGroup(SourceCategoryType.TEST_INTEGRATION, "LBL_IntegrationTests", result); |
| addGroup(SourceCategoryType.TEST_UNIT, "LBL_UnitTests", result); |
| } else if (GroovySources.SOURCES_TYPE_GRAILS.equals(type)) { |
| addGroup(SourceCategoryType.LIB, "LBL_lib", result); |
| addGroup(SourceCategoryType.GRAILSAPP_I18N, "LBL_grails-app_i18n", result); |
| addGroup(SourceCategoryType.WEBAPP, "LBL_web-app", result); |
| addGroup(SourceCategoryType.GRAILSAPP_VIEWS, "LBL_grails-app_views", result); |
| addGroup(SourceCategoryType.TEMPLATES, "LBL_grails-templates", result); |
| } else if (GroovySources.SOURCES_TYPE_GRAILS_UNKNOWN.equals(type)) { |
| // plugins may reside in project dir |
| File pluginsDirFile = project.getBuildConfig().getProjectPluginsDir(); |
| FileObject pluginsDir = pluginsDirFile == null ? null : FileUtil.toFileObject( |
| FileUtil.normalizeFile(pluginsDirFile)); |
| File globalPluginsDirFile = project.getBuildConfig().getGlobalPluginsDir(); |
| FileObject globalPluginsDir = globalPluginsDirFile == null ? null : FileUtil.toFileObject( |
| FileUtil.normalizeFile(globalPluginsDirFile)); |
| |
| for (FileObject child : projectDir.getChildren()) { |
| if (child.isFolder() |
| && VisibilityQuery.getDefault().isVisible(child) |
| && !KNOWN_FOLDERS.contains(child.getName()) |
| && !IGNORED_FOLDERS_IN_GRAILS_APP.contains(child.getName()) |
| && child != pluginsDir |
| && child != globalPluginsDir) { |
| String name = child.getName(); |
| addGroup(child, Character.toUpperCase(name.charAt(0)) + name.substring(1), result); |
| } |
| } |
| |
| addGroup(SourceCategoryType.SRC_GWT, "LBL_SrcGwt", result); |
| addUnknownGroups(KNOWN_FOLDERS_IN_GRAILS_APP, result, "grails-app", null); |
| addUnknownGroups(KNOWN_OR_IGNORED_FOLDERS_IN_TEST, result, "test", "LBL_SomeTests"); |
| } |
| return result.toArray(new SourceGroup[result.size()]); |
| } |
| |
| public void addChangeListener(ChangeListener listener) { |
| changeSupport.addChangeListener(listener); |
| } |
| |
| public void removeChangeListener(ChangeListener listener) { |
| changeSupport.removeChangeListener(listener); |
| } |
| |
| @Override |
| public void fileDeleted(FileEvent fe) { |
| changeSupport.fireChange(); |
| } |
| |
| @Override |
| public void fileFolderCreated(FileEvent fe) { |
| changeSupport.fireChange(); |
| } |
| |
| @Override |
| public void fileRenamed(FileRenameEvent fe) { |
| changeSupport.fireChange(); |
| } |
| |
| private void addUnknownGroups(Collection<String> alreadyKnown, List<Group> result, |
| String relativePath, String bundleKey) { |
| FileObject folder = projectDir.getFileObject(relativePath); |
| if (folder != null) { |
| for (FileObject child : folder.getChildren()) { |
| if (child.isFolder() |
| && VisibilityQuery.getDefault().isVisible(child) |
| && !alreadyKnown.contains(child.getName())) { |
| |
| String name = child.getName(); |
| String localizedName = Character.toUpperCase(name.charAt(0)) + name.substring(1); |
| if (bundleKey != null) { |
| localizedName = NbBundle.getMessage(GrailsSources.class, bundleKey, localizedName); |
| } |
| addGroup(child, localizedName, result); |
| } |
| } |
| } |
| } |
| |
| private void addGroup(FileObject fileObject, String displayName, List<Group> list) { |
| if (fileObject != null) { |
| list.add(new Group(fileObject, displayName)); |
| } |
| } |
| |
| private void addGroup(SourceCategoryType sourceCategory, String bundleLabel, List<Group> list) { |
| FileObject fileObject = projectDir.getFileObject( |
| project.getSourceCategoriesFactory().getSourceCategory(sourceCategory).getRelativePath() |
| ); |
| if (fileObject != null) { |
| list.add(new Group(fileObject, NbBundle.getMessage(GrailsSources.class, bundleLabel))); |
| } |
| } |
| |
| private final class Group implements SourceGroup { |
| |
| private final FileObject loc; |
| private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); |
| private final String displayName; |
| |
| public Group(FileObject loc, String displayName) { |
| this.loc = loc; |
| this.displayName = displayName; |
| } |
| |
| public FileObject getRootFolder() { |
| return loc; |
| } |
| |
| public String getName() { |
| String location = loc.getPath(); |
| return location.length() > 0 ? location : "generic"; // NOI18N |
| } |
| |
| public String getDisplayName() { |
| return displayName; |
| } |
| |
| public Icon getIcon(boolean opened) { |
| return null; |
| } |
| |
| public boolean contains(FileObject file) throws IllegalArgumentException { |
| if (file == loc) { |
| return true; |
| } |
| String path = FileUtil.getRelativePath(loc, file); |
| if (path == null) { |
| throw new IllegalArgumentException(); |
| } |
| if (file.isFolder()) { |
| path += File.separator; // NOI18N |
| } |
| if (file.isFolder() && file != projectDir && ProjectManager.getDefault().isProject(file)) { |
| // #67450: avoid actually loading the nested project. |
| return false; |
| } |
| File f = FileUtil.toFile(file); |
| if (f != null && SharabilityQuery.getSharability(f) == SharabilityQuery.NOT_SHARABLE) { |
| return false; |
| } // else MIXED, UNKNOWN, or SHARABLE; or not a disk file |
| return true; |
| } |
| |
| public void addPropertyChangeListener(PropertyChangeListener l) { |
| pcs.addPropertyChangeListener(l); |
| } |
| |
| public void removePropertyChangeListener(PropertyChangeListener l) { |
| pcs.removePropertyChangeListener(l); |
| } |
| |
| @Override |
| public String toString() { |
| return "GrailsSources.Group[name=" + getName() + ",rootFolder=" + getRootFolder() + "]"; // NOI18N |
| } |
| |
| } |
| |
| } |