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
.dom
;
18 import com
.intellij
.lang
.properties
.psi
.PropertiesFile
;
19 import com
.intellij
.lang
.properties
.psi
.Property
;
20 import com
.intellij
.openapi
.editor
.Editor
;
21 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
22 import com
.intellij
.openapi
.project
.Project
;
23 import com
.intellij
.openapi
.util
.Pair
;
24 import com
.intellij
.openapi
.util
.io
.FileUtil
;
25 import com
.intellij
.openapi
.util
.text
.StringUtil
;
26 import com
.intellij
.openapi
.vfs
.LocalFileSystem
;
27 import com
.intellij
.openapi
.vfs
.VfsUtil
;
28 import com
.intellij
.openapi
.vfs
.VirtualFile
;
29 import com
.intellij
.openapi
.vfs
.VirtualFileSystem
;
30 import com
.intellij
.psi
.PsiElement
;
31 import com
.intellij
.psi
.PsiFile
;
32 import com
.intellij
.psi
.PsiManager
;
33 import com
.intellij
.psi
.util
.PsiTreeUtil
;
34 import com
.intellij
.psi
.search
.GlobalSearchScope
;
35 import com
.intellij
.psi
.xml
.XmlElement
;
36 import com
.intellij
.psi
.xml
.XmlFile
;
37 import com
.intellij
.psi
.xml
.XmlTag
;
38 import com
.intellij
.util
.xml
.*;
39 import com
.intellij
.util
.xml
.reflect
.DomCollectionChildDescription
;
40 import org
.jetbrains
.annotations
.NotNull
;
41 import org
.jetbrains
.annotations
.Nullable
;
42 import org
.jetbrains
.idea
.maven
.dom
.model
.*;
43 import org
.jetbrains
.idea
.maven
.project
.*;
44 import org
.jetbrains
.idea
.maven
.utils
.MavenConstants
;
45 import org
.jetbrains
.idea
.maven
.vfs
.MavenPropertiesVirtualFileSystem
;
48 import java
.util
.List
;
49 import java
.util
.regex
.Matcher
;
50 import java
.util
.regex
.Pattern
;
52 public class MavenDomUtil
{
53 public static boolean isMavenFile(PsiFile file
) {
54 return isProjectFile(file
) || isProfilesFile(file
) || isSettingsFile(file
);
57 public static boolean isProjectFile(PsiFile file
) {
58 if (!(file
instanceof XmlFile
)) return false;
60 String name
= file
.getName();
61 return name
.equals(MavenConstants
.POM_XML
)
62 || name
.endsWith("." + MavenConstants
.POM_EXTENSION
)
63 || name
.equals(MavenConstants
.SUPER_POM_XML
);
66 public static boolean isProfilesFile(PsiFile file
) {
67 if (!(file
instanceof XmlFile
)) return false;
69 String name
= file
.getName();
70 return name
.equals(MavenConstants
.PROFILES_XML
);
73 public static boolean isSettingsFile(PsiFile file
) {
74 if (!(file
instanceof XmlFile
)) return false;
76 String name
= file
.getName();
77 return name
.equals(MavenConstants
.SETTINGS_XML
);
80 public static boolean isMavenFile(PsiElement element
) {
81 return isMavenFile(element
.getContainingFile());
84 public static boolean isMavenProperty(PsiElement target
) {
85 XmlTag tag
= PsiTreeUtil
.getParentOfType(target
, XmlTag
.class, false);
86 if (tag
== null) return false;
87 return DomUtil
.findDomElement(tag
, MavenDomProperties
.class) != null;
90 public static String
calcRelativePath(VirtualFile parent
, VirtualFile child
) {
91 String result
= FileUtil
.getRelativePath(new File(parent
.getPath()),
92 new File(child
.getPath()));
93 return FileUtil
.toSystemIndependentName(result
);
96 public static MavenDomParent
updateMavenParent(MavenDomProjectModel mavenModel
, MavenProject parentProject
) {
97 MavenDomParent result
= mavenModel
.getMavenParent();
99 VirtualFile pomFile
= DomUtil
.getFile(mavenModel
).getVirtualFile();
100 Project project
= mavenModel
.getXmlElement().getProject();
102 MavenId parentId
= parentProject
.getMavenId();
103 result
.getGroupId().setStringValue(parentId
.getGroupId());
104 result
.getArtifactId().setStringValue(parentId
.getArtifactId());
105 result
.getVersion().setStringValue(parentId
.getVersion());
107 if (pomFile
.getParent().getParent() != parentProject
.getDirectoryFile()) {
108 result
.getRelativePath().setValue(PsiManager
.getInstance(project
).findFile(parentProject
.getFile()));
114 public static <T
> T
getImmediateParent(ConvertContext context
, Class
<T
> clazz
) {
115 DomElement parentElement
= context
.getInvocationElement().getParent();
116 return clazz
.isInstance(parentElement
) ?
(T
)parentElement
: null;
120 public static VirtualFile
getVirtualFile(@NotNull DomElement element
) {
121 PsiFile psiFile
= DomUtil
.getFile(element
);
122 return getVirtualFile(psiFile
);
126 public static VirtualFile
getVirtualFile(@NotNull PsiElement element
) {
127 PsiFile psiFile
= element
.getContainingFile();
128 return getVirtualFile(psiFile
);
132 private static VirtualFile
getVirtualFile(PsiFile psiFile
) {
133 if (psiFile
== null) return null;
134 psiFile
= psiFile
.getOriginalFile();
135 return psiFile
.getVirtualFile();
139 public static MavenProject
findProject(@NotNull MavenDomProjectModel projectDom
) {
140 XmlElement element
= projectDom
.getXmlElement();
141 if (element
== null) return null;
143 VirtualFile file
= getVirtualFile(element
);
144 if (file
== null) return null;
145 MavenProjectsManager manager
= MavenProjectsManager
.getInstance(element
.getProject());
146 return manager
.findProject(file
);
150 public static MavenProject
findContainingProject(@NotNull PsiElement element
) {
151 VirtualFile file
= getVirtualFile(element
);
152 if (file
== null) return null;
153 MavenProjectsManager manager
= MavenProjectsManager
.getInstance(element
.getProject());
154 return manager
.findContainingProject(file
);
158 public static MavenDomProjectModel
getMavenDomProjectModel(@NotNull Project project
, @NotNull VirtualFile file
) {
159 return getMavenDomModel(project
, file
, MavenDomProjectModel
.class);
163 public static MavenDomProfiles
getMavenDomProfilesModel(@NotNull Project project
, @NotNull VirtualFile file
) {
164 MavenDomProfilesModel model
= getMavenDomModel(project
, file
, MavenDomProfilesModel
.class);
165 if (model
!= null) return model
.getProfiles();
166 return getMavenDomModel(project
, file
, MavenDomProfiles
.class); // try old-style model
170 public static <T
extends MavenDomElement
> T
getMavenDomModel(@NotNull Project project
,
171 @NotNull VirtualFile file
,
172 @NotNull Class
<T
> clazz
) {
173 PsiFile psiFile
= PsiManager
.getInstance(project
).findFile(file
);
174 if (psiFile
== null) return null;
175 return getMavenDomModel(psiFile
, clazz
);
179 public static <T
extends MavenDomElement
> T
getMavenDomModel(@NotNull PsiFile file
, @NotNull Class
<T
> clazz
) {
180 DomFileElement
<T
> fileElement
= getMavenDomFile(file
, clazz
);
181 return fileElement
== null ?
null : fileElement
.getRootElement();
185 private static <T
extends MavenDomElement
> DomFileElement
<T
> getMavenDomFile(@NotNull PsiFile file
, @NotNull Class
<T
> clazz
) {
186 if (!(file
instanceof XmlFile
)) return null;
187 return DomManager
.getDomManager(file
.getProject()).getFileElement((XmlFile
)file
, clazz
);
191 public static XmlTag
findTag(@NotNull DomElement domElement
, @NotNull String path
) {
192 List
<String
> elements
= StringUtil
.split(path
, ".");
193 if (elements
.isEmpty()) return null;
195 Pair
<String
, Integer
> nameAndIndex
= translateTagName(elements
.get(0));
196 String name
= nameAndIndex
.first
;
197 Integer index
= nameAndIndex
.second
;
199 XmlTag result
= domElement
.getXmlTag();
200 if (result
== null || !name
.equals(result
.getName())) return null;
201 result
= getIndexedTag(result
, index
);
203 for (String each
: elements
.subList(1, elements
.size())) {
204 nameAndIndex
= translateTagName(each
);
205 name
= nameAndIndex
.first
;
206 index
= nameAndIndex
.second
;
208 result
= result
.findFirstSubTag(name
);
209 if (result
== null) return null;
210 result
= getIndexedTag(result
, index
);
215 private static final Pattern XML_TAG_NAME_PATTERN
= Pattern
.compile("(\\S*)\\[(\\d*)\\]\\z");
217 private static Pair
<String
, Integer
> translateTagName(String text
) {
218 String tagName
= text
.trim();
219 Integer index
= null;
221 Matcher matcher
= XML_TAG_NAME_PATTERN
.matcher(tagName
);
222 if (matcher
.find()) {
223 tagName
= matcher
.group(1);
225 index
= Integer
.parseInt(matcher
.group(2));
227 catch (NumberFormatException e
) {
232 return Pair
.create(tagName
, index
);
235 private static XmlTag
getIndexedTag(XmlTag parent
, Integer index
) {
236 if (index
== null) return parent
;
238 XmlTag
[] children
= parent
.getSubTags();
239 if (index
< 0 || index
>= children
.length
) return null;
240 return children
[index
];
244 public static PropertiesFile
getPropertiesFile(@NotNull Project project
, @NotNull String fileName
) {
245 VirtualFileSystem fs
= MavenPropertiesVirtualFileSystem
.getInstance();
246 VirtualFile file
= fs
.findFileByPath(fileName
);
247 if (file
== null) return null;
248 return getPropertiesFile(project
, file
);
252 public static PropertiesFile
getPropertiesFile(@NotNull Project project
, @NotNull VirtualFile file
) {
253 PsiFile psiFile
= PsiManager
.getInstance(project
).findFile(file
);
254 if (!(psiFile
instanceof PropertiesFile
)) return null;
255 return (PropertiesFile
)psiFile
;
259 public static Property
findProperty(@NotNull Project project
, @NotNull String fileName
, @NotNull String propName
) {
260 PropertiesFile propertiesFile
= getPropertiesFile(project
, fileName
);
261 return propertiesFile
== null ?
null : propertiesFile
.findPropertyByKey(propName
);
265 public static Property
findProperty(@NotNull Project project
, @NotNull VirtualFile file
, @NotNull String propName
) {
266 PropertiesFile propertiesFile
= getPropertiesFile(project
, file
);
267 return propertiesFile
== null ?
null : propertiesFile
.findPropertyByKey(propName
);
271 public static PsiElement
findPropertyValue(@NotNull Project project
, @NotNull VirtualFile file
, @NotNull String propName
) {
272 Property prop
= findProperty(project
, file
, propName
);
273 return prop
== null ?
null : prop
.getFirstChild().getNextSibling().getNextSibling();
276 public static boolean isFiltererResourceFile(PsiElement element
) {
277 MavenProject project
= findContainingProject(element
);
278 if (project
== null) return false;
280 VirtualFile file
= MavenDomUtil
.getVirtualFile(element
);
281 if (file
== null) return false;
283 for (MavenResource each
: project
.getResources()) {
284 VirtualFile resourceDir
= LocalFileSystem
.getInstance().findFileByPath(each
.getDirectory());
285 if (resourceDir
== null) continue;
286 if (!VfsUtil
.isAncestor(resourceDir
, file
, true)) continue;
287 return each
.isFiltered();
292 public static List
<DomFileElement
<MavenDomProjectModel
>> collectProjectModels(Project p
) {
293 return DomService
.getInstance().getFileElements(MavenDomProjectModel
.class, p
, GlobalSearchScope
.projectScope(p
));
296 public static MavenId
describe(PsiFile psiFile
) {
297 MavenDomProjectModel model
= getMavenDomModel(psiFile
, MavenDomProjectModel
.class);
299 String groupId
= model
.getGroupId().getStringValue();
300 String artifactId
= model
.getArtifactId().getStringValue();
301 String version
= model
.getVersion().getStringValue();
303 if (groupId
== null) {
304 groupId
= model
.getMavenParent().getGroupId().getStringValue();
307 if (version
== null) {
308 version
= model
.getMavenParent().getVersion().getStringValue();
311 return new MavenId(groupId
, artifactId
, version
);
316 public static MavenDomDependency
createDomDependency(MavenDomProjectModel model
, MavenArtifact mavenArtifact
, Editor editor
) {
317 MavenDomDependency domDependency
= createMavenDomDependency(model
, editor
);
319 domDependency
.getGroupId().setStringValue(mavenArtifact
.getGroupId());
320 domDependency
.getArtifactId().setStringValue(mavenArtifact
.getArtifactId());
321 domDependency
.getVersion().setStringValue(mavenArtifact
.getVersion());
323 return domDependency
;
327 private static MavenDomDependency
createMavenDomDependency(@NotNull MavenDomProjectModel model
, @Nullable Editor editor
) {
328 MavenDomDependencies dependencies
= model
.getDependencies();
330 int index
= getCollectionIndex(dependencies
, editor
);
332 DomCollectionChildDescription childDescription
= dependencies
.getGenericInfo().getCollectionChildDescription("dependency");
333 if (childDescription
!= null) {
334 DomElement element
= childDescription
.addValue(dependencies
, index
);
335 if (element
instanceof MavenDomDependency
) {
336 return (MavenDomDependency
)element
;
341 return dependencies
.addDependency();
345 public static int getCollectionIndex(@NotNull final MavenDomDependencies dependencies
, @Nullable final Editor editor
) {
346 if (editor
!= null) {
347 int offset
= editor
.getCaretModel().getOffset();
349 List
<MavenDomDependency
> dependencyList
= dependencies
.getDependencies();
351 for (int i
= 0; i
< dependencyList
.size(); i
++) {
352 MavenDomDependency dependency
= dependencyList
.get(i
);
353 XmlElement xmlElement
= dependency
.getXmlElement();
355 if (xmlElement
!= null && xmlElement
.getTextRange().getStartOffset() >= offset
) {