ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / plugins / devkit / src / dom / impl / ExtensionDomExtender.java
blob071e6450b422c5346bf23931a180751770bacfb1
1 /*
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.devkit.dom.impl;
18 import com.intellij.ide.plugins.PluginManager;
19 import com.intellij.openapi.util.text.StringUtil;
20 import com.intellij.openapi.vfs.VirtualFile;
21 import com.intellij.psi.*;
22 import com.intellij.psi.search.GlobalSearchScope;
23 import com.intellij.psi.xml.XmlElement;
24 import com.intellij.psi.xml.XmlFile;
25 import com.intellij.util.containers.ContainerUtil;
26 import com.intellij.util.xml.*;
27 import com.intellij.util.xml.reflect.DomExtender;
28 import com.intellij.util.xml.reflect.DomExtension;
29 import com.intellij.util.xml.reflect.DomExtensionsRegistrar;
30 import com.intellij.util.xmlb.annotations.Attribute;
31 import com.intellij.util.xmlb.annotations.Tag;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34 import org.jetbrains.idea.devkit.dom.*;
36 import java.util.Collection;
37 import java.util.HashSet;
38 import java.util.Set;
40 /**
41 * @author mike
43 public class ExtensionDomExtender extends DomExtender<Extensions> {
44 private static final PsiClassConverter CLASS_CONVERTER = new PluginPsiClassConverter();
47 public void registerExtensions(@NotNull final Extensions extensions, @NotNull final DomExtensionsRegistrar registrar) {
48 final XmlElement xmlElement = extensions.getXmlElement();
49 if (xmlElement == null) return;
50 final PsiManager psiManager = xmlElement.getManager();
52 IdeaPlugin ideaPlugin = extensions.getParentOfType(IdeaPlugin.class, true);
54 if (ideaPlugin == null) return;
56 String prefix = extensions.getDefaultExtensionNs().getStringValue();
57 if (prefix == null) prefix = extensions.getXmlns().getStringValue();
58 if (prefix != null) {
59 prefix += ".";
60 } else {
61 prefix = "";
64 registerExtensions(prefix, ideaPlugin, registrar, psiManager);
65 final Collection<String> dependencies = getDependencies(ideaPlugin);
66 for (IdeaPlugin plugin : IdeaPluginConverter.collectAllVisiblePlugins(DomUtil.getFile(extensions))) {
67 final String value = plugin.getPluginId();
68 if (value != null && dependencies.contains(value)) {
69 registerExtensions(prefix, plugin, registrar, psiManager);
75 private static void registerExtensions(final String prefix, final IdeaPlugin plugin, final DomExtensionsRegistrar registrar,
76 final PsiManager psiManager) {
77 final String pluginId = plugin.getPluginId();
78 for (ExtensionPoints points : plugin.getExtensionPoints()) {
79 for (ExtensionPoint point : points.getExtensionPoints()) {
80 registerExtensionPoint(registrar, point, psiManager, prefix, pluginId);
85 private static void registerExtensionPoint(final DomExtensionsRegistrar registrar, final ExtensionPoint extensionPoint, final PsiManager manager, String prefix, @Nullable String pluginId) {
86 String epName = extensionPoint.getName().getStringValue();
87 if (epName != null && StringUtil.isNotEmpty(pluginId)) epName = pluginId + "." + epName;
88 if (epName == null) epName = extensionPoint.getQualifiedName().getStringValue();
89 if (epName == null) return;
90 if (!epName.startsWith(prefix)) return;
92 final DomExtension domExtension = registrar.registerCollectionChildrenExtension(new XmlName(epName.substring(prefix.length())), Extension.class);
93 domExtension.putUserData(DomExtension.KEY_DECLARATION, extensionPoint);
94 domExtension.addExtender(new DomExtender() {
95 public void registerExtensions(@NotNull final DomElement domElement, @NotNull final DomExtensionsRegistrar registrar) {
96 final String interfaceName = extensionPoint.getInterface().getStringValue();
97 if (interfaceName != null) {
98 registrar.registerGenericAttributeValueChildExtension(new XmlName("implementation"), PsiClass.class).setConverter(
99 CLASS_CONVERTER);
101 final PsiClass implClass =
102 JavaPsiFacade.getInstance(manager.getProject()).findClass(interfaceName, GlobalSearchScope.allScope(manager.getProject()));
103 if (implClass != null) {
104 registerXmlb(registrar, implClass);
107 else {
108 final String beanClassName = extensionPoint.getBeanClass().getStringValue();
109 if (beanClassName != null) {
110 final PsiClass beanClass =
111 JavaPsiFacade.getInstance(manager.getProject()).findClass(beanClassName, GlobalSearchScope.allScope(manager.getProject()));
113 if (beanClass != null) {
114 registerXmlb(registrar, beanClass);
122 private static void registerXmlb(final DomExtensionsRegistrar registrar, final PsiClass beanClass) {
123 final PsiField[] fields = beanClass.getAllFields();
124 for (PsiField field : fields) {
125 if (field.hasModifierProperty(PsiModifier.PUBLIC)) {
126 registerField(registrar, field);
131 private static void registerField(final DomExtensionsRegistrar registrar, @NotNull final PsiField field) {
132 final PsiAnnotation[] annotations = field.getModifierList().getAnnotations();
133 final PsiConstantEvaluationHelper evalHelper = JavaPsiFacade.getInstance(field.getProject()).getConstantEvaluationHelper();
134 for (PsiAnnotation annotation : annotations) {
135 final String qName = annotation.getQualifiedName();
136 if (qName != null) {
137 if (qName.equals(Attribute.class.getName())) {
138 final PsiAnnotationMemberValue attributeName = annotation.findAttributeValue("value");
139 if (attributeName != null && attributeName instanceof PsiExpression) {
140 final Class<String> type = String.class;
141 PsiExpression expression = (PsiExpression)attributeName;
142 final Object evaluatedExpression = evalHelper.computeConstantExpression(expression, false);
143 if (evaluatedExpression != null) {
144 registrar.registerGenericAttributeValueChildExtension(new XmlName(evaluatedExpression.toString()), type);
147 } else if (qName.equals(Tag.class.getName())) {
148 final PsiAnnotationMemberValue attributeName = annotation.findAttributeValue("value");
149 if (attributeName != null && attributeName instanceof PsiExpression) {
150 PsiExpression expression = (PsiExpression)attributeName;
151 final Object evaluatedExpression = evalHelper.computeConstantExpression(expression, false);
152 if (evaluatedExpression != null) {
153 // I guess this actually needs something like registrar.registerGenericTagValueChildExtension...
154 registrar.registerFixedNumberChildExtension(new XmlName(evaluatedExpression.toString()), SimpleTagValue.class);
162 public static Collection<String> getDependencies(IdeaPlugin ideaPlugin) {
163 Set<String> result = new HashSet<String>();
165 result.add(PluginManager.CORE_PLUGIN_ID);
167 for (Dependency dependency : ideaPlugin.getDependencies()) {
168 ContainerUtil.addIfNotNull(dependency.getStringValue(), result);
171 if (ideaPlugin.getPluginId() == null) {
172 final VirtualFile file = DomUtil.getFile(ideaPlugin).getOriginalFile().getVirtualFile();
173 if (file != null) {
174 final String fileName = file.getName();
175 if (!"plugin.xml".equals(fileName)) {
176 final VirtualFile mainPluginXml = file.findFileByRelativePath("../plugin.xml");
177 if (mainPluginXml != null) {
178 final PsiFile psiFile = PsiManager.getInstance(ideaPlugin.getManager().getProject()).findFile(mainPluginXml);
179 if (psiFile instanceof XmlFile) {
180 final XmlFile xmlFile = (XmlFile)psiFile;
181 final DomFileElement<IdeaPlugin> fileElement = ideaPlugin.getManager().getFileElement(xmlFile, IdeaPlugin.class);
182 if (fileElement != null) {
183 final IdeaPlugin mainPlugin = fileElement.getRootElement();
184 ContainerUtil.addIfNotNull(mainPlugin.getPluginId(), result);
185 for (Dependency dependency : mainPlugin.getDependencies()) {
186 ContainerUtil.addIfNotNull(dependency.getStringValue(), result);
195 return result;
198 interface SimpleTagValue extends DomElement {
199 @TagValue
200 String getValue();