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