package name.admitriev.jhelper.configuration;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.jetbrains.cidr.execution.CidrCommandLineState;
import name.admitriev.jhelper.exceptions.JHelperException;
import name.admitriev.jhelper.task.TaskData;
import name.admitriev.jhelper.ui.TaskSettingsComponent;
import net.egork.chelper.task.StreamConfiguration;
import net.egork.chelper.task.Test;
import net.egork.chelper.task.TestType;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* Run Configuration for running JHelper tasks
*/
public class TaskConfiguration extends RunConfigurationBase {
private String className;
private String cppPath;
private StreamConfiguration input;
private StreamConfiguration output;
private TestType testType;
private Test[] tests;
public TaskConfiguration(Project project, ConfigurationFactory factory) {
super(project, factory, "");
className = "";
cppPath = "";
input = new StreamConfiguration(StreamConfiguration.StreamType.STANDARD);
output = new StreamConfiguration(StreamConfiguration.StreamType.STANDARD);
testType = TestType.SINGLE;
tests = new Test[0];
}
@NotNull
@Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new SettingsEditor<TaskConfiguration>() {
private TaskSettingsComponent component = new TaskSettingsComponent(getProject(), false);
@Override
protected void resetEditorFrom(@NotNull TaskConfiguration settings) {
component.setTaskData(new TaskData(
getName(),
className,
cppPath,
input,
output,
testType,
new Test[0]
));
}
@Override
protected void applyEditorTo(@NotNull TaskConfiguration settings) {
TaskData data = component.getTask();
settings.className = data.getClassName();
settings.cppPath = data.getCppPath();
settings.input = data.getInput();
settings.output = data.getOutput();
settings.testType = data.getTestType();
}
@NotNull
@Override
protected JComponent createEditor() {
return component;
}
};
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
}
@Nullable
@Override
public CidrCommandLineState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
throw new JHelperException("This method is not expected to be used");
}
@Override
public TaskConfiguration clone() {
TaskConfiguration newConfiguration = (TaskConfiguration) super.clone();
newConfiguration.className = className;
newConfiguration.cppPath = cppPath;
newConfiguration.input = input;
newConfiguration.output = output;
newConfiguration.testType = testType;
newConfiguration.tests = tests.clone();
return newConfiguration;
}
private static StreamConfiguration readStreamConfiguration(
Element element,
String typeAttribute,
String filenameAttribute
) {
try {
StreamConfiguration.StreamType inputType = StreamConfiguration.StreamType.valueOf(
element.getAttribute(typeAttribute).getValue()
);
if (inputType.hasStringParameter) {
String filename = element.getAttributeValue(filenameAttribute);
return new StreamConfiguration(inputType, filename);
}
else {
return new StreamConfiguration(inputType);
}
} catch (RuntimeException ignored) {
return StreamConfiguration.STANDARD;
}
}
@Override
public void readExternal(Element element) {
super.readExternal(element);
className = element.getAttributeValue("className", "");
cppPath = element.getAttributeValue("cppPath", "");
input = readStreamConfiguration(element, "inputPath", "inputFile");
output = readStreamConfiguration(element, "outputPath", "outputFile");
try {
testType = TestType.valueOf(element.getAttributeValue("testType", "SINGLE"));
} catch (IllegalArgumentException ignored) {
testType = TestType.SINGLE;
}
List<Element> children = element.getChildren();
for (Element child : children) {
if (Objects.equals(child.getName(), "tests")) {
List<Element> testChildren = child.getChildren();
tests = new Test[testChildren.size()];
for (int i = 0; i < testChildren.size(); ++i) {
tests[i] = readTest(testChildren.get(i));
}
}
}
}
private static Test readTest(Element element) {
assert element.getName().equals("test");
String input = element.getAttributeValue("input");
String output = element.getAttributeValue("output");
boolean active = element.getAttributeValue("active").equals("true");
return new Test(input, output, 0, active);
}
@Override
public void writeExternal(Element element) {
element.setAttribute("className", className);
element.setAttribute("cppPath", cppPath);
element.setAttribute("inputType", String.valueOf(input.type.name()));
if (input.fileName != null) {
element.setAttribute("inputFile", input.fileName);
}
element.setAttribute("outputType", String.valueOf(output.type.name()));
if (output.fileName != null) {
element.setAttribute("outputFile", output.fileName);
}
element.setAttribute("testType", testType.name());
Element testsElements = new Element("tests");
for (Test test : tests) {
Element testElement = new Element("test");
testElement.setAttribute("input", test.input);
if (test.output != null) {
testElement.setAttribute("output", test.output);
}
testElement.setAttribute("active", String.valueOf(test.active));
testsElements.addContent(testElement);
}
element.addContent(testsElements);
super.writeExternal(element);
}
public void setFromTaskData(TaskData data) {
setName(data.getName());
className = data.getClassName();
cppPath = data.getCppPath();
input = data.getInput();
output = data.getOutput();
testType = data.getTestType();
tests = data.getTests();
}
public void setTests(Test[] tests) {
this.tests = Arrays.copyOf(tests, tests.length);
}
public Test[] getTests() {
return Arrays.copyOf(tests, tests.length);
}
public String getCppPath() {
return cppPath;
}
public String getClassName() {
return className;
}
public TestType getTestType() {
return testType;
}
public StreamConfiguration getInput() {
return input;
}
public StreamConfiguration getOutput() {
return output;
}
}