spring external beans support
[fedora-idea.git] / dom / openapi / src / com / intellij / util / xml / DomUtil.java
blobe0375c5c6beca2e3f77b60765021747d8be0b555
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.psi.PsiDocumentManager;
8 import com.intellij.psi.PsiElement;
9 import com.intellij.psi.PsiFile;
10 import com.intellij.psi.util.PsiTreeUtil;
11 import com.intellij.psi.xml.XmlAttributeValue;
12 import com.intellij.psi.xml.XmlElement;
13 import com.intellij.psi.xml.XmlFile;
14 import com.intellij.psi.xml.XmlTag;
15 import com.intellij.util.ReflectionCache;
16 import com.intellij.util.ReflectionUtil;
17 import com.intellij.util.xml.reflect.DomAttributeChildDescription;
18 import com.intellij.util.xml.reflect.DomCollectionChildDescription;
19 import com.intellij.util.xml.reflect.DomFixedChildDescription;
20 import com.intellij.util.xml.reflect.DomGenericInfo;
21 import org.jetbrains.annotations.NonNls;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Type;
27 import java.lang.reflect.TypeVariable;
28 import java.util.*;
30 /**
31 * @author peter
33 public class DomUtil {
34 public static final TypeVariable<Class<GenericValue>> GENERIC_VALUE_TYPE_VARIABLE = ReflectionCache.getTypeParameters(GenericValue.class)[0];
36 private DomUtil() {
39 public static Class extractParameterClassFromGenericType(Type type) {
40 return getGenericValueParameter(type);
43 public static boolean isGenericValueType(Type type) {
44 return getGenericValueParameter(type) != null;
47 @Nullable
48 public static <T extends DomElement> T findByName(@NotNull Collection<T> list, @NonNls @NotNull String name) {
49 for (T element: list) {
50 String elementName = element.getGenericInfo().getElementName(element);
51 if (elementName != null && elementName.equals(name)) {
52 return element;
55 return null;
58 @NotNull
59 public static String[] getElementNames(@NotNull Collection<? extends DomElement> list) {
60 ArrayList<String> result = new ArrayList<String>(list.size());
61 if (list.size() > 0) {
62 for (DomElement element: list) {
63 String name = element.getGenericInfo().getElementName(element);
64 if (name != null) {
65 result.add(name);
69 return result.toArray(new String[result.size()]);
72 @NotNull
73 public static List<XmlTag> getElementTags(@NotNull Collection<? extends DomElement> list) {
74 ArrayList<XmlTag> result = new ArrayList<XmlTag>(list.size());
75 for (DomElement element: list) {
76 XmlTag tag = element.getXmlTag();
77 if (tag != null) {
78 result.add(tag);
81 return result;
84 @NotNull
85 public static XmlTag[] getElementTags(@NotNull DomElement[] list) {
86 XmlTag[] result = new XmlTag[list.length];
87 int i = 0;
88 for (DomElement element: list) {
89 XmlTag tag = element.getXmlTag();
90 if (tag != null) {
91 result[i++] = tag;
94 return result;
97 @Nullable
98 public static List<JavaMethod> getFixedPath(DomElement element) {
99 assert element.isValid();
100 final LinkedList<JavaMethod> methods = new LinkedList<JavaMethod>();
101 while (true) {
102 final DomElement parent = element.getParent();
103 if (parent instanceof DomFileElement) {
104 break;
106 final JavaMethod method = getGetterMethod(element, parent);
107 if (method == null) {
108 return null;
110 methods.addFirst(method);
111 element = element.getParent();
113 return methods;
116 @Nullable
117 private static JavaMethod getGetterMethod(final DomElement element, final DomElement parent) {
118 final String xmlElementName = element.getXmlElementName();
119 final String namespace = element.getXmlElementNamespaceKey();
120 final DomGenericInfo genericInfo = parent.getGenericInfo();
122 if (element instanceof GenericAttributeValue) {
123 final DomAttributeChildDescription description = genericInfo.getAttributeChildDescription(xmlElementName, namespace);
124 assert description != null;
125 return description.getGetterMethod();
128 final DomFixedChildDescription description = genericInfo.getFixedChildDescription(xmlElementName, namespace);
129 return description != null ? description.getGetterMethod(description.getValues(parent).indexOf(element)) : null;
132 public static Class getGenericValueParameter(Type type) {
133 return ReflectionUtil.substituteGenericType(GENERIC_VALUE_TYPE_VARIABLE, type);
136 @Nullable
137 public static XmlElement getValueElement(GenericDomValue domValue) {
138 if (domValue instanceof GenericAttributeValue) {
139 final GenericAttributeValue value = (GenericAttributeValue)domValue;
140 final XmlAttributeValue attributeValue = value.getXmlAttributeValue();
141 return attributeValue == null ? value.getXmlAttribute() : attributeValue;
142 } else {
143 return domValue.getXmlTag();
147 public static List<? extends DomElement> getIdentitySiblings(DomElement element) {
148 final Method nameValueMethod = ElementPresentationManager.findNameValueMethod(element.getClass());
149 if (nameValueMethod != null) {
150 final NameValue nameValue = DomReflectionUtil.findAnnotationDFS(nameValueMethod, NameValue.class);
151 if (nameValue == null || nameValue.unique()) {
152 final String stringValue = ElementPresentationManager.getElementName(element);
153 if (stringValue != null) {
154 final DomElement parent = element.getManager().getIdentityScope(element);
155 final DomGenericInfo domGenericInfo = parent.getGenericInfo();
156 final String tagName = element.getXmlElementName();
157 final DomCollectionChildDescription childDescription = domGenericInfo.getCollectionChildDescription(tagName, element.getXmlElementNamespaceKey());
158 if (childDescription != null) {
159 final ArrayList<DomElement> list = new ArrayList<DomElement>(childDescription.getValues(parent));
160 list.remove(element);
161 return list;
166 return Collections.emptyList();
169 @Nullable
170 public static DomElement findDuplicateNamedValue(DomElement element, String newName) {
171 return ElementPresentationManager.findByName(getIdentitySiblings(element), newName);
174 public static boolean isAncestor(@NotNull DomElement ancestor, @NotNull DomElement descendant, boolean strict) {
175 if (!strict && ancestor.equals(descendant)) return true;
176 final DomElement parent = descendant.getParent();
177 return parent != null && isAncestor(ancestor, parent, false);
180 public static void acceptAvailableChildren(final DomElement element, final DomElementVisitor visitor) {
181 final XmlTag tag = element.getXmlTag();
182 if (tag != null) {
183 for (XmlTag xmlTag : tag.getSubTags()) {
184 final DomElement childElement = element.getManager().getDomElement(xmlTag);
185 if (childElement != null) {
186 childElement.accept(visitor);
192 public static Collection<Class> getAllInterfaces(final Class aClass, final Collection<Class> result) {
193 final Class[] interfaces = ReflectionCache.getInterfaces(aClass);
194 result.addAll(Arrays.asList(interfaces));
195 if (aClass.getSuperclass() != null) {
196 getAllInterfaces(aClass.getSuperclass(), result);
198 for (Class anInterface : interfaces) {
199 getAllInterfaces(anInterface, result);
201 return result;
204 @Nullable
205 public static <T> T getParentOfType(final DomElement element, final Class<T> requiredClass, final boolean strict) {
206 for (DomElement curElement = strict && element != null? element.getParent() : element;
207 curElement != null;
208 curElement = curElement.getParent()) {
209 if (requiredClass.isInstance(curElement)) {
210 return (T)curElement;
213 return null;
216 @Nullable
217 public static DomElement getContextElement(@Nullable final Editor editor) {
218 if(editor == null) return null;
220 final PsiFile file = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument());
221 if (!(file instanceof XmlFile)) {
222 return null;
225 int offset = editor.getCaretModel().getOffset();
226 PsiElement element = file.findElementAt(offset);
227 if (element == null) return null;
229 XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
230 while (tag != null) {
231 final DomElement domElement = DomManager.getDomManager(file.getProject()).getDomElement(tag);
232 if(domElement != null) return domElement;
234 tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class, true);
236 return null;