spring: file structure usages grouping for top level beans references(IDEADEV-18706)
[fedora-idea.git] / dom / openapi / src / com / intellij / util / xml / DomUtil.java
blob75fbac43f5f5d786102d02e08d7b5112b4470746
1 /*
2 * Copyright (c) 2005 Your Corporation. All Rights Reserved.
3 */
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;
29 import java.util.*;
31 /**
32 * @author peter
34 public class DomUtil {
35 public static final TypeVariable<Class<GenericValue>> GENERIC_VALUE_TYPE_VARIABLE = ReflectionCache.getTypeParameters(GenericValue.class)[0];
37 private DomUtil() {
40 public static Class extractParameterClassFromGenericType(Type type) {
41 return getGenericValueParameter(type);
44 public static boolean isGenericValueType(Type type) {
45 return getGenericValueParameter(type) != null;
48 @Nullable
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)) {
53 return element;
56 return null;
59 @NotNull
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);
65 if (name != null) {
66 result.add(name);
70 return result.toArray(new String[result.size()]);
73 @NotNull
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();
78 if (tag != null) {
79 result.add(tag);
82 return result;
85 @NotNull
86 public static XmlTag[] getElementTags(@NotNull DomElement[] list) {
87 XmlTag[] result = new XmlTag[list.length];
88 int i = 0;
89 for (DomElement element: list) {
90 XmlTag tag = element.getXmlTag();
91 if (tag != null) {
92 result[i++] = tag;
95 return result;
98 @Nullable
99 public static List<JavaMethod> getFixedPath(DomElement element) {
100 assert element.isValid();
101 final LinkedList<JavaMethod> methods = new LinkedList<JavaMethod>();
102 while (true) {
103 final DomElement parent = element.getParent();
104 if (parent instanceof DomFileElement) {
105 break;
107 final JavaMethod method = getGetterMethod(element, parent);
108 if (method == null) {
109 return null;
111 methods.addFirst(method);
112 element = element.getParent();
114 return methods;
117 @Nullable
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);
137 @Nullable
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;
143 } else {
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);
162 return list;
167 return Collections.emptyList();
170 @Nullable
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();
183 if (tag != null) {
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);
202 return result;
205 @Nullable
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;
208 curElement != null;
209 curElement = curElement.getParent()) {
210 if (requiredClass.isInstance(curElement)) {
211 return (T)curElement;
214 return null;
217 @Nullable
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)) {
223 return null;
226 int offset = editor.getCaretModel().getOffset();
227 PsiElement element = file.findElementAt(offset);
229 return getDomElement(element);
232 @Nullable
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);
244 return null;