maven dependency management gutter support (override icons)
authorsergey.vasiliev <sergey.vasiliev@jetbrains.com>
Fri, 12 Feb 2010 12:21:36 +0000 (12 15:21 +0300)
committersergey.vasiliev <sergey.vasiliev@jetbrains.com>
Fri, 12 Feb 2010 12:23:02 +0000 (12 15:23 +0300)
12 files changed:
plugins/maven/maven.iml
plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java [new file with mode: 0644]
plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomGutterAnnotator.java [new file with mode: 0644]
plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/MavenCodeInsightGenerateAction.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenIcons.java
plugins/maven/src/main/resources/DomBundle.properties
plugins/maven/src/main/resources/META-INF/plugin.xml
plugins/maven/src/main/resources/images/overridenDependency.png [new file with mode: 0644]
plugins/maven/src/main/resources/images/overridingDependency.png [new file with mode: 0644]

index 8889960..c23db08 100644 (file)
     <orderEntry type="library" exported="" scope="TEST" name="JUnit4" level="project" />
     <orderEntry type="module" module-name="testFramework-java" exported="" scope="TEST" />
     <orderEntry type="module" module-name="jetgroovy" scope="TEST" />
+    <orderEntry type="module" module-name="jam-support-openapi" />
   </component>
   <component name="copyright">
     <Base>
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
new file mode 100644 (file)
index 0000000..1330d20
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed 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.jetbrains.idea.maven.dom;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.Function;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.hash.HashSet;
+import com.intellij.util.xml.DomUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.dom.MavenDomUtil;
+import org.jetbrains.idea.maven.dom.model.*;
+import org.jetbrains.idea.maven.project.*;
+import org.jetbrains.idea.maven.utils.MavenUtil;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+public class MavenDomProjectProcessorUtils {
+  private MavenDomProjectProcessorUtils() {
+  }
+
+  @Nullable
+  public static XmlTag searchProperty(@NotNull final String propertyName,
+                                      @NotNull MavenDomProjectModel projectDom,
+                                      @NotNull final Project project) {
+    final XmlTag[] property = new XmlTag[]{null};
+
+    Processor<MavenDomProperties> searchProcessor = new Processor<MavenDomProperties>() {
+      public boolean process(MavenDomProperties mavenDomProperties) {
+        XmlTag propertiesTag = mavenDomProperties.getXmlTag();
+        if (propertiesTag != null) {
+          for (XmlTag each : propertiesTag.getSubTags()) {
+            if (each.getName().equals(propertyName)) {
+              property[0] = each;
+              return true;
+            }
+          }
+        }
+        return false;
+      }
+    };
+
+    processProperties(projectDom, searchProcessor, project);
+
+    return property[0];
+  }
+
+  @Nullable
+  public static Set<XmlTag> collectProperties(@NotNull MavenDomProjectModel projectDom, @NotNull final Project project) {
+    final Set<XmlTag> properties = new HashSet<XmlTag>();
+
+    Processor<MavenDomProperties> collectProcessor = new Processor<MavenDomProperties>() {
+      public boolean process(MavenDomProperties mavenDomProperties) {
+        XmlTag propertiesTag = mavenDomProperties.getXmlTag();
+        if (propertiesTag != null) {
+          properties.addAll(Arrays.asList(propertiesTag.getSubTags()));
+        }
+        return false;
+      }
+    };
+
+    processProperties(projectDom, collectProcessor, project);
+
+    return properties;
+  }
+
+  @NotNull
+  public static Set<MavenDomDependency> searchDependencyUsages(@NotNull final MavenDomDependency dependency,
+                                                               @NotNull final Project project) {
+    final Set<MavenDomDependency> usages = new HashSet<MavenDomDependency>();
+
+    MavenDomProjectModel model = dependency.getParentOfType(MavenDomProjectModel.class, false);
+    if (model != null) {
+      final String artifactId = dependency.getArtifactId().getStringValue();
+      final String groupId = dependency.getGroupId().getStringValue();
+      if (artifactId != null && groupId != null) {
+        Processor<MavenDomProjectModel> collectProcessor = new Processor<MavenDomProjectModel>() {
+          public boolean process(MavenDomProjectModel mavenDomProjectModel) {
+            for (MavenDomDependency domDependency : mavenDomProjectModel.getDependencies().getDependencies()) {
+              if (domDependency.equals(dependency)) continue;
+              if (artifactId.equals(domDependency.getArtifactId().getStringValue()) &&
+                  groupId.equals(domDependency.getGroupId().getStringValue())) {
+                usages.add(domDependency);
+              }
+            }
+            return false;
+          }
+        };
+
+        processProjectDependenciesRecursively(model, collectProcessor, project);
+      }
+    }
+
+    return usages;
+  }
+
+  private static void processProjectDependenciesRecursively(@Nullable MavenDomProjectModel model,
+                                                            @NotNull Processor<MavenDomProjectModel> processor,
+                                                            @NotNull Project project) {
+    if (model != null) {
+      if (processor.process(model)) return;
+
+      MavenProject mavenProject = MavenDomUtil.findProject(model);
+      if (mavenProject != null) {
+        for (MavenProject childProject : MavenProjectsManager.getInstance(project).findInheritors(mavenProject)) {
+          MavenDomProjectModel childProjectModel = MavenDomUtil.getMavenDomProjectModel(project, childProject.getFile());
+
+          processProjectDependenciesRecursively(childProjectModel, processor, project);
+        }
+      }
+    }
+  }
+
+  @Nullable
+  public static MavenDomDependency searchManagingDependency(@NotNull final MavenDomDependency dependency, @NotNull final Project project) {
+    final MavenDomDependency[] parent = new MavenDomDependency[]{null};
+
+    final String artifactId = dependency.getArtifactId().getStringValue();
+    final String groupId = dependency.getGroupId().getStringValue();
+    if (artifactId != null && groupId != null) {
+      MavenDomProjectModel model = dependency.getParentOfType(MavenDomProjectModel.class, false);
+      if (model != null) {
+        Processor<MavenDomDependencies> processor = new Processor<MavenDomDependencies>() {
+          public boolean process(MavenDomDependencies mavenDomDependencies) {
+            for (MavenDomDependency domDependency : mavenDomDependencies.getDependencies()) {
+              if (domDependency.equals(dependency)) continue;
+              if (artifactId.equals(domDependency.getArtifactId().getStringValue()) &&
+                  groupId.equals(domDependency.getGroupId().getStringValue())) {
+                parent[0] = domDependency;
+                return true;
+              }
+            }
+            return false;
+          }
+        };
+        processDependenciesInDependencyManagement(model, processor, project);
+      }
+    }
+
+    return parent[0];
+  }
+
+
+  public static boolean processDependenciesInDependencyManagement(@NotNull MavenDomProjectModel projectDom,
+                                                                  @NotNull final Processor<MavenDomDependencies> processor,
+                                                                  @NotNull final Project project) {
+
+    Function<MavenDomProfile, MavenDomDependencies> domProfileFunction = new Function<MavenDomProfile, MavenDomDependencies>() {
+      public MavenDomDependencies fun(MavenDomProfile mavenDomProfile) {
+        return mavenDomProfile.getDependencyManagement().getDependencies();
+      }
+    };
+    Function<MavenDomProjectModel, MavenDomDependencies> projectDomFunction = new Function<MavenDomProjectModel, MavenDomDependencies>() {
+      public MavenDomDependencies fun(MavenDomProjectModel mavenDomProjectModel) {
+        return mavenDomProjectModel.getDependencyManagement().getDependencies();
+      }
+    };
+
+    return process(projectDom, processor, project, domProfileFunction, projectDomFunction);
+  }
+
+  public static boolean processProperties(@NotNull MavenDomProjectModel projectDom,
+                                          @NotNull final Processor<MavenDomProperties> processor,
+                                          @NotNull final Project project) {
+
+    Function<MavenDomProfile, MavenDomProperties> domProfileFunction = new Function<MavenDomProfile, MavenDomProperties>() {
+      public MavenDomProperties fun(MavenDomProfile mavenDomProfile) {
+        return mavenDomProfile.getProperties();
+      }
+    };
+    Function<MavenDomProjectModel, MavenDomProperties> projectDomFunction = new Function<MavenDomProjectModel, MavenDomProperties>() {
+      public MavenDomProperties fun(MavenDomProjectModel mavenDomProjectModel) {
+        return mavenDomProjectModel.getProperties();
+      }
+    };
+
+    return process(projectDom, processor, project, domProfileFunction, projectDomFunction);
+  }
+
+  public static <T> boolean process(@NotNull MavenDomProjectModel projectDom,
+                                    @NotNull final Processor<T> processor,
+                                    @NotNull final Project project,
+                                    @NotNull final Function<MavenDomProfile, T> domProfileFunction,
+                                    @NotNull final Function<MavenDomProjectModel, T> projectDomFunction) {
+
+    MavenProject mavenProjectOrNull = MavenDomUtil.findProject(projectDom);
+
+    if (processSettingsXml(mavenProjectOrNull, processor, project, domProfileFunction)) return true;
+    if (processProject(projectDom, mavenProjectOrNull, processor, project, domProfileFunction, projectDomFunction)) return true;
+
+    return processParentProjectFile(projectDom, processor, project, domProfileFunction, projectDomFunction);
+  }
+
+  private static <T> boolean processParentProjectFile(MavenDomProjectModel projectDom,
+                                                      final Processor<T> processor,
+                                                      final Project project,
+                                                      final Function<MavenDomProfile, T> domProfileFunction,
+                                                      final Function<MavenDomProjectModel, T> projectDomFunction) {
+    Boolean aBoolean = new MyMavenParentProjectFileProcessor<Boolean>(project) {
+      protected Boolean doProcessParent(VirtualFile parentFile) {
+        MavenDomProjectModel parentProjectDom = MavenDomUtil.getMavenDomProjectModel(project, parentFile);
+        if (parentProjectDom == null) return false;
+        MavenProject parentMavenProject = MavenDomUtil.findProject(parentProjectDom);
+
+        return processProject(parentProjectDom, parentMavenProject, processor, project, domProfileFunction, projectDomFunction);
+      }
+    }.process(projectDom);
+
+    return aBoolean == null ? false : aBoolean.booleanValue();
+  }
+
+  private static <T> boolean processSettingsXml(@Nullable MavenProject mavenProject,
+                                                @NotNull Processor<T> processor,
+                                                @NotNull Project project,
+                                                Function<MavenDomProfile, T> domProfileFunction) {
+    MavenGeneralSettings settings = MavenProjectsManager.getInstance(project).getGeneralSettings();
+
+    for (VirtualFile each : settings.getEffectiveSettingsFiles()) {
+      MavenDomSettingsModel settingsDom = MavenDomUtil.getMavenDomModel(project, each, MavenDomSettingsModel.class);
+      if (settingsDom == null) continue;
+
+      if (processProfiles(settingsDom.getProfiles(), mavenProject, processor, domProfileFunction)) return true;
+    }
+    return false;
+  }
+
+  private static <T> boolean processProject(MavenDomProjectModel projectDom,
+                                            MavenProject mavenProjectOrNull,
+                                            Processor<T> processor,
+                                            Project project,
+                                            Function<MavenDomProfile, T> domProfileFunction,
+                                            Function<MavenDomProjectModel, T> projectDomFunction) {
+
+    if (processProfilesXml(MavenDomUtil.getVirtualFile(projectDom), mavenProjectOrNull, processor, project, domProfileFunction)) {
+      return true;
+    }
+
+    if (processProfiles(projectDom.getProfiles(), mavenProjectOrNull, processor, domProfileFunction)) return true;
+
+    T t = projectDomFunction.fun(projectDom);
+    return t == null ? false : processor.process(t);
+  }
+
+  private static <T> boolean processProfilesXml(VirtualFile projectFile,
+                                                MavenProject mavenProjectOrNull,
+                                                Processor<T> processor,
+                                                Project project,
+                                                Function<MavenDomProfile, T> f) {
+    VirtualFile profilesFile = MavenUtil.findProfilesXmlFile(projectFile);
+    if (profilesFile == null) return false;
+
+    MavenDomProfiles profiles = MavenDomUtil.getMavenDomProfilesModel(project, profilesFile);
+    if (profiles == null) return false;
+
+    return processProfiles(profiles, mavenProjectOrNull, processor, f);
+  }
+
+  private static <T> boolean processProfiles(MavenDomProfiles profilesDom,
+                                             MavenProject mavenProjectOrNull,
+                                             Processor<T> processor,
+                                             Function<MavenDomProfile, T> f) {
+    Collection<String> activePropfiles = mavenProjectOrNull == null ? null : mavenProjectOrNull.getActiveProfilesIds();
+    for (MavenDomProfile each : profilesDom.getProfiles()) {
+      XmlTag idTag = each.getId().getXmlTag();
+      if (idTag == null) continue;
+      if (activePropfiles != null && !activePropfiles.contains(idTag.getValue().getText())) continue;
+
+      T t = f.fun(each);
+      if (t != null && processor.process(t)) return true;
+    }
+    return false;
+  }
+
+  private abstract static class MyMavenParentProjectFileProcessor<T> extends MavenParentProjectFileProcessor<Boolean> {
+    private final Project myProject;
+
+    public MyMavenParentProjectFileProcessor(Project project) {
+      myProject = project;
+    }
+
+    protected VirtualFile findManagedFile(@NotNull MavenId id) {
+      MavenProject project = MavenProjectsManager.getInstance(myProject).findProject(id);
+      return project == null ? null : project.getFile();
+    }
+
+    @Nullable
+    public Boolean process(@NotNull MavenDomProjectModel projectDom) {
+      MavenDomParent parent = projectDom.getMavenParent();
+      MavenParentDesc parentDesc = null;
+      if (DomUtil.hasXml(parent)) {
+        String parentGroupId = parent.getGroupId().getStringValue();
+        String parentArtifactId = parent.getArtifactId().getStringValue();
+        String parentVersion = parent.getVersion().getStringValue();
+        String parentRelativePath = parent.getRelativePath().getStringValue();
+        if (StringUtil.isEmptyOrSpaces(parentRelativePath)) parentRelativePath = "../pom.xml";
+        MavenId parentId = new MavenId(parentGroupId, parentArtifactId, parentVersion);
+        parentDesc = new MavenParentDesc(parentId, parentRelativePath);
+      }
+
+      return process(MavenProjectsManager.getInstance(myProject).getGeneralSettings(), MavenDomUtil.getVirtualFile(projectDom), parentDesc);
+    }
+  }
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomGutterAnnotator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomGutterAnnotator.java
new file mode 100644 (file)
index 0000000..120bcbb
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed 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.jetbrains.idea.maven.dom.annotator;
+
+import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
+import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.Annotator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.NotNullFunction;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.DomManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.dom.MavenDomBundle;
+import org.jetbrains.idea.maven.dom.MavenDomProjectProcessorUtils;
+import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
+import org.jetbrains.idea.maven.dom.model.MavenDomDependencyManagement;
+import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
+import org.jetbrains.idea.maven.utils.MavenIcons;
+
+import javax.swing.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public class MavenDomGutterAnnotator implements Annotator {
+
+  private static final PsiElementListCellRenderer<XmlTag> RENDERER = new PsiElementListCellRenderer<XmlTag>() {
+    @Override
+    public String getElementText(XmlTag tag) {
+      DomElement domElement = DomManager.getDomManager(tag.getProject()).getDomElement(tag);
+      if (domElement != null) {
+        MavenDomProjectModel model = domElement.getParentOfType(MavenDomProjectModel.class, false);
+        if (model != null) {
+          String name = model.getName().getStringValue();
+          if (!StringUtil.isEmptyOrSpaces(name)) {
+               return name;
+          }
+        }
+      }
+
+      return tag.getContainingFile().getName();
+    }
+
+    @Override
+    protected String getContainerText(XmlTag element, String name) {
+      return null;
+    }
+
+    @Override
+    protected Icon getIcon(PsiElement element) {
+      return MavenIcons.MAVEN_PROJECT_ICON;
+    }
+
+    @Override
+    protected int getIconFlags() {
+      return 0;
+    }
+  };
+
+  private static final NotNullFunction<MavenDomDependency, Collection<? extends PsiElement>> CONVERTER =
+    new NotNullFunction<MavenDomDependency, Collection<? extends PsiElement>>() {
+
+      @NotNull
+      public Collection<? extends PsiElement> fun(final MavenDomDependency pointer) {
+        return ContainerUtil.createMaybeSingletonList(pointer.getXmlTag());
+      }
+    };
+
+  private static void annotateDependencyUsages(@NotNull MavenDomDependency dependency, AnnotationHolder holder) {
+    final XmlTag tag = dependency.getXmlTag();
+    if (tag == null) return;
+
+    final Set<MavenDomDependency> children = getDependencyUsages(dependency);
+    if (children.size() > 0) {
+      final NavigationGutterIconBuilder<MavenDomDependency> iconBuilder =
+        NavigationGutterIconBuilder.create(MavenIcons.OVERRIDEN_DEPENDENCY, CONVERTER);
+      iconBuilder.
+        setTargets(children).
+        setPopupTitle(MavenDomBundle.message("navigate.parent.dependency.title")).
+        setCellRenderer(RENDERER).
+        setTooltipText(MavenDomBundle.message("overriding.dependency.title")).
+        install(holder, dependency.getXmlTag());
+    }
+  }
+
+
+
+  private static void annotateManagedDependency(MavenDomDependency dependency, AnnotationHolder holder) {
+    final XmlTag tag = dependency.getXmlTag();
+    if (tag == null) return;
+
+    final List<MavenDomDependency> children = getManagingDependencies(dependency);
+    if (children.size() > 0) {
+
+      final NavigationGutterIconBuilder<MavenDomDependency> iconBuilder =
+        NavigationGutterIconBuilder.create(MavenIcons.OVERRIDING_DEPENDENCY, CONVERTER);
+      iconBuilder.
+        setTargets(children).
+        setTooltipText(MavenDomBundle.message("overriden.dependency.title")).
+        install(holder, dependency.getXmlTag());
+    }
+  }
+
+  private static List<MavenDomDependency> getManagingDependencies(@NotNull MavenDomDependency dependency) {
+    Project project = dependency.getManager().getProject();
+    MavenDomDependency parentDependency = MavenDomProjectProcessorUtils.searchManagingDependency(dependency, project);
+
+    if (parentDependency != null) {
+      return Collections.singletonList(parentDependency);
+    }
+    return Collections.emptyList();
+  }
+
+  @NotNull
+  private static Set<MavenDomDependency> getDependencyUsages(@NotNull MavenDomDependency dependency) {
+    return MavenDomProjectProcessorUtils.searchDependencyUsages(dependency, dependency.getManager().getProject());
+  }
+
+  public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
+    if (psiElement instanceof XmlTag) {
+      final DomElement element = DomManager.getDomManager(psiElement.getProject()).getDomElement((XmlTag)psiElement);
+      if (element instanceof MavenDomDependency) {
+        MavenDomDependency dependency = (MavenDomDependency)element;
+        if (isDependencyManagementSection(dependency)) {
+           annotateDependencyUsages(dependency, holder);
+        } else {
+          annotateManagedDependency(dependency, holder);
+        }
+      }
+    }
+  }
+
+  private static boolean isDependencyManagementSection(@NotNull MavenDomDependency dependency) {
+    return dependency.getParentOfType(MavenDomDependencyManagement.class, false) != null;
+  }
+}
\ No newline at end of file
index 26c7aaf..731d627 100644 (file)
@@ -33,7 +33,7 @@ public class MavenCodeInsightGenerateAction extends GenerateDomElementAction {
     super(new MavenGenerateDomElementProvider(description, childElementClass, mappingId, parentFunction));
 
     getTemplatePresentation().setIcon(ElementPresentationManager.getIconForClass(childElementClass));
-  }
+  }                       
 
   public MavenCodeInsightGenerateAction(final GenerateDomElementProvider generateProvider) {
     super(generateProvider);
index 3d5695e..71234c6 100644 (file)
@@ -28,8 +28,10 @@ import com.intellij.psi.xml.XmlDocument;
 import com.intellij.psi.xml.XmlFile;
 import com.intellij.psi.xml.XmlTag;
 import com.intellij.psi.xml.XmlTagChild;
+import com.intellij.util.Function;
 import com.intellij.util.Icons;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.xml.DomElement;
 import com.intellij.util.xml.DomUtil;
 import com.intellij.xml.XmlElementDescriptor;
@@ -37,17 +39,16 @@ import com.intellij.xml.XmlNSDescriptor;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.dom.MavenDomProjectProcessorUtils;
 import org.jetbrains.idea.maven.dom.MavenDomUtil;
 import org.jetbrains.idea.maven.dom.MavenSchemaProvider;
 import org.jetbrains.idea.maven.dom.model.*;
 import org.jetbrains.idea.maven.project.*;
 import org.jetbrains.idea.maven.utils.MavenIcons;
-import org.jetbrains.idea.maven.utils.MavenUtil;
 import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem;
 
 import javax.swing.*;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -100,13 +101,7 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
     PsiElement result = resolveSystemPropety();
     if (result != null) return result;
 
-    result = processProperties(myProjectDom, new PropertyProcessor<PsiElement>() {
-      @Nullable
-      public PsiElement process(@NotNull XmlTag property) {
-        if (property.getName().equals(myText)) return property;
-        return null;
-      }
-    });
+    result = MavenDomProjectProcessorUtils.searchProperty(myText, myProjectDom, myProject);
     if (result != null) return result;
 
     if (myText.startsWith("settings.")) {
@@ -146,94 +141,6 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
   }
 
   @Nullable
-  private <T> T processProperties(@NotNull MavenDomProjectModel projectDom, final PropertyProcessor<T> processor) {
-    T result;
-    MavenProject mavenProjectOrNull = MavenDomUtil.findProject(projectDom);
-
-    result = processSettingsXmlProperties(mavenProjectOrNull, processor);
-    if (result != null) return result;
-
-    result = processProjectProperties(projectDom, mavenProjectOrNull, processor);
-    if (result != null) return result;
-
-    return new MyMavenParentProjectFileProcessor<T>() {
-      protected T doProcessParent(VirtualFile parentFile) {
-        MavenDomProjectModel parentProjectDom = MavenDomUtil.getMavenDomProjectModel(myProject, parentFile);
-        if (parentProjectDom == null) return null;
-        MavenProject parentMavenProject = MavenDomUtil.findProject(parentProjectDom);
-        return processProjectProperties(parentProjectDom, parentMavenProject, processor);
-      }
-    }.process(projectDom);
-  }
-
-  @Nullable
-  private <T> T processSettingsXmlProperties(@Nullable MavenProject mavenProject, PropertyProcessor<T> processor) {
-    MavenGeneralSettings settings = myProjectsManager.getGeneralSettings();
-    T result;
-
-    for (VirtualFile each : settings.getEffectiveSettingsFiles()) {
-      MavenDomSettingsModel settingsDom = MavenDomUtil.getMavenDomModel(myProject, each, MavenDomSettingsModel.class);
-      if (settingsDom == null) continue;
-
-      result = processProfilesProperties(settingsDom.getProfiles(), mavenProject, processor);
-      if (result != null) return result;
-    }
-    return null;
-  }
-
-  @Nullable
-  private <T> T processProjectProperties(MavenDomProjectModel projectDom,
-                                         MavenProject mavenProjectOrNull,
-                                         PropertyProcessor<T> processor) {
-    T result;
-
-    result = processProfilesXmlProperties(MavenDomUtil.getVirtualFile(projectDom), mavenProjectOrNull, processor);
-    if (result != null) return result;
-
-    result = processProfilesProperties(projectDom.getProfiles(), mavenProjectOrNull, processor);
-    if (result != null) return result;
-
-    return processProperties(projectDom.getProperties(), processor);
-  }
-
-  @Nullable
-  private <T> T processProfilesXmlProperties(VirtualFile projectFile, MavenProject mavenProjectOrNull, PropertyProcessor<T> processor) {
-    VirtualFile profilesFile = MavenUtil.findProfilesXmlFile(projectFile);
-    if (profilesFile == null) return null;
-
-    MavenDomProfiles profiles = MavenDomUtil.getMavenDomProfilesModel(myProject, profilesFile);
-    if (profiles == null) return null;
-
-    return processProfilesProperties(profiles, mavenProjectOrNull, processor);
-  }
-
-  @Nullable
-  private <T> T processProfilesProperties(MavenDomProfiles profilesDom, MavenProject mavenProjectOrNull, PropertyProcessor<T> processor) {
-    Collection<String> activePropfiles = mavenProjectOrNull == null ? null : mavenProjectOrNull.getActiveProfilesIds();
-    for (MavenDomProfile each : profilesDom.getProfiles()) {
-      XmlTag idTag = each.getId().getXmlTag();
-      if (idTag == null) continue;
-      if (activePropfiles != null && !activePropfiles.contains(idTag.getValue().getText())) continue;
-
-      T result = processProperties(each.getProperties(), processor);
-      if (result != null) return result;
-    }
-    return null;
-  }
-
-  @Nullable
-  private <T> T processProperties(MavenDomProperties propertiesDom, PropertyProcessor<T> processor) {
-    XmlTag propertiesTag = propertiesDom.getXmlTag();
-    if (propertiesTag != null) {
-      for (XmlTag each : propertiesTag.getSubTags()) {
-        T result = processor.process(each);
-        if (result != null) return result;
-      }
-    }
-    return null;
-  }
-
-  @Nullable
   private PsiElement resolveSettingsModelProperty() {
     if (!schemaHasProperty(MavenSchemaProvider.MAVEN_SETTINGS_SCHEMA_URL, myText)) return null;
 
@@ -332,12 +239,12 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
   }
 
   private void collectPropertiesVariants(final List<Object> result) {
-    processProperties(myProjectDom, new PropertyProcessor<Object>() {
-      public Object process(@NotNull XmlTag property) {
-        result.add(createLookupElement(property, property.getName()));
-        return null;
+    Set<XmlTag> properties = MavenDomProjectProcessorUtils.collectProperties(myProjectDom, myProject);
+    result.addAll(ContainerUtil.map(properties, new Function<XmlTag, LookupElement>() {
+      public LookupElement fun(XmlTag xmlTag) {
+        return createLookupElement(xmlTag, xmlTag.getName());
       }
-    });
+    });
   }
 
   private void collectSystemEnvProperties(String propertiesFileName, String prefix, List<Object> result) {
@@ -376,7 +283,7 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
     return doProcessSchema(descriptors, null, processor, new THashSet<XmlElementDescriptor>());
   }
 
-  private <T> T doProcessSchema(XmlElementDescriptor[] descriptors,
+  private static <T> T doProcessSchema(XmlElementDescriptor[] descriptors,
                                 String prefix,
                                 SchemaProcessor<T> processor,
                                 Set<XmlElementDescriptor> recursionGuard) {
@@ -403,7 +310,7 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
     return null;
   }
 
-  private <T> boolean isCollection(XmlElementDescriptor each) {
+  private static <T> boolean isCollection(XmlElementDescriptor each) {
     XmlTag declaration = (XmlTag)each.getDeclaration();
     if (declaration != null) {
       XmlTag complexType = declaration.findFirstSubTag("xs:complexType");
@@ -419,17 +326,12 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
     return mySoft;
   }
 
-  private interface PropertyProcessor<T> {
-    @Nullable
-    T process(@NotNull XmlTag property);
-  }
-
   private interface SchemaProcessor<T> {
     @Nullable
     T process(@NotNull String property, XmlElementDescriptor descriptor);
   }
 
-  private class CollectingSchemaProcessor implements SchemaProcessor {
+  private static class CollectingSchemaProcessor implements SchemaProcessor {
     private final List<Object> myResult;
 
     public CollectingSchemaProcessor(List<Object> result) {
index aae4399..1a704e7 100644 (file)
@@ -43,6 +43,7 @@ import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.update.Update;
 import gnu.trove.THashMap;
 import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.idea.maven.dom.MavenDomUtil;
@@ -546,6 +547,12 @@ public class MavenProjectsManager extends SimpleProjectComponent implements Pers
     return ProjectRootManager.getInstance(myProject).getFileIndex().getModuleForFile(project.getFile());
   }
 
+  @NotNull
+  public Set<MavenProject> findInheritors(@Nullable MavenProject parent) {
+    if (parent == null || !isInitialized()) return Collections.emptySet();
+    return myProjectsTree.findInheritors(parent);
+  }
+
   public MavenProject findContainingProject(VirtualFile file) {
     if (!isInitialized()) return null;
     Module module = ProjectRootManager.getInstance(myProject).getFileIndex().getModuleForFile(file);
index b73d15a..50f9d6a 100644 (file)
@@ -960,7 +960,7 @@ public class MavenProjectsTree {
     return findProject(project.getParentId());
   }
 
-  private Set<MavenProject> findInheritors(MavenProject project) {
+  public Set<MavenProject> findInheritors(MavenProject project) {
     Set<MavenProject> result = new THashSet<MavenProject>();
     MavenId id = project.getMavenId();
 
index ebb3782..ee7ef71 100644 (file)
@@ -37,4 +37,7 @@ public class MavenIcons {
   public static final Icon DEPENDENCY_ICON = IconLoader.getIcon("/nodes/ppLib.png");
   public static final Icon OPEN_MODULES_ICON = IconLoader.getIcon("/images/modulesOpen.png");
   public static final Icon CLOSED_MODULES_ICON = IconLoader.getIcon("/images/modulesClosed.png");
+  
+  public static final Icon OVERRIDING_DEPENDENCY = IconLoader.getIcon("/images/overridingDependency.png");
+  public static final Icon OVERRIDEN_DEPENDENCY = IconLoader.getIcon("/images/overridenDependency.png");
 }
index 7c13e9f..3a284cc 100644 (file)
@@ -16,3 +16,6 @@ generate.dependency.group=Dependency (group)
 
 generate.plugin.artifact=Plugin (artifact)
 generate.plugin.group=Plugin (group)
+overriden.dependency.title=Navigate to managing dependency 
+overriding.dependency.title=Navigate to dependency usages
+navigate.parent.dependency.title=Choose dependency to navigate
index 4b03ff0..2113cd3 100644 (file)
@@ -88,6 +88,7 @@
     <fileTemplateGroup implementation="org.jetbrains.idea.maven.utils.MavenFileTemplateGroupFactory"/>
 
     <completion.contributor language="XML" implementationClass="org.jetbrains.idea.maven.dom.model.completion.MavenGroupIdSmartCompletionContributor"/>
+    <annotator language="XML" implementationClass="org.jetbrains.idea.maven.dom.annotator.MavenDomGutterAnnotator"/>
   </extensions>
 
   <application-components>
diff --git a/plugins/maven/src/main/resources/images/overridenDependency.png b/plugins/maven/src/main/resources/images/overridenDependency.png
new file mode 100644 (file)
index 0000000..62d6b64
Binary files /dev/null and b/plugins/maven/src/main/resources/images/overridenDependency.png differ
diff --git a/plugins/maven/src/main/resources/images/overridingDependency.png b/plugins/maven/src/main/resources/images/overridingDependency.png
new file mode 100644 (file)
index 0000000..35795fd
Binary files /dev/null and b/plugins/maven/src/main/resources/images/overridingDependency.png differ