Maven: displaying plugins' goals in the 'select before run task' dialog
[fedora-idea.git] / plugins / maven / src / main / java / org / jetbrains / idea / maven / navigator / MavenProjectsStructure.java
blob4af25939d6b0a841ccdddceadc089dbc8ee6f5ef
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.idea.maven.navigator;
18 import com.intellij.ide.projectView.impl.nodes.NamedLibraryElement;
19 import com.intellij.ide.util.treeView.NodeDescriptor;
20 import com.intellij.ide.util.treeView.NodeRenderer;
21 import com.intellij.openapi.module.Module;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.roots.OrderEntry;
24 import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
25 import com.intellij.openapi.util.Comparing;
26 import com.intellij.openapi.util.Disposer;
27 import com.intellij.openapi.util.Pair;
28 import com.intellij.openapi.util.text.StringUtil;
29 import com.intellij.openapi.vfs.VirtualFile;
30 import com.intellij.pom.Navigatable;
31 import com.intellij.psi.PsiManager;
32 import com.intellij.ui.ErrorLabel;
33 import com.intellij.ui.GroupedElementsRenderer;
34 import com.intellij.ui.SimpleTextAttributes;
35 import com.intellij.ui.treeStructure.*;
36 import com.intellij.util.containers.ContainerUtil;
37 import gnu.trove.THashMap;
38 import org.jetbrains.annotations.NonNls;
39 import org.jetbrains.annotations.Nullable;
40 import org.jetbrains.annotations.TestOnly;
41 import org.jetbrains.idea.maven.embedder.MavenEmbedderFactory;
42 import org.jetbrains.idea.maven.importing.MavenRootModelAdapter;
43 import org.jetbrains.idea.maven.project.*;
44 import org.jetbrains.idea.maven.tasks.MavenShortcutsManager;
45 import org.jetbrains.idea.maven.tasks.MavenTasksManager;
46 import org.jetbrains.idea.maven.utils.*;
48 import javax.swing.*;
49 import javax.swing.tree.DefaultTreeModel;
50 import javax.swing.tree.TreeCellRenderer;
51 import javax.swing.tree.TreePath;
52 import java.awt.*;
53 import java.awt.event.InputEvent;
54 import java.net.URL;
55 import java.util.*;
56 import java.util.List;
58 import static org.jetbrains.idea.maven.project.ProjectBundle.message;
60 public class MavenProjectsStructure extends SimpleTreeStructure {
61 private static final URL ERROR_ICON_URL = MavenProjectsStructure.class.getResource("/images/error.png");
62 private static final Collection<String> BASIC_PHASES = MavenEmbedderFactory.getBasicPhasesList();
63 private static final Collection<String> PHASES = MavenEmbedderFactory.getPhasesList();
65 private static final Comparator<MavenSimpleNode> NODE_COMPARATOR = new Comparator<MavenSimpleNode>() {
66 public int compare(MavenSimpleNode o1, MavenSimpleNode o2) {
67 return Comparing.compare(o1.getName(), o2.getName());
71 private final Project myProject;
72 private final MavenProjectsManager myProjectsManager;
73 private final MavenTasksManager myTasksManager;
74 private final MavenShortcutsManager myShortcutsManager;
75 private final MavenProjectsNavigator myProjectsNavigator;
77 private final SimpleTreeBuilder myTreeBuilder;
78 private final RootNode myRoot = new RootNode();
80 private final Map<MavenProject, ProjectNode> myProjectToNodeMapping = new THashMap<MavenProject, ProjectNode>();
82 public MavenProjectsStructure(Project project,
83 MavenProjectsManager projectsManager,
84 MavenTasksManager tasksManager,
85 MavenShortcutsManager shortcutsManager,
86 MavenProjectsNavigator projectsNavigator,
87 SimpleTree tree) {
88 myProject = project;
89 myProjectsManager = projectsManager;
90 myTasksManager = tasksManager;
91 myShortcutsManager = shortcutsManager;
92 myProjectsNavigator = projectsNavigator;
94 configureTree(tree);
96 myTreeBuilder = new SimpleTreeBuilder(tree, (DefaultTreeModel)tree.getModel(), this, null);
97 Disposer.register(myProject, myTreeBuilder);
99 myTreeBuilder.initRoot();
100 myTreeBuilder.expand(myRoot, null);
103 private void configureTree(final SimpleTree tree) {
104 tree.setRootVisible(false);
105 tree.setShowsRootHandles(true);
107 MavenUIUtil.installCheckboxRenderer(tree, new MavenUIUtil.CheckboxHandler() {
108 public void toggle(TreePath treePath, InputEvent e) {
109 SimpleNode node = tree.getNodeFor(treePath);
110 if (node != null) {
111 node.handleDoubleClickOrEnter(tree, e);
115 public boolean isVisible(Object userObject) {
116 return userObject instanceof ProfileNode;
119 public MavenUIUtil.CheckBoxState getState(Object userObject) {
120 MavenProfileState state = ((ProfileNode)userObject).getState();
121 switch (state) {
122 case NONE: return MavenUIUtil.CheckBoxState.UNCHECKED;
123 case EXPLICIT: return MavenUIUtil.CheckBoxState.CHECKED;
124 case IMPLICIT: return MavenUIUtil.CheckBoxState.PARTIAL;
126 MavenLog.LOG.error("unknown profile state: " + state);
127 return MavenUIUtil.CheckBoxState.UNCHECKED;
132 public RootNode getRootElement() {
133 return myRoot;
136 public void update() {
137 List<MavenProject> projects = myProjectsManager.getProjects();
138 List<MavenProject> deleted = new ArrayList<MavenProject>(myProjectToNodeMapping.keySet());
139 deleted.removeAll(projects);
140 updateProjects(projects, deleted);
143 private void updateFrom(SimpleNode node) {
144 myTreeBuilder.addSubtreeToUpdateByElement(node);
147 private void updateUpTo(SimpleNode node) {
148 SimpleNode each = node;
149 while (each != null) {
150 updateFrom(each);
151 each = each.getParent();
155 public void updateProjects(List<MavenProject> updated, List<MavenProject> deleted) {
156 for (MavenProject each : updated) {
157 ProjectNode node = findNodeFor(each);
158 if (node == null) {
159 node = new ProjectNode(each);
160 myProjectToNodeMapping.put(each, node);
162 doUpdateProject(node);
165 for (MavenProject each : deleted) {
166 ProjectNode node = myProjectToNodeMapping.remove(each);
167 if (node != null) {
168 ProjectsGroupNode parent = node.getGroup();
169 parent.remove(node);
173 myRoot.updateProfiles();
176 private void doUpdateProject(ProjectNode node) {
177 MavenProject project = node.getMavenProject();
179 ProjectsGroupNode newParentNode = myRoot;
181 if (myProjectsNavigator.getGroupModules()) {
182 MavenProject aggregator = myProjectsManager.findAggregator(project);
183 if (aggregator != null) {
184 ProjectNode aggregatorNode = findNodeFor(aggregator);
185 if (aggregatorNode != null && aggregatorNode.isVisible()) {
186 newParentNode = aggregatorNode.getModulesNode();
191 node.updateProject();
192 reconnectNode(node, newParentNode);
194 ProjectsGroupNode newModulesParentNode = myProjectsNavigator.getGroupModules() && node.isVisible() ? node.getModulesNode() : myRoot;
195 for (MavenProject each : myProjectsManager.getModules(project)) {
196 ProjectNode moduleNode = findNodeFor(each);
197 if (moduleNode != null && !moduleNode.getParent().equals(newModulesParentNode)) {
198 reconnectNode(moduleNode, newModulesParentNode);
203 private void reconnectNode(ProjectNode node, ProjectsGroupNode newParentNode) {
204 ProjectsGroupNode oldParentNode = node.getGroup();
205 if (oldParentNode == null || !oldParentNode.equals(newParentNode)) {
206 if (oldParentNode != null) {
207 oldParentNode.remove(node);
209 newParentNode.add(node);
211 else {
212 newParentNode.sortProjects();
216 public void updateProfiles() {
217 myRoot.updateProfiles();
220 public void updateIgnored(List<MavenProject> projects) {
221 for (MavenProject each : projects) {
222 ProjectNode node = findNodeFor(each);
223 if (node == null) continue;
224 node.updateIgnored();
228 public void accept(SimpleNodeVisitor visitor) {
229 ((SimpleTree)myTreeBuilder.getTree()).accept(myTreeBuilder, visitor);
232 public void updateGoals() {
233 for (ProjectNode each : myProjectToNodeMapping.values()) {
234 each.updateGoals();
238 public void select(MavenProject project) {
239 ProjectNode node = findNodeFor(project);
240 if (node != null) select(node);
243 public void select(SimpleNode node) {
244 myTreeBuilder.select(node, null);
247 private ProjectNode findNodeFor(MavenProject project) {
248 return myProjectToNodeMapping.get(project);
251 enum DisplayKind {
252 ALWAYS, NEVER, NORMAL
255 protected Class<? extends MavenSimpleNode>[] getVisibleNodesClasses() {
256 return null;
259 protected boolean showDescriptions() {
260 return true;
263 protected boolean showOnlyBasicPhases() {
264 return myProjectsNavigator.getShowBasicPhasesOnly();
267 public static <T extends MavenSimpleNode> List<T> getSelectedNodes(SimpleTree tree, Class<T> nodeClass) {
268 final List<T> filtered = new ArrayList<T>();
269 for (SimpleNode node : getSelectedNodes(tree)) {
270 if ((nodeClass != null) && (!nodeClass.isInstance(node))) {
271 filtered.clear();
272 break;
274 //noinspection unchecked
275 filtered.add((T)node);
277 return filtered;
280 private static List<SimpleNode> getSelectedNodes(SimpleTree tree) {
281 List<SimpleNode> nodes = new ArrayList<SimpleNode>();
282 TreePath[] treePaths = tree.getSelectionPaths();
283 if (treePaths != null) {
284 for (TreePath treePath : treePaths) {
285 nodes.add(tree.getNodeFor(treePath));
288 return nodes;
291 @Nullable
292 public static ProjectNode getCommonProjectNode(Collection<? extends MavenSimpleNode> nodes) {
293 ProjectNode parent = null;
294 for (MavenSimpleNode node : nodes) {
295 ProjectNode nextParent = node.findParent(ProjectNode.class);
296 if (parent == null) {
297 parent = nextParent;
299 else if (parent != nextParent) {
300 return null;
303 return parent;
306 public enum ErrorLevel {
307 NONE, ERROR
310 public abstract class MavenSimpleNode extends CachingSimpleNode {
311 private MavenSimpleNode myParent;
312 private ErrorLevel myErrorLevel = ErrorLevel.NONE;
313 private ErrorLevel myTotalErrorLevel = null;
315 public MavenSimpleNode(MavenSimpleNode parent) {
316 super(MavenProjectsStructure.this.myProject, null);
317 setParent(parent);
320 public void setParent(MavenSimpleNode parent) {
321 myParent = parent;
324 @Override
325 public NodeDescriptor getParentDescriptor() {
326 return myParent;
329 public <T extends MavenSimpleNode> T findParent(Class<T> parentClass) {
330 MavenSimpleNode node = this;
331 while (true) {
332 node = node.myParent;
333 if (node == null || parentClass.isInstance(node)) {
334 //noinspection unchecked
335 return (T)node;
340 public boolean isVisible() {
341 return getDisplayKind() != DisplayKind.NEVER;
344 public DisplayKind getDisplayKind() {
345 Class[] visibles = getVisibleNodesClasses();
346 if (visibles == null) return DisplayKind.NORMAL;
348 for (Class each : visibles) {
349 if (each.isInstance(this)) return DisplayKind.ALWAYS;
351 return DisplayKind.NEVER;
355 @Override
356 protected SimpleNode[] buildChildren() {
357 List<? extends MavenSimpleNode> children = doGetChildren();
358 if (children.isEmpty()) return NO_CHILDREN;
360 List<MavenSimpleNode> result = new ArrayList<MavenSimpleNode>();
361 for (MavenSimpleNode each : children) {
362 if (each.isVisible()) result.add(each);
364 return result.toArray(new MavenSimpleNode[result.size()]);
367 protected List<? extends MavenSimpleNode> doGetChildren() {
368 return Collections.emptyList();
371 @Override
372 public void cleanUpCache() {
373 super.cleanUpCache();
374 myTotalErrorLevel = null;
377 protected void childrenChanged() {
378 MavenSimpleNode each = this;
379 while (each != null) {
380 each.cleanUpCache();
381 each = (MavenSimpleNode)each.getParent();
383 updateUpTo(this);
386 public ErrorLevel getTotalErrorLevel() {
387 if (myTotalErrorLevel == null) {
388 myTotalErrorLevel = calcTotalErrorLevel();
390 return myTotalErrorLevel;
393 private ErrorLevel calcTotalErrorLevel() {
394 ErrorLevel childrenErrorLevel = getChildrenErrorLevel();
395 return childrenErrorLevel.compareTo(myErrorLevel) > 0 ? childrenErrorLevel : myErrorLevel;
398 public ErrorLevel getChildrenErrorLevel() {
399 ErrorLevel result = ErrorLevel.NONE;
400 for (SimpleNode each : getChildren()) {
401 ErrorLevel eachLevel = ((MavenSimpleNode)each).getTotalErrorLevel();
402 if (eachLevel.compareTo(result) > 0) result = eachLevel;
404 return result;
407 public void setErrorLevel(ErrorLevel level) {
408 if (myErrorLevel == level) return;
409 myErrorLevel = level;
410 updateUpTo(this);
413 @Override
414 protected void doUpdate() {
415 setNameAndTooltip(getName(), null);
418 protected void setNameAndTooltip(String name, @Nullable String tooltip) {
419 setNameAndTooltip(name, tooltip, (String)null);
422 protected void setNameAndTooltip(String name, @Nullable String tooltip, @Nullable String hint) {
423 setNameAndTooltip(name, tooltip, getPlainAttributes());
424 if (showDescriptions() && !StringUtil.isEmptyOrSpaces(hint)) {
425 addColoredFragment(" (" + hint + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
429 protected void setNameAndTooltip(String name, @Nullable String tooltip, SimpleTextAttributes attribs) {
430 clearColoredText();
431 addColoredFragment(name, prepareAttribs(attribs));
432 getTemplatePresentation().setTooltip(tooltip);
435 private SimpleTextAttributes prepareAttribs(SimpleTextAttributes from) {
436 ErrorLevel level = getTotalErrorLevel();
437 Color waveColor = level == ErrorLevel.NONE ? null : Color.RED;
438 int style = from.getStyle();
439 if (waveColor != null) style |= SimpleTextAttributes.STYLE_WAVED;
440 return new SimpleTextAttributes(from.getBgColor(), from.getFgColor(), waveColor, style);
443 @Nullable
444 @NonNls
445 String getActionId() {
446 return null;
449 @Nullable
450 @NonNls
451 String getMenuId() {
452 return null;
455 @Nullable
456 public VirtualFile getVirtualFile() {
457 return null;
460 @Nullable
461 public Navigatable getNavigatable() {
462 VirtualFile file = getVirtualFile();
463 if (file == null || !file.isValid()) return null;
464 return PsiManager.getInstance(getProject()).findFile(file);
467 public void handleDoubleClickOrEnter(SimpleTree tree, InputEvent inputEvent) {
468 String actionId = getActionId();
469 if (actionId != null) {
470 MavenUIUtil.executeAction(actionId, inputEvent);
475 public abstract class GroupNode extends MavenSimpleNode {
476 public GroupNode(MavenSimpleNode parent) {
477 super(parent);
480 @Override
481 public boolean isVisible() {
482 if (getDisplayKind() == DisplayKind.ALWAYS) return true;
484 for (SimpleNode each : getChildren()) {
485 if (((MavenSimpleNode)each).isVisible()) return true;
487 return false;
490 protected <T extends MavenSimpleNode> void insertSorted(List<T> list, T newObject) {
491 int pos = Collections.binarySearch(list, newObject, NODE_COMPARATOR);
492 list.add(pos >= 0 ? pos : -pos - 1, newObject);
495 protected void sort(List<? extends MavenSimpleNode> list) {
496 Collections.sort(list, NODE_COMPARATOR);
500 public abstract class ProjectsGroupNode extends GroupNode {
501 private final List<ProjectNode> myProjectNodes = new ArrayList<ProjectNode>();
503 public ProjectsGroupNode(MavenSimpleNode parent) {
504 super(parent);
505 setIcons(MavenIcons.CLOSED_MODULES_ICON, MavenIcons.OPEN_MODULES_ICON);
508 @Override
509 protected List<? extends MavenSimpleNode> doGetChildren() {
510 return myProjectNodes;
513 @TestOnly
514 public List<ProjectNode> getProjectNodesInTests() {
515 return myProjectNodes;
518 protected void add(ProjectNode projectNode) {
519 projectNode.setParent(this);
520 insertSorted(myProjectNodes, projectNode);
522 childrenChanged();
525 public void remove(ProjectNode projectNode) {
526 projectNode.setParent(null);
527 myProjectNodes.remove(projectNode);
529 childrenChanged();
532 public void sortProjects() {
533 sort(myProjectNodes);
534 childrenChanged();
538 public class RootNode extends ProjectsGroupNode {
539 private ProfilesNode myProfilesNode;
541 public RootNode() {
542 super(null);
543 myProfilesNode = new ProfilesNode(this);
546 @Override
547 public boolean isVisible() {
548 return true;
551 @Override
552 protected List<? extends MavenSimpleNode> doGetChildren() {
553 return ContainerUtil.concat(Collections.singletonList(myProfilesNode), super.doGetChildren());
556 public void updateProfiles() {
557 myProfilesNode.updateProfiles();
561 public class ProfilesNode extends GroupNode {
562 private List<ProfileNode> myProfileNodes = new ArrayList<ProfileNode>();
564 public ProfilesNode(MavenSimpleNode parent) {
565 super(parent);
566 setIcons(MavenIcons.CLOSED_PROFILES_ICON, MavenIcons.OPEN_PROFILES_ICON);
569 protected List<? extends MavenSimpleNode> doGetChildren() {
570 return myProfileNodes;
573 @Override
574 public String getName() {
575 return message("view.node.profiles");
578 public void updateProfiles() {
579 Collection<Pair<String,MavenProfileState>> profiles = myProjectsManager.getProfilesWithStates();
581 List<ProfileNode> newNodes = new ArrayList<ProfileNode>(profiles.size());
582 for (Pair<String, MavenProfileState> each : profiles) {
583 ProfileNode node = findOrCreateNodeFor(each.first);
584 node.setState(each.second);
585 newNodes.add(node);
588 myProfileNodes = newNodes;
589 sort(myProfileNodes);
590 childrenChanged();
593 private ProfileNode findOrCreateNodeFor(String profileName) {
594 for (ProfileNode each : myProfileNodes) {
595 if (each.getProfileName().equals(profileName)) return each;
597 return new ProfileNode(this, profileName);
601 public class ProfileNode extends MavenSimpleNode {
602 private final String myProfileName;
603 private MavenProfileState myState;
605 public ProfileNode(ProfilesNode parent, String profileName) {
606 super(parent);
607 myProfileName = profileName;
610 @Override
611 public String getName() {
612 return myProfileName;
615 public String getProfileName() {
616 return myProfileName;
619 public MavenProfileState getState() {
620 return myState;
623 private void setState(MavenProfileState state) {
624 myState = state;
627 @Nullable
628 @NonNls
629 protected String getActionId() {
630 return "Maven.ToggleProfile";
634 public class ProjectNode extends GroupNode {
635 private final MavenProject myMavenProject;
636 private final LifecycleNode myLifecycleNode;
637 private final PluginsNode myPluginsNode;
638 private final DependenciesNode myDependenciesNode;
639 private final ModulesNode myModulesNode;
641 private String myTooltipCache;
643 public ProjectNode(MavenProject mavenProject) {
644 super(null);
645 myMavenProject = mavenProject;
647 myLifecycleNode = new LifecycleNode(this);
648 myPluginsNode = new PluginsNode(this);
649 myDependenciesNode = new DependenciesNode(this);
650 myModulesNode = new ModulesNode(this);
652 setUniformIcon(MavenIcons.MAVEN_PROJECT_ICON);
653 updateProject();
656 public MavenProject getMavenProject() {
657 return myMavenProject;
660 public ProjectsGroupNode getGroup() {
661 return (ProjectsGroupNode)super.getParent();
664 @Override
665 public boolean isVisible() {
666 if (!myProjectsNavigator.getShowIgnored() && myProjectsManager.isIgnored(myMavenProject)) return false;
667 return super.isVisible();
670 @Override
671 protected List<? extends MavenSimpleNode> doGetChildren() {
672 return Arrays.asList(myLifecycleNode, myPluginsNode, myDependenciesNode, myModulesNode);
676 public ModulesNode getModulesNode() {
677 return myModulesNode;
680 private void updateProject() {
681 setErrorLevel(myMavenProject.getProblems().isEmpty() ? ErrorLevel.NONE : ErrorLevel.ERROR);
682 myLifecycleNode.updateGoalsList();
683 myPluginsNode.updatePlugins(myMavenProject);
684 myDependenciesNode.updateDependencies(myMavenProject);
686 myTooltipCache = makeDescription();
688 updateFrom(getParent());
691 public void updateIgnored() {
692 getGroup().childrenChanged();
695 public void updateGoals() {
696 updateFrom(myLifecycleNode);
697 updateFrom(myPluginsNode);
700 @Override
701 public String getName() {
702 return myMavenProject.getDisplayName();
705 @Override
706 protected void doUpdate() {
707 setNameAndTooltip(getName(), myTooltipCache);
710 @Override
711 protected SimpleTextAttributes getPlainAttributes() {
712 if (myProjectsManager.isIgnored(myMavenProject)) {
713 return new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, Color.GRAY);
715 return super.getPlainAttributes();
718 private String makeDescription() {
719 StringBuilder desc = new StringBuilder();
720 desc.append("<html>");
721 desc.append("<table>");
722 desc.append("<tr>");
723 desc.append("<td>");
724 desc.append(" <table>");
725 desc.append(" <tr>");
726 desc.append(" <td>Project:</td>");
727 desc.append(" <td nowrap>" + myMavenProject.getMavenId() + "</td>");
728 desc.append(" </tr>");
729 desc.append(" <tr>");
730 desc.append(" <td>Location:</td>");
731 desc.append(" <td nowrap>" + myMavenProject.getPath() + "</td>");
732 desc.append(" </tr>");
733 desc.append(" </table>");
734 desc.append("</td>");
735 desc.append("</tr>");
736 appendProblems(desc);
738 desc.append("</table>");
739 desc.append("</html>");
740 return desc.toString();
743 private void appendProblems(StringBuilder desc) {
744 List<MavenProjectProblem> problems = myMavenProject.getProblems();
745 if (problems.isEmpty()) return;
747 desc.append("<tr>");
748 desc.append("<td>");
749 desc.append("<table>");
750 boolean first = true;
751 for (MavenProjectProblem each : problems) {
752 desc.append("<tr>");
753 if (first) {
754 desc.append("<td valign=top>" + MavenUtil.formatHtmlImage(ERROR_ICON_URL) + "</td>");
755 desc.append("<td valign=top>Problems:</td>");
756 first = false;
758 else {
759 desc.append("<td colspan=2></td>");
761 desc.append("<td valign=top>" + wrappedText(each));
762 desc.append("</tr>");
764 desc.append("</table>");
765 desc.append("</td>");
766 desc.append("</tr>");
769 private String wrappedText(MavenProjectProblem each) {
770 String text = StringUtil.replace(each.getDescription(), new String[]{"<", ">"}, new String[]{"&lt;", "&gt;"});
771 StringBuffer result = new StringBuffer();
772 int count = 0;
773 for (int i = 0; i < text.length(); i++) {
774 char ch = text.charAt(i);
775 result.append(ch);
777 if (count++ > 80) {
778 if (ch == ' ') {
779 count = 0;
780 result.append("<br>");
784 return result.toString();
787 @Override
788 public VirtualFile getVirtualFile() {
789 return myMavenProject.getFile();
792 @Nullable
793 @NonNls
794 protected String getMenuId() {
795 return "Maven.NavigatorProjectMenu";
799 public class ModulesNode extends ProjectsGroupNode {
800 public ModulesNode(ProjectNode parent) {
801 super(parent);
802 setIcons(MavenIcons.CLOSED_MODULES_ICON, MavenIcons.OPEN_MODULES_ICON);
805 @Override
806 public String getName() {
807 return message("view.node.modules");
811 public abstract class GoalsGroupNode extends GroupNode {
812 protected final List<GoalNode> myGoalNodes = new ArrayList<GoalNode>();
814 public GoalsGroupNode(MavenSimpleNode parent) {
815 super(parent);
818 protected List<? extends MavenSimpleNode> doGetChildren() {
819 return myGoalNodes;
823 public abstract class GoalNode extends MavenSimpleNode {
824 private final MavenProject myMavenProject;
825 private final String myGoal;
826 private final String myDisplayName;
828 public GoalNode(GoalsGroupNode parent, String goal, String displayName) {
829 super(parent);
830 myMavenProject = findParent(ProjectNode.class).getMavenProject();
831 myGoal = goal;
832 myDisplayName = displayName;
833 setUniformIcon(MavenIcons.PHASE_ICON);
836 public String getProjectPath() {
837 return myMavenProject.getPath();
840 public String getGoal() {
841 return myGoal;
844 @Override
845 public String getName() {
846 return myDisplayName;
849 @Override
850 protected void doUpdate() {
851 String hint = StringUtil.join(Arrays.asList(myShortcutsManager.getDescription(myMavenProject, myGoal),
852 myTasksManager.getDescription(myMavenProject, myGoal)), ", ");
853 setNameAndTooltip(getName(), null, hint);
856 @Override
857 protected SimpleTextAttributes getPlainAttributes() {
858 if (myGoal.equals(myMavenProject.getDefaultGoal())) {
859 return new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, getColor());
861 return super.getPlainAttributes();
864 @Nullable
865 @NonNls
866 protected String getActionId() {
867 return "Maven.RunBuild";
870 @Nullable
871 @NonNls
872 protected String getMenuId() {
873 return "Maven.BuildMenu";
877 public class LifecycleNode extends GoalsGroupNode {
878 public LifecycleNode(ProjectNode parent) {
879 super(parent);
881 for (String goal : PHASES) {
882 myGoalNodes.add(new StandardGoalNode(this, goal));
884 setIcons(MavenIcons.CLOSED_PHASES_ICON, MavenIcons.OPEN_PHASES_ICON);
887 @Override
888 public String getName() {
889 return message("view.node.lifecycle");
892 public void updateGoalsList() {
893 childrenChanged();
897 public class StandardGoalNode extends GoalNode {
898 public StandardGoalNode(GoalsGroupNode parent, String goal) {
899 super(parent, goal, goal);
902 @Override
903 public boolean isVisible() {
904 if (showOnlyBasicPhases() && !BASIC_PHASES.contains(getGoal())) return false;
905 return super.isVisible();
909 public class PluginsNode extends GroupNode {
910 private final List<PluginNode> myPluginNodes = new ArrayList<PluginNode>();
912 public PluginsNode(ProjectNode parent) {
913 super(parent);
914 setIcons(MavenIcons.CLOSED_PLUGINS_ICON, MavenIcons.OPEN_PLUGINS_ICON);
917 @Override
918 public String getName() {
919 return message("view.node.plugins");
922 protected List<? extends MavenSimpleNode> doGetChildren() {
923 return myPluginNodes;
926 public void updatePlugins(MavenProject mavenProject) {
927 List<MavenPlugin> plugins = mavenProject.getDeclaredPlugins();
929 for (PluginNode each : new ArrayList<PluginNode>(myPluginNodes)) {
930 if (plugins.contains(each.getPlugin())) {
931 each.updatePlugin();
933 else {
934 myPluginNodes.remove(each);
937 for (MavenPlugin each : plugins) {
938 if (!hasNodeFor(each)) {
939 myPluginNodes.add(new PluginNode(this, each));
942 sort(myPluginNodes);
943 childrenChanged();
946 private boolean hasNodeFor(MavenPlugin plugin) {
947 for (PluginNode each : myPluginNodes) {
948 if (each.getPlugin().getMavenId().equals(plugin.getMavenId())) {
949 return true;
952 return false;
956 public class PluginNode extends GoalsGroupNode {
957 private final MavenPlugin myPlugin;
958 private MavenPluginInfo myPluginInfo;
960 public PluginNode(PluginsNode parent, MavenPlugin plugin) {
961 super(parent);
962 myPlugin = plugin;
964 setUniformIcon(MavenIcons.PLUGIN_ICON);
965 updatePlugin();
968 public MavenPlugin getPlugin() {
969 return myPlugin;
972 @Override
973 public String getName() {
974 return myPluginInfo == null ? myPlugin.getDisplayString() : myPluginInfo.getGoalPrefix();
977 @Override
978 protected void doUpdate() {
979 setNameAndTooltip(getName(), null, myPluginInfo != null ? myPlugin.getDisplayString() : null);
982 public void updatePlugin() {
983 boolean hadPluginInfo = myPluginInfo != null;
985 myPluginInfo = MavenArtifactUtil.readPluginInfo(myProjectsManager.getLocalRepository(), myPlugin.getMavenId());
987 boolean hasPluginInfo = myPluginInfo != null;
989 setErrorLevel(myPluginInfo == null ? ErrorLevel.ERROR : ErrorLevel.NONE);
991 if (hadPluginInfo == hasPluginInfo) return;
993 myGoalNodes.clear();
994 if (myPluginInfo != null) {
995 for (MavenPluginInfo.Mojo mojo : myPluginInfo.getMojos()) {
996 myGoalNodes.add(new PluginGoalNode(this, mojo.getQualifiedGoal(), mojo.getDisplayName()));
1000 updateFrom(this);
1001 childrenChanged();
1004 @Override
1005 public boolean isVisible() {
1006 // show regardless absence of children
1007 return super.isVisible() || getDisplayKind() != DisplayKind.NEVER;
1011 public class PluginGoalNode extends GoalNode {
1012 public PluginGoalNode(PluginNode parent, String goal, String displayName) {
1013 super(parent, goal, displayName);
1014 setUniformIcon(MavenIcons.PLUGIN_GOAL_ICON);
1018 public abstract class BaseDependenciesNode extends GroupNode {
1019 private List<DependencyNode> myChildren = new ArrayList<DependencyNode>();
1021 protected BaseDependenciesNode(MavenSimpleNode parent) {
1022 super(parent);
1025 @Override
1026 protected List<? extends MavenSimpleNode> doGetChildren() {
1027 return myChildren;
1030 protected void updateChildren(List<MavenArtifactNode> children, MavenProject mavenProject) {
1031 List<DependencyNode> newNodes = new ArrayList<DependencyNode>(children.size());
1032 for (MavenArtifactNode each : children) {
1033 DependencyNode newNode = findOrCreateNodeFor(each, mavenProject);
1034 newNodes.add(newNode);
1035 newNode.updateChildren(each.getDependencies(), mavenProject);
1036 newNode.updateDependency();
1038 myChildren = newNodes;
1039 childrenChanged();
1042 private DependencyNode findOrCreateNodeFor(MavenArtifactNode artifact, MavenProject mavenProject) {
1043 for (DependencyNode each : myChildren) {
1044 if (each.myArtifact.equals(artifact.getArtifact())) return each;
1046 return new DependencyNode(this, artifact, mavenProject);
1050 public class DependenciesNode extends BaseDependenciesNode {
1051 public DependenciesNode(ProjectNode parent) {
1052 super(parent);
1053 setIcons(MavenIcons.CLOSED_DEPENDENCIES_ICON, MavenIcons.OPEN_DEPENDENCIES_ICON);
1056 @Override
1057 public String getName() {
1058 return message("view.node.dependencies");
1061 public void updateDependencies(MavenProject mavenProject) {
1062 updateChildren(mavenProject.getDependenciesNodes(), mavenProject);
1066 public class DependencyNode extends BaseDependenciesNode {
1067 private final MavenArtifact myArtifact;
1068 private final MavenProject myMavenProject;
1070 public DependencyNode(MavenSimpleNode parent, MavenArtifactNode artifactNode, MavenProject mavenProject) {
1071 super(parent);
1072 myMavenProject = mavenProject;
1073 myArtifact = artifactNode.getArtifact();
1074 setUniformIcon(MavenIcons.DEPENDENCY_ICON);
1077 @Override
1078 public String getName() {
1079 return myArtifact.getDisplayStringForLibraryName();
1082 @Override
1083 protected void doUpdate() {
1084 String scope = myArtifact.getScope();
1085 setNameAndTooltip(getName(), null, MavenConstants.SCOPE_COMPILE.equals(scope) ? null : scope);
1088 private void updateDependency() {
1089 setErrorLevel(myArtifact.isResolved() ? ErrorLevel.NONE : ErrorLevel.ERROR);
1092 @Override
1093 public Navigatable getNavigatable() {
1094 final Module m = myProjectsManager.findModule(myMavenProject);
1095 if (m == null) return null;
1096 final OrderEntry e = MavenRootModelAdapter.findLibraryEntry(m, myArtifact);
1097 if (e == null) return null;
1098 return new Navigatable() {
1099 public void navigate(boolean requestFocus) {
1100 ProjectSettingsService.getInstance(myProject).openProjectLibrarySettings(new NamedLibraryElement(m, e));
1103 public boolean canNavigate() {
1104 return true;
1107 public boolean canNavigateToSource() {
1108 return false;
1113 @Override
1114 public boolean isVisible() {
1115 // show regardless absence of children
1116 return getDisplayKind() != DisplayKind.NEVER;