2 * Copyright (c) 2005 Your Corporation. All Rights Reserved.
4 package com
.intellij
.util
.xml
;
6 import com
.intellij
.openapi
.editor
.Editor
;
7 import com
.intellij
.openapi
.project
.Project
;
8 import com
.intellij
.psi
.PsiDocumentManager
;
9 import com
.intellij
.psi
.PsiElement
;
10 import com
.intellij
.psi
.PsiFile
;
11 import com
.intellij
.psi
.util
.PsiTreeUtil
;
12 import com
.intellij
.psi
.xml
.XmlAttributeValue
;
13 import com
.intellij
.psi
.xml
.XmlElement
;
14 import com
.intellij
.psi
.xml
.XmlFile
;
15 import com
.intellij
.psi
.xml
.XmlTag
;
16 import com
.intellij
.util
.ReflectionCache
;
17 import com
.intellij
.util
.ReflectionUtil
;
18 import com
.intellij
.util
.xml
.reflect
.DomAttributeChildDescription
;
19 import com
.intellij
.util
.xml
.reflect
.DomCollectionChildDescription
;
20 import com
.intellij
.util
.xml
.reflect
.DomFixedChildDescription
;
21 import com
.intellij
.util
.xml
.reflect
.DomGenericInfo
;
22 import org
.jetbrains
.annotations
.NonNls
;
23 import org
.jetbrains
.annotations
.NotNull
;
24 import org
.jetbrains
.annotations
.Nullable
;
26 import java
.lang
.reflect
.Method
;
27 import java
.lang
.reflect
.Type
;
28 import java
.lang
.reflect
.TypeVariable
;
34 public class DomUtil
{
35 public static final TypeVariable
<Class
<GenericValue
>> GENERIC_VALUE_TYPE_VARIABLE
= ReflectionCache
.getTypeParameters(GenericValue
.class)[0];
40 public static Class
extractParameterClassFromGenericType(Type type
) {
41 return getGenericValueParameter(type
);
44 public static boolean isGenericValueType(Type type
) {
45 return getGenericValueParameter(type
) != null;
49 public static <T
extends DomElement
> T
findByName(@NotNull Collection
<T
> list
, @NonNls @NotNull String name
) {
50 for (T element
: list
) {
51 String elementName
= element
.getGenericInfo().getElementName(element
);
52 if (elementName
!= null && elementName
.equals(name
)) {
60 public static String
[] getElementNames(@NotNull Collection
<?
extends DomElement
> list
) {
61 ArrayList
<String
> result
= new ArrayList
<String
>(list
.size());
62 if (list
.size() > 0) {
63 for (DomElement element
: list
) {
64 String name
= element
.getGenericInfo().getElementName(element
);
70 return result
.toArray(new String
[result
.size()]);
74 public static List
<XmlTag
> getElementTags(@NotNull Collection
<?
extends DomElement
> list
) {
75 ArrayList
<XmlTag
> result
= new ArrayList
<XmlTag
>(list
.size());
76 for (DomElement element
: list
) {
77 XmlTag tag
= element
.getXmlTag();
86 public static XmlTag
[] getElementTags(@NotNull DomElement
[] list
) {
87 XmlTag
[] result
= new XmlTag
[list
.length
];
89 for (DomElement element
: list
) {
90 XmlTag tag
= element
.getXmlTag();
99 public static List
<JavaMethod
> getFixedPath(DomElement element
) {
100 assert element
.isValid();
101 final LinkedList
<JavaMethod
> methods
= new LinkedList
<JavaMethod
>();
103 final DomElement parent
= element
.getParent();
104 if (parent
instanceof DomFileElement
) {
107 final JavaMethod method
= getGetterMethod(element
, parent
);
108 if (method
== null) {
111 methods
.addFirst(method
);
112 element
= element
.getParent();
118 private static JavaMethod
getGetterMethod(final DomElement element
, final DomElement parent
) {
119 final String xmlElementName
= element
.getXmlElementName();
120 final String namespace
= element
.getXmlElementNamespaceKey();
121 final DomGenericInfo genericInfo
= parent
.getGenericInfo();
123 if (element
instanceof GenericAttributeValue
) {
124 final DomAttributeChildDescription description
= genericInfo
.getAttributeChildDescription(xmlElementName
, namespace
);
125 assert description
!= null;
126 return description
.getGetterMethod();
129 final DomFixedChildDescription description
= genericInfo
.getFixedChildDescription(xmlElementName
, namespace
);
130 return description
!= null ? description
.getGetterMethod(description
.getValues(parent
).indexOf(element
)) : null;
133 public static Class
getGenericValueParameter(Type type
) {
134 return ReflectionUtil
.substituteGenericType(GENERIC_VALUE_TYPE_VARIABLE
, type
);
138 public static XmlElement
getValueElement(GenericDomValue domValue
) {
139 if (domValue
instanceof GenericAttributeValue
) {
140 final GenericAttributeValue value
= (GenericAttributeValue
)domValue
;
141 final XmlAttributeValue attributeValue
= value
.getXmlAttributeValue();
142 return attributeValue
== null ? value
.getXmlAttribute() : attributeValue
;
144 return domValue
.getXmlTag();
148 public static List
<?
extends DomElement
> getIdentitySiblings(DomElement element
) {
149 final Method nameValueMethod
= ElementPresentationManager
.findNameValueMethod(element
.getClass());
150 if (nameValueMethod
!= null) {
151 final NameValue nameValue
= DomReflectionUtil
.findAnnotationDFS(nameValueMethod
, NameValue
.class);
152 if (nameValue
== null || nameValue
.unique()) {
153 final String stringValue
= ElementPresentationManager
.getElementName(element
);
154 if (stringValue
!= null) {
155 final DomElement parent
= element
.getManager().getIdentityScope(element
);
156 final DomGenericInfo domGenericInfo
= parent
.getGenericInfo();
157 final String tagName
= element
.getXmlElementName();
158 final DomCollectionChildDescription childDescription
= domGenericInfo
.getCollectionChildDescription(tagName
, element
.getXmlElementNamespaceKey());
159 if (childDescription
!= null) {
160 final ArrayList
<DomElement
> list
= new ArrayList
<DomElement
>(childDescription
.getValues(parent
));
161 list
.remove(element
);
167 return Collections
.emptyList();
171 public static DomElement
findDuplicateNamedValue(DomElement element
, String newName
) {
172 return ElementPresentationManager
.findByName(getIdentitySiblings(element
), newName
);
175 public static boolean isAncestor(@NotNull DomElement ancestor
, @NotNull DomElement descendant
, boolean strict
) {
176 if (!strict
&& ancestor
.equals(descendant
)) return true;
177 final DomElement parent
= descendant
.getParent();
178 return parent
!= null && isAncestor(ancestor
, parent
, false);
181 public static void acceptAvailableChildren(final DomElement element
, final DomElementVisitor visitor
) {
182 final XmlTag tag
= element
.getXmlTag();
184 for (XmlTag xmlTag
: tag
.getSubTags()) {
185 final DomElement childElement
= element
.getManager().getDomElement(xmlTag
);
186 if (childElement
!= null) {
187 childElement
.accept(visitor
);
193 public static Collection
<Class
> getAllInterfaces(final Class aClass
, final Collection
<Class
> result
) {
194 final Class
[] interfaces
= ReflectionCache
.getInterfaces(aClass
);
195 result
.addAll(Arrays
.asList(interfaces
));
196 if (aClass
.getSuperclass() != null) {
197 getAllInterfaces(aClass
.getSuperclass(), result
);
199 for (Class anInterface
: interfaces
) {
200 getAllInterfaces(anInterface
, result
);
206 public static <T
> T
getParentOfType(final DomElement element
, final Class
<T
> requiredClass
, final boolean strict
) {
207 for (DomElement curElement
= strict
&& element
!= null? element
.getParent() : element
;
209 curElement
= curElement
.getParent()) {
210 if (requiredClass
.isInstance(curElement
)) {
211 return (T
)curElement
;
218 public static DomElement
getContextElement(@Nullable final Editor editor
) {
219 if(editor
== null) return null;
221 final PsiFile file
= PsiDocumentManager
.getInstance(editor
.getProject()).getPsiFile(editor
.getDocument());
222 if (!(file
instanceof XmlFile
)) {
226 int offset
= editor
.getCaretModel().getOffset();
227 PsiElement element
= file
.findElementAt(offset
);
229 return getDomElement(element
);
233 public static DomElement
getDomElement(@Nullable final PsiElement element
) {
234 if (element
== null) return null;
236 final Project project
= element
.getProject();
237 XmlTag tag
= PsiTreeUtil
.getParentOfType(element
, XmlTag
.class);
238 while (tag
!= null) {
239 final DomElement domElement
= DomManager
.getDomManager(project
).getDomElement(tag
);
240 if(domElement
!= null) return domElement
;
242 tag
= PsiTreeUtil
.getParentOfType(tag
, XmlTag
.class, true);