/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.components.optimizer.generic.execution.internal; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.io.FileUtils; import de.rcenvironment.components.optimizer.common.MethodDescription; import de.rcenvironment.components.optimizer.common.OptimizerComponentConstants; import de.rcenvironment.components.optimizer.common.OptimizerComponentHistoryDataItem; import de.rcenvironment.components.optimizer.common.execution.CommonPythonAlgorithmExecutor; import de.rcenvironment.core.component.api.ComponentException; import de.rcenvironment.core.component.datamanagement.api.ComponentDataManagementService; import de.rcenvironment.core.component.execution.api.ComponentContext; import de.rcenvironment.core.configuration.ConfigurationService; import de.rcenvironment.core.configuration.ConfigurationService.ConfigurablePathId; import de.rcenvironment.core.datamodel.api.TypedDatum; import de.rcenvironment.core.datamodel.types.api.FileReferenceTD; import de.rcenvironment.core.utils.common.CompressingHelper; import de.rcenvironment.core.utils.common.LogUtils; import de.rcenvironment.toolkit.modules.concurrency.api.TaskDescription; /** * This class provides everything for running the generic optimizer blackbox. * * @author Sascha Zur */ public class GenericAlgorithmExecutor extends CommonPythonAlgorithmExecutor { private File configurationFile; private FileReferenceTD configurationFileReference; public GenericAlgorithmExecutor(Map<String, MethodDescription> methodConfiguration, Map<String, TypedDatum> outputValues, Collection<String> input, ComponentContext ci, Map<String, Double> upperMap, Map<String, Double> lowerMap, Map<String, Double> stepValues) throws ComponentException { super(methodConfiguration, outputValues, input, ci, upperMap, lowerMap, stepValues, "input.in"); } @Override protected void prepareProblem() throws ComponentException { try { File sourceFolder = getSourceFolder(); if (sourceFolder.exists()) { if (sourceFolder.exists()) { FileUtils.copyDirectoryToDirectory(sourceFolder, workingDir); } } CompressingHelper.unzip(GenericAlgorithmExecutor.class.getResourceAsStream("/resources/RCE_Optimizer_API.zip"), new File(workingDir, "source/")); } catch (IOException | ArchiveException e) { throw new ComponentException("Failed to prepare generic algorithm", e); } configurationFile = new File(new File(workingDir, OptimizerComponentConstants.GENERIC_SOURCE), "configuration.json"); writeConfigurationFile(configurationFile); } private File getSourceFolder() { File configFolder = new File(compContext.getService(ConfigurationService.class).getConfigurablePath( ConfigurablePathId.DEFAULT_WRITEABLE_INTEGRATION_ROOT), "optimizer"); File sourceFolder = new File(new File(configFolder, methodConfiguration.get(algorithm).getConfigValue("genericFolder")), OptimizerComponentConstants.GENERIC_SOURCE); return sourceFolder; } @Override public int getOptimalRunNumber() throws ComponentException { File result = new File(workingDir, "generic.result"); try (BufferedReader fr = new BufferedReader(new FileReader(result))) { String firstLine = fr.readLine(); if (firstLine != null) { return Integer.parseInt(firstLine); } throw new ComponentException("Failed to parse result file for information about optimal variables;" + " cause: result file is empty"); } catch (IOException e) { throw new ComponentException("Failed to parse result file for information about optimal variables", e); } } @Override @TaskDescription("Optimizer Algorithm Executor Generic") public void run() { try { File pythonPathFile = new File(getSourceFolder(), "python_path"); if (pythonPathFile.exists()) { List<String> lines = FileUtils.readLines(pythonPathFile); if (lines.size() > 0 && lines.get(0) != null && !lines.get(0).isEmpty()) { String pythonPath = lines.get(0); if (pythonPath == null || pythonPath.isEmpty() || pythonPath.contains("$")) { LOGGER.warn("Failed to find path to Python; trying 'python'"); pythonPath = "python"; } startProgram(OptimizerComponentConstants.GENERIC_SOURCE + File.separator + OptimizerComponentConstants.GENERIC_MAIN_FILE, pythonPath); } else { throw new ComponentException("Could not read python path from file: " + pythonPathFile.getAbsolutePath()); } } else { throw new ComponentException( "Could not read python path from file, it does not exist: " + pythonPathFile.getAbsolutePath()); } } catch (ComponentException | IOException e) { startFailed.set(true); startFailedException = e; LOGGER.error("Could not start external algorithm: ", e); } } @Override public void writeHistoryDataItem(OptimizerComponentHistoryDataItem historyItem) { if (configurationFileReference == null) { try { configurationFileReference = compContext.getService(ComponentDataManagementService.class).createFileReferenceTDFromLocalFile(compContext, configurationFile, "configuration.json"); } catch (IOException e) { String errorMessage = "Failed to store configuration file into the data management" + "; it is not available in the workflow data browser"; String errorId = LogUtils.logExceptionWithStacktraceAndAssignUniqueMarker(LOGGER, errorMessage, e); compContext.getLog().componentError(errorMessage, e, errorId); } } if (configurationFileReference != null) { historyItem.setInputFileReference(configurationFileReference.getFileReference()); } } }