3b68a0706062469fe8d003385fd7802ce9fd8bd4
[idea/community.git] / platform / lang-api / src / com / intellij / execution / junit / RuntimeConfigurationProducer.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.intellij.execution.junit;
18
19 import com.intellij.execution.*;
20 import com.intellij.execution.actions.ConfigurationContext;
21 import com.intellij.execution.configurations.*;
22 import com.intellij.execution.runners.ExecutionEnvironment;
23 import com.intellij.openapi.extensions.ExtensionPointName;
24 import com.intellij.openapi.extensions.Extensions;
25 import com.intellij.openapi.module.Module;
26 import com.intellij.openapi.options.SettingsEditor;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.util.InvalidDataException;
29 import com.intellij.openapi.util.WriteExternalException;
30 import com.intellij.psi.PsiElement;
31 import org.jdom.Element;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34
35 import java.util.ArrayList;
36 import java.util.Comparator;
37 import java.util.List;
38
39 /**
40  * @deprecated please use {@link com.intellij.execution.actions.RunConfigurationProducer} instead
41  */
42 public abstract class RuntimeConfigurationProducer implements Comparable, Cloneable {
43   public static final ExtensionPointName<RuntimeConfigurationProducer> RUNTIME_CONFIGURATION_PRODUCER = ExtensionPointName.create("com.intellij.configurationProducer");
44
45   public static final Comparator<RuntimeConfigurationProducer> COMPARATOR = new ProducerComparator();
46   protected static final int PREFERED = -1;
47   private final ConfigurationFactory myConfigurationFactory;
48   private RunnerAndConfigurationSettings myConfiguration;
49   protected boolean isClone;
50
51   public RuntimeConfigurationProducer(final ConfigurationType configurationType) {
52     this(configurationType.getConfigurationFactories()[0]);
53   }
54
55   protected RuntimeConfigurationProducer(ConfigurationFactory configurationFactory) {
56     myConfigurationFactory = configurationFactory;
57   }
58
59   public RuntimeConfigurationProducer createProducer(final Location location, final ConfigurationContext context) {
60     final RuntimeConfigurationProducer result = clone();
61     result.myConfiguration = location != null ? result.createConfigurationByElement(location, context) : null;
62
63     if (result.myConfiguration != null) {
64       final PsiElement psiElement = result.getSourceElement();
65       final Location<PsiElement> _location = PsiLocation.fromPsiElement(psiElement, location != null ? location.getModule() : null);
66       if (_location != null) {
67         // replace with existing configuration if any
68         final RunManager runManager = RunManager.getInstance(context.getProject());
69         final ConfigurationType type = result.myConfiguration.getType();
70         final List<RunnerAndConfigurationSettings> configurations = runManager.getConfigurationSettingsList(type);
71         final RunnerAndConfigurationSettings configuration = result.findExistingByElement(_location, configurations, context);
72         if (configuration != null) {
73           result.myConfiguration = configuration;
74         } else {
75           final ArrayList<String> currentNames = new ArrayList<String>();
76           for (RunnerAndConfigurationSettings configurationSettings : configurations) {
77             currentNames.add(configurationSettings.getName());
78           }
79           result.myConfiguration.setName(RunManager.suggestUniqueName(result.myConfiguration.getName(), currentNames));
80         }
81       }
82     }
83
84     return result;
85   }
86
87   @Nullable
88   public RunnerAndConfigurationSettings findExistingConfiguration(@NotNull Location location, ConfigurationContext context) {
89     assert isClone;
90     final RunManager runManager = RunManager.getInstance(location.getProject());
91     final List<RunnerAndConfigurationSettings> configurations = runManager.getConfigurationSettingsList(getConfigurationType());
92     return findExistingByElement(location, configurations, context);
93   }
94
95   public abstract PsiElement getSourceElement();
96
97   public RunnerAndConfigurationSettings getConfiguration() {
98     assert isClone;
99     return myConfiguration;
100   }
101
102   public void setConfiguration(RunnerAndConfigurationSettings configuration) {
103     assert isClone;
104     myConfiguration = configuration;
105   }
106
107   @Nullable
108   protected abstract RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context);
109
110   @Nullable
111   protected RunnerAndConfigurationSettings findExistingByElement(final Location location,
112                                                                  @NotNull final List<RunnerAndConfigurationSettings> existingConfigurations,
113                                                                  ConfigurationContext context) {
114     assert isClone;
115     return null;
116   }
117
118   @Override
119   public RuntimeConfigurationProducer clone() {
120     assert !isClone;
121     try {
122       RuntimeConfigurationProducer clone = (RuntimeConfigurationProducer)super.clone();
123       clone.isClone = true;
124       return clone;
125     }
126     catch (CloneNotSupportedException e) {
127       throw new RuntimeException(e);
128     }
129   }
130
131   protected RunnerAndConfigurationSettings cloneTemplateConfiguration(final Project project, @Nullable final ConfigurationContext context) {
132     if (context != null) {
133       final RunConfiguration original = context.getOriginalConfiguration(myConfigurationFactory.getType());
134       if (original != null) {
135         final RunConfiguration c = original instanceof DelegatingRuntimeConfiguration? ((DelegatingRuntimeConfiguration)original).getPeer() : original;
136         return RunManager.getInstance(project).createConfiguration(c.clone(), myConfigurationFactory);
137       }
138     }
139     return RunManager.getInstance(project).createRunConfiguration("", myConfigurationFactory);
140   }
141
142   protected ConfigurationFactory getConfigurationFactory() {
143     return myConfigurationFactory;
144   }
145
146   public ConfigurationType getConfigurationType() {
147     return myConfigurationFactory.getType();
148   }
149
150   public void perform(ConfigurationContext context, Runnable performRunnable){
151     performRunnable.run();
152   }
153
154   public static <T extends RuntimeConfigurationProducer> T getInstance(final Class<T> aClass) {
155     final RuntimeConfigurationProducer[] configurationProducers = Extensions.getExtensions(RUNTIME_CONFIGURATION_PRODUCER);
156     for (RuntimeConfigurationProducer configurationProducer : configurationProducers) {
157       if (configurationProducer.getClass() == aClass) {
158         //noinspection unchecked
159         return (T) configurationProducer;
160       }
161     }
162     return null;
163   }
164
165   private static class ProducerComparator implements Comparator<RuntimeConfigurationProducer> {
166     @Override
167     public int compare(final RuntimeConfigurationProducer producer1, final RuntimeConfigurationProducer producer2) {
168       final PsiElement psiElement1 = producer1.getSourceElement();
169       final PsiElement psiElement2 = producer2.getSourceElement();
170       if (doesContain(psiElement1, psiElement2)) return -PREFERED;
171       if (doesContain(psiElement2, psiElement1)) return PREFERED;
172       return producer1.compareTo(producer2);
173     }
174
175     private static boolean doesContain(final PsiElement container, PsiElement element) {
176       while ((element = element.getParent()) != null) {
177         if (container.equals(element)) return true;
178       }
179       return false;
180     }
181   }
182
183   /**
184    * @deprecated feel free to pass your configuration to SMTRunnerConsoleProperties directly instead of wrapping in DelegatingRuntimeConfiguration
185    */
186   public static class DelegatingRuntimeConfiguration<T extends LocatableConfiguration>
187     extends LocatableConfigurationBase implements ModuleRunConfiguration {
188     private final T myConfig;
189
190     public DelegatingRuntimeConfiguration(T config) {
191       super(config.getProject(), config.getFactory(), config.getName());
192       myConfig = config;
193     }
194
195     @NotNull
196     @Override
197     public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
198       return myConfig.getConfigurationEditor();
199     }
200
201     @SuppressWarnings({"CloneDoesntCallSuperClone"})
202     @Override
203     public DelegatingRuntimeConfiguration<T> clone() {
204       return new DelegatingRuntimeConfiguration<T>((T)myConfig.clone());
205     }
206
207     @Override
208     public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
209       return myConfig.getState(executor, env);
210     }
211
212     @Override
213     public void checkConfiguration() throws RuntimeConfigurationException {
214       myConfig.checkConfiguration();
215     }
216
217     @Override
218     public String suggestedName() {
219       return myConfig.suggestedName();
220     }
221
222     @Override
223     public void readExternal(Element element) throws InvalidDataException {
224       myConfig.readExternal(element);
225     }
226
227     @Override
228     public void writeExternal(Element element) throws WriteExternalException {
229       myConfig.writeExternal(element);
230     }
231
232     public T getPeer() {
233       return myConfig;
234     }
235
236     @Override
237     @NotNull
238     public Module[] getModules() {
239       return Module.EMPTY_ARRAY;
240     }
241   }
242 }