com.powsybl.iidm.network.scripting.GroovyScriptPostProcessor Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2017, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network.scripting;
import com.google.auto.service.AutoService;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.computation.ComputationManager;
import com.powsybl.iidm.network.ImportPostProcessor;
import com.powsybl.iidm.network.Network;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.transform.ThreadInterrupt;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
/**
* @author Mathieu Bague {@literal }
*/
@AutoService(ImportPostProcessor.class)
public class GroovyScriptPostProcessor implements ImportPostProcessor {
public static final String NAME = "groovyScript";
public static final String DEFAULT_SCRIPT_NAME = "import-post-processor.groovy";
private static final Logger LOGGER = LoggerFactory.getLogger(GroovyScriptPostProcessor.class);
private final Path script;
public GroovyScriptPostProcessor() {
this(PlatformConfig.defaultConfig());
}
public GroovyScriptPostProcessor(PlatformConfig platformConfig) {
this(getConfiguredScript(platformConfig));
}
public GroovyScriptPostProcessor(Path script) {
this.script = Objects.requireNonNull(script);
}
private static Path getConfiguredScript(PlatformConfig platformConfig) {
Objects.requireNonNull(platformConfig);
return platformConfig.getOptionalModuleConfig("groovy-post-processor")
.flatMap(config -> config.getOptionalPathProperty("script"))
.or(() -> platformConfig.getConfigDir().map(dir -> dir.resolve(DEFAULT_SCRIPT_NAME)))
.orElseThrow(() -> new PowsyblException("No script path nor configuration directory defined in platform config"));
}
@Override
public String getName() {
return NAME;
}
@Override
public void process(Network network, ComputationManager computationManager) throws Exception {
if (Files.exists(script)) {
LOGGER.debug("Execute groovy post processor {}", script);
try (Reader reader = Files.newBufferedReader(script, StandardCharsets.UTF_8)) {
CompilerConfiguration conf = new CompilerConfiguration();
// Add a check on thread interruption in every loop (for, while) in the script
conf.addCompilationCustomizers(new ASTTransformationCustomizer(ThreadInterrupt.class));
Binding binding = new Binding();
binding.setVariable("network", network);
binding.setVariable("computationManager", computationManager);
GroovyShell shell = new GroovyShell(binding, conf);
// Check for thread interruption right before beginning the evaluation
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException("Execution Interrupted");
}
shell.evaluate(reader);
}
}
}
}