Skip to content
Snippets Groups Projects
Commit feb53311 authored by Reiner Jung's avatar Reiner Jung
Browse files

Merge branch 'dataflow' into 'main'

Dataflow

See merge request oceandsl/oceandsl-tools!5
parents e6b5f93f 94bdf125
No related branches found
No related tags found
No related merge requests found
Showing
with 1075 additions and 41 deletions
......@@ -30,8 +30,12 @@ import com.beust.jcommander.converters.PathConverter;
public class Settings {
@Parameter(names = { "-i",
"--input" }, required = true, converter = PathConverter.class, description = "Function call CSV file")
private Path inputFile;
"--call-input" }, required = true, converter = PathConverter.class, description = "Function call CSV file")
private Path operationCallInputFile;
@Parameter(names = { "-j",
"--dataflow-input" }, required = true, converter = PathConverter.class, description = "Dataflow CSV file")
private Path dataflowInputFile;
@Parameter(names = { "-f",
"--function-names" }, required = false, variableArity = true, converter = PathConverter.class, description = "Function file map CSV file")
......@@ -59,8 +63,8 @@ public class Settings {
@Parameter(names = { "-E", "--experiment-name" }, required = true, description = "Name of the experiment")
private String experimentName;
public Path getInputFile() {
return this.inputFile;
public Path getOperationCallInputFile() {
return this.operationCallInputFile;
}
public List<Path> getFunctionNameFiles() {
......@@ -90,4 +94,8 @@ public class Settings {
public Path getComponentMapFile() {
return this.componentMapFile;
}
public Path getDataflowInputFile() {
return this.dataflowInputFile;
}
}
......@@ -15,21 +15,22 @@
***************************************************************************/
package org.oceandsl.tools.sar;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import org.oceandsl.architecture.model.ArchitectureModelManagementFactory;
import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import kieker.analysis.stage.model.ModelRepository;
import kieker.common.configuration.Configuration;
import kieker.common.exception.ConfigurationException;
import kieker.tools.common.AbstractService;
import teetime.framework.Configuration;
import teetime.framework.Execution;
/**
* Architecture analysis main class.
......@@ -37,7 +38,28 @@ import kieker.tools.common.AbstractService;
* @author Reiner Jung
* @since 1.1
*/
public class StaticArchitectureRecoveryMain extends AbstractService<TeetimeConfiguration, Settings> {
public class StaticArchitectureRecoveryMain {
/** Exit code for successful operation. */
public static final int SUCCESS_EXIT_CODE = 0;
/** An runtime error happened. */
public static final int RUNTIME_ERROR = 1;
/** There was an configuration error. */
public static final int CONFIGURATION_ERROR = 2;
/** There was a parameter error. */
public static final int PARAMETER_ERROR = 3;
/** Displayed the usage message. */
public static final int USAGE_EXIT_CODE = 4;
/** logger for all tools. */
protected final Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName()); // NOPMD
/** true if help should be displayed. */
protected boolean help = false; // NOPMD this is set to false for documentation purposes
/** configuration specified as parameters. */
protected Settings settings;
/** configuration provided as kieker configuration file. */
protected kieker.common.configuration.Configuration kiekerConfiguration;
private ModelRepository repository;
......@@ -53,39 +75,84 @@ public class StaticArchitectureRecoveryMain extends AbstractService<TeetimeConfi
}
}
@Override
protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
/**
* Execute the tool.
*
* @param commander
* command line parter JCommander
* @param label
* printed to the debug log about what application is running.
*/
private void execute(final JCommander commander, final String label) throws ConfigurationException {
this.executeConfiguration("call", label, this.createTeetimeCallConfiguration());
this.executeConfiguration("dataflow", label, this.createTeetimeDataflowConfiguration());
this.shutdownService();
this.logger.debug("Done");
}
private <T extends Configuration> void executeConfiguration(final String type, final String label,
final T createTeetimeConfiguration) {
final Execution<T> execution = new Execution<>(createTeetimeConfiguration);
final Thread shutdownThread = this.shutdownHook(execution);
this.logger.debug("Running {} {}", type, label);
execution.executeBlocking();
if (!shutdownThread.isAlive()) {
Runtime.getRuntime().removeShutdownHook(shutdownThread);
}
}
/**
* General shutdown hook for services and tools.
*
* @param execution
* teetime execution
*/
private Thread shutdownHook(final Execution<?> execution) {
final Thread shutdownThread = new Thread(new Runnable() { // NOPMD is not a web app
/**
* Thread to gracefully terminate service.
*/
@Override
public void run() {
synchronized (execution) {
execution.abortEventually();
StaticArchitectureRecoveryMain.this.shutdownService();
}
}
});
Runtime.getRuntime().addShutdownHook(shutdownThread);
return shutdownThread;
}
private TeetimeCallConfiguration createTeetimeCallConfiguration() throws ConfigurationException {
try {
this.repository = ArchitectureModelManagementFactory.createModelRepository(
this.parameterConfiguration.getExperimentName(),
this.parameterConfiguration.getComponentMapFile() != null);
return new TeetimeConfiguration(this.logger, this.parameterConfiguration, this.repository);
return new TeetimeCallConfiguration(this.logger, this.settings, this.repository);
} catch (final IOException | ValueConversionErrorException e) {
this.logger.error("Error reading files. Cause: {}", e.getLocalizedMessage());
throw new ConfigurationException(e);
}
}
@Override
protected File getConfigurationFile() {
// we do not use a configuration file
return null;
}
@Override
protected boolean checkConfiguration(final Configuration configuration, final JCommander commander) {
return true;
private TeetimeDataflowConfiguration createTeetimeDataflowConfiguration() throws ConfigurationException {
try {
return new TeetimeDataflowConfiguration(this.logger, this.settings, this.repository);
} catch (final IOException | ValueConversionErrorException e) {
this.logger.error("Error reading files. Cause: {}", e.getLocalizedMessage());
throw new ConfigurationException(e);
}
}
@Override
protected boolean checkParameters(final JCommander commander) throws ConfigurationException {
if (!Files.isReadable(this.parameterConfiguration.getInputFile())) {
this.logger.error("Input path {} is not file", this.parameterConfiguration.getInputFile());
if (!Files.isReadable(this.settings.getOperationCallInputFile())) {
this.logger.error("Input path {} is not file", this.settings.getOperationCallInputFile());
return false;
}
if (this.parameterConfiguration.getFunctionNameFiles() != null) {
for (final Path functionNameFile : this.parameterConfiguration.getFunctionNameFiles()) {
if (this.settings.getFunctionNameFiles() != null) {
for (final Path functionNameFile : this.settings.getFunctionNameFiles()) {
if (!Files.isReadable(functionNameFile)) {
this.logger.error("Function map file {} cannot be found", functionNameFile);
return false;
......@@ -93,18 +160,63 @@ public class StaticArchitectureRecoveryMain extends AbstractService<TeetimeConfi
}
}
if (!Files.isDirectory(this.parameterConfiguration.getOutputDirectory().getParent())) {
this.logger.error("Output path {} is not directory", this.parameterConfiguration.getOutputDirectory());
if (!Files.isDirectory(this.settings.getOutputDirectory().getParent())) {
this.logger.error("Output path {} is not directory", this.settings.getOutputDirectory());
return false;
}
return true;
}
@Override
protected void shutdownService() {
/**
* Configure and execute the evaluation tool utilizing an external configuration.
*
* @param title
* start up label for debug messages
* @param label
* label used during execution to indicate the running service
* @param args
* arguments are ignored
* @param stettings
* configuration object
*
* @return returns exit code
*/
public int run(final String title, final String label, final String[] args, final Settings stettings) {
this.settings = stettings;
this.logger.debug(title);
final JCommander commander = new JCommander(stettings);
try {
commander.parse(args);
if (this.checkParameters(commander)) {
if (this.help) {
commander.usage();
return StaticArchitectureRecoveryMain.USAGE_EXIT_CODE;
} else {
this.repository = ArchitectureModelManagementFactory.createModelRepository(
this.settings.getExperimentName(), this.settings.getComponentMapFile() != null);
this.execute(commander, label);
return StaticArchitectureRecoveryMain.SUCCESS_EXIT_CODE;
}
} else {
this.logger.error("Configuration Error"); // NOPMD
return StaticArchitectureRecoveryMain.CONFIGURATION_ERROR;
}
} catch (final ParameterException e) {
this.logger.error(e.getLocalizedMessage()); // NOPMD
commander.usage();
return StaticArchitectureRecoveryMain.PARAMETER_ERROR;
} catch (final ConfigurationException e) {
this.logger.error(e.getLocalizedMessage()); // NOPMD
commander.usage();
return StaticArchitectureRecoveryMain.CONFIGURATION_ERROR;
}
}
private void shutdownService() {
try {
ArchitectureModelManagementFactory.writeModelRepository(this.parameterConfiguration.getOutputDirectory(),
ArchitectureModelManagementFactory.writeModelRepository(this.settings.getOutputDirectory(),
this.repository);
} catch (final IOException e) {
this.logger.error("Error saving model: {}", e.getLocalizedMessage());
......
......@@ -25,6 +25,9 @@ import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
import org.oceandsl.architecture.model.stages.CSVFixPathStage;
import org.oceandsl.architecture.model.stages.CSVMapperStage;
import org.oceandsl.architecture.model.stages.CountUniqueCallsStage;
import org.oceandsl.tools.sar.stages.FileBasedCleanupComponentSignatureStage;
import org.oceandsl.tools.sar.stages.MapBasedCleanupComponentSignatureStage;
import org.oceandsl.tools.sar.stages.OperationAndCall4StaticDataStage;
import org.slf4j.Logger;
import kieker.analysis.signature.IComponentSignatureExtractor;
......@@ -53,16 +56,18 @@ import teetime.framework.OutputPort;
* @author Reiner Jung
* @since 1.0
*/
public class TeetimeConfiguration extends Configuration {
public TeetimeConfiguration(final Logger logger, final Settings parameterConfiguration,
public class TeetimeCallConfiguration extends Configuration {
public TeetimeCallConfiguration(final Logger logger, final Settings parameterConfiguration,
final ModelRepository repository) throws IOException, ValueConversionErrorException {
OutputPort<CallerCallee> readerPort;
logger.info("Processing static call log");
final CSVFunctionCallReaderStage readCsvStage = new CSVFunctionCallReaderStage(
parameterConfiguration.getInputFile());
parameterConfiguration.getOperationCallInputFile());
readerPort = readCsvStage.getOutputPort();
if ((parameterConfiguration.getFunctionNameFiles() != null)
&& !parameterConfiguration.getFunctionNameFiles().isEmpty()) {
final CSVFixPathStage fixPathStage = new CSVFixPathStage(parameterConfiguration.getFunctionNameFiles());
......@@ -86,6 +91,7 @@ public class TeetimeConfiguration extends Configuration {
parameterConfiguration.getCaseInsensitive());
this.connectPorts(readerPort, cleanupComponentSignatureStage.getInputPort());
readerPort = cleanupComponentSignatureStage.getOutputPort();
}
......@@ -119,7 +125,7 @@ public class TeetimeConfiguration extends Configuration {
final OperationAndCall4StaticDataStage operationAndCallStage = new OperationAndCall4StaticDataStage(
parameterConfiguration.getHostname());
/** -- call based modeling -- */
final TypeModelAssemblerStage typeModelAssemblerStage = new TypeModelAssemblerStage(
repository.getModel(TypeModel.class), repository.getModel(SourceModel.class),
parameterConfiguration.getSourceLabel(), componentSignatureExtractor, operationSignatureExtractor);
......
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar;
import java.io.IOException;
import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
import org.oceandsl.tools.sar.stages.dataflow.AssemblyModelDataflowAssemblerStage;
import org.oceandsl.tools.sar.stages.dataflow.CSVDataflowReaderStage;
import org.oceandsl.tools.sar.stages.dataflow.DataAccess;
import org.oceandsl.tools.sar.stages.dataflow.DeploymentModelDataflowAssemblerStage;
import org.oceandsl.tools.sar.stages.dataflow.ExecutionModelDataflowAssemblerStage;
import org.oceandsl.tools.sar.stages.dataflow.FileBasedCleanupComponentInDataflowSignatureStage;
import org.oceandsl.tools.sar.stages.dataflow.TypeModelDataflowAssemblerStage;
import org.slf4j.Logger;
import kieker.analysis.stage.model.ModelRepository;
import kieker.model.analysismodel.assembly.AssemblyModel;
import kieker.model.analysismodel.deployment.DeploymentModel;
import kieker.model.analysismodel.execution.ExecutionModel;
import kieker.model.analysismodel.sources.SourceModel;
import kieker.model.analysismodel.type.TypeModel;
import teetime.framework.Configuration;
import teetime.framework.OutputPort;
/**
* Pipe and Filter configuration for the architecture creation tool.
*
* @author Reiner Jung
* @since 1.0
*/
public class TeetimeDataflowConfiguration extends Configuration {
public TeetimeDataflowConfiguration(final Logger logger, final Settings parameterConfiguration,
final ModelRepository repository) throws IOException, ValueConversionErrorException {
OutputPort<DataAccess> readerDataflowPort;
logger.info("Processing static call log");
final CSVDataflowReaderStage readDataflowStage = new CSVDataflowReaderStage(
parameterConfiguration.getDataflowInputFile());
readerDataflowPort = readDataflowStage.getOutputPort();
if (parameterConfiguration.getComponentMapFile() != null) {
logger.info("Map based component definition");
} else {
logger.info("File based component definition");
final FileBasedCleanupComponentInDataflowSignatureStage cleanupComponentDataflowSignatureStage = new FileBasedCleanupComponentInDataflowSignatureStage(
parameterConfiguration.getCaseInsensitive());
this.connectPorts(readerDataflowPort, cleanupComponentDataflowSignatureStage.getInputPort());
readerDataflowPort = cleanupComponentDataflowSignatureStage.getOutputPort();
}
/** -- call based modeling -- */
final TypeModelDataflowAssemblerStage typeModelDataflowAssemblerStage = new TypeModelDataflowAssemblerStage(
repository.getModel(TypeModel.class), repository.getModel(SourceModel.class),
parameterConfiguration.getSourceLabel());
final AssemblyModelDataflowAssemblerStage assemblyModelDataflowAssemblerStage = new AssemblyModelDataflowAssemblerStage(
repository.getModel(TypeModel.class), repository.getModel(AssemblyModel.class),
repository.getModel(SourceModel.class), parameterConfiguration.getSourceLabel());
final DeploymentModelDataflowAssemblerStage deploymentModelDataflowAssemblerStage = new DeploymentModelDataflowAssemblerStage(
repository.getModel(AssemblyModel.class), repository.getModel(DeploymentModel.class),
repository.getModel(SourceModel.class), parameterConfiguration.getSourceLabel());
final ExecutionModelDataflowAssemblerStage executionModelDataflowGenerationStage = new ExecutionModelDataflowAssemblerStage(
repository.getModel(ExecutionModel.class), repository.getModel(DeploymentModel.class),
repository.getModel(SourceModel.class), parameterConfiguration.getSourceLabel());
/** connecting ports. */
this.connectPorts(readerDataflowPort, typeModelDataflowAssemblerStage.getInputPort());
this.connectPorts(typeModelDataflowAssemblerStage.getOutputPort(),
assemblyModelDataflowAssemblerStage.getInputPort());
this.connectPorts(assemblyModelDataflowAssemblerStage.getOutputPort(),
deploymentModelDataflowAssemblerStage.getInputPort());
this.connectPorts(deploymentModelDataflowAssemblerStage.getOutputPort(),
executionModelDataflowGenerationStage.getInputPort());
}
}
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar;
package org.oceandsl.tools.sar.stages;
import org.oceandsl.analysis.CallerCallee;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar;
package org.oceandsl.tools.sar.stages;
import java.io.IOException;
import java.nio.file.Path;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar;
package org.oceandsl.tools.sar.stages;
import java.io.BufferedReader;
import java.io.IOException;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar;
package org.oceandsl.tools.sar.stages;
import java.time.Duration;
......
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import kieker.model.analysismodel.sources.SourceModel;
import teetime.stage.basic.AbstractTransformation;
/**
* @author Reiner Jung
* @since 1.1
*/
public abstract class AbstractDataflowAssemblerStage<I, O> extends AbstractTransformation<I, O> {
protected final SourceModel sourceModel;
protected final String sourceLabel;
public AbstractDataflowAssemblerStage(final SourceModel sourceModel, final String sourceLabel) {
this.sourceModel = sourceModel;
this.sourceLabel = sourceLabel;
}
protected void addObjectToSource(final EObject object) {
EList<String> sources = this.sourceModel.getSources().get(object);
boolean exists = false;
if (sources != null) {
for (final String source : sources) {
if (this.sourceLabel.equals(source)) {
exists = true;
}
}
} else {
sources = new BasicEList<>();
}
if (!exists) {
sources.add(this.sourceLabel);
this.sourceModel.getSources().put(object, sources);
}
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import kieker.model.analysismodel.assembly.AssemblyComponent;
import kieker.model.analysismodel.assembly.AssemblyFactory;
import kieker.model.analysismodel.assembly.AssemblyModel;
import kieker.model.analysismodel.assembly.AssemblyOperation;
import kieker.model.analysismodel.assembly.AssemblyStorage;
import kieker.model.analysismodel.sources.SourceModel;
import kieker.model.analysismodel.type.ComponentType;
import kieker.model.analysismodel.type.StorageType;
import kieker.model.analysismodel.type.TypeModel;
/**
* @author Reiner Jung
*
*/
public class AssemblyModelDataflowAssemblerStage extends AbstractDataflowAssemblerStage<DataAccess, DataAccess> {
private final TypeModel typeModel;
private final AssemblyModel assemblyModel;
private final Map<String, AssemblyStorage> assemblyStorageMap = new HashMap<>();
private final Map<AssemblyStorage, List<AssemblyComponent>> assemblyStorageAccessMap = new HashMap<>();
public AssemblyModelDataflowAssemblerStage(final TypeModel typeModel, final AssemblyModel assemblyModel,
final SourceModel sourceModel, final String sourceLabel) {
super(sourceModel, sourceLabel);
this.typeModel = typeModel;
this.assemblyModel = assemblyModel;
}
@Override
protected void execute(final DataAccess element) throws Exception {
final AssemblyOperation operation = this.findOperation(element);
final AssemblyStorage assemblyStorage = this.findOrCreateDataStorage(element, operation.getAssemblyComponent());
this.addObjectToSource(assemblyStorage);
this.outputPort.send(element);
}
private AssemblyStorage findOrCreateDataStorage(final DataAccess element,
final AssemblyComponent assemblyComponent) {
AssemblyStorage assemblyStorage = this.assemblyStorageMap.get(element.getSharedData());
if (assemblyStorage == null) {
assemblyStorage = AssemblyFactory.eINSTANCE.createAssemblyStorage();
assemblyStorage.setStorageType(this.findStorageType(element.getSharedData()));
assemblyComponent.getAssemblyStorages().put(element.getSharedData(), assemblyStorage);
this.assemblyStorageMap.put(element.getSharedData(), assemblyStorage);
final List<AssemblyComponent> newList = new ArrayList<>();
newList.add(assemblyComponent);
this.assemblyStorageAccessMap.put(assemblyStorage, newList);
} else {
final List<AssemblyComponent> accessedByList = this.assemblyStorageAccessMap.get(assemblyStorage);
if (!accessedByList.contains(assemblyComponent)) {
if (accessedByList.size() == 1) {
this.moveStorageAccessToSeparateComponent(assemblyStorage, accessedByList.get(0));
}
accessedByList.add(assemblyComponent);
this.assemblyStorageAccessMap.put(assemblyStorage, accessedByList);
}
}
return assemblyStorage;
}
private void moveStorageAccessToSeparateComponent(final AssemblyStorage assemblyStorage,
final AssemblyComponent assemblyComponent) {
final String name = assemblyStorage.getStorageType().getName();
assemblyComponent.getAssemblyStorages().removeKey(name);
final AssemblyComponent newAssemblyComponent = AssemblyFactory.eINSTANCE.createAssemblyComponent();
newAssemblyComponent
.setComponentType(this.findComponentType(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name));
newAssemblyComponent.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name);
newAssemblyComponent.getAssemblyStorages().put(name, assemblyStorage);
this.addObjectToSource(newAssemblyComponent);
this.assemblyModel.getAssemblyComponents().put(newAssemblyComponent.getSignature(), newAssemblyComponent);
}
private ComponentType findComponentType(final String componentSignature) {
return this.typeModel.getComponentTypes().get(componentSignature);
}
private StorageType findStorageType(final String sharedData) {
for (final ComponentType type : this.typeModel.getComponentTypes().values()) {
final StorageType storageType = type.getProvidedStorages().get(sharedData);
if (storageType != null) {
return storageType;
}
}
this.logger.error("Intternal error: Missing storage type for given data access element {}", sharedData);
return null;
}
private AssemblyOperation findOperation(final DataAccess element) {
AssemblyComponent assemblyComponent = this.assemblyModel.getAssemblyComponents().get(element.getModule());
if (assemblyComponent == null) {
assemblyComponent = AssemblyFactory.eINSTANCE.createAssemblyComponent();
assemblyComponent.setComponentType(this.findComponentType(element.getModule()));
assemblyComponent.setSignature(element.getModule());
this.assemblyModel.getAssemblyComponents().put(element.getModule(), assemblyComponent);
}
AssemblyOperation operation = assemblyComponent.getAssemblyOperations().get(element.getOperation());
if (operation == null) {
operation = AssemblyFactory.eINSTANCE.createAssemblyOperation();
operation.setOperationType(
assemblyComponent.getComponentType().getProvidedOperations().get(element.getOperation()));
assemblyComponent.getAssemblyOperations().put(element.getOperation(), operation);
}
return operation;
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import teetime.framework.AbstractProducerStage;
/**
* @author Reiner Jung
*
*/
public class CSVDataflowReaderStage extends AbstractProducerStage<DataAccess> {
private final BufferedReader reader;
/**
* Read a single CSV file.
*
* @param path
* file path
* @throws IOException
* when a stream could not be opened.
*/
public CSVDataflowReaderStage(final Path path) throws IOException {
this.reader = Files.newBufferedReader(path);
}
@Override
protected void execute() throws Exception {
// ignore the header
this.reader.readLine();
String line;
while ((line = this.reader.readLine()) != null) {
final String[] values = line.split(",");
if (values.length >= 4) {
try {
this.outputPort.send(new DataAccess(values[0].trim(), values[1].trim(),
EDirection.getValue(values[2].trim()), values[3].trim()));
} catch (final Exception e) {
this.logger.error("Line format error '{}', {}", line, e.getMessage());
}
} else {
this.logger.error("Line needs at least 4 values. :{}:", line);
}
}
this.reader.close();
this.workCompleted();
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
/**
* @author Reiner Jung
* @since 1.1
*/
public class DataAccess {
private String module;
private final String operation;
private final EDirection direction;
private final String sharedData;
public DataAccess(final String module, final String operation, final EDirection direction,
final String sharedData) {
this.module = module;
this.operation = operation;
this.direction = direction;
this.sharedData = sharedData;
}
public String getModule() {
return this.module;
}
public String getOperation() {
return this.operation;
}
public EDirection getDirection() {
return this.direction;
}
public String getSharedData() {
return this.sharedData;
}
public void setModule(final String module) {
this.module = module;
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import kieker.model.analysismodel.assembly.AssemblyComponent;
import kieker.model.analysismodel.assembly.AssemblyModel;
import kieker.model.analysismodel.assembly.AssemblyOperation;
import kieker.model.analysismodel.assembly.AssemblyStorage;
import kieker.model.analysismodel.deployment.DeployedComponent;
import kieker.model.analysismodel.deployment.DeployedOperation;
import kieker.model.analysismodel.deployment.DeployedStorage;
import kieker.model.analysismodel.deployment.DeploymentContext;
import kieker.model.analysismodel.deployment.DeploymentFactory;
import kieker.model.analysismodel.deployment.DeploymentModel;
import kieker.model.analysismodel.sources.SourceModel;
/**
* @author Reiner Jung
* @since 1.1
*
*/
public class DeploymentModelDataflowAssemblerStage extends AbstractDataflowAssemblerStage<DataAccess, DataAccess> {
private final AssemblyModel assemblyModel;
private final DeploymentModel deploymentModel;
private final Map<String, DeployedStorage> deployedStorageMap = new HashMap<>();
private final Map<DeployedStorage, List<DeployedComponent>> deployedStorageAccessMap = new HashMap<>();
public DeploymentModelDataflowAssemblerStage(final AssemblyModel assemblyModel,
final DeploymentModel deploymentModel, final SourceModel sourceModel, final String sourceLabel) {
super(sourceModel, sourceLabel);
this.assemblyModel = assemblyModel;
this.deploymentModel = deploymentModel;
}
@Override
protected void execute(final DataAccess element) throws Exception {
final DeployedOperation operation = this.findOperation(element);
final DeployedStorage assemblyStorage = this.findOrCreateDataStorage(element, operation.getComponent());
this.addObjectToSource(assemblyStorage);
this.outputPort.send(element);
}
private DeployedStorage findOrCreateDataStorage(final DataAccess element,
final DeployedComponent deployedComponent) {
DeployedStorage deployedStorage = this.deployedStorageMap.get(element.getSharedData());
if (deployedStorage == null) {
deployedStorage = DeploymentFactory.eINSTANCE.createDeployedStorage();
deployedStorage.setAssemblyStorage(this.findAssemblyStorage(element.getSharedData()));
deployedComponent.getContainedStorages().put(element.getSharedData(), deployedStorage);
this.deployedStorageMap.put(element.getSharedData(), deployedStorage);
final List<DeployedComponent> newList = new ArrayList<>();
newList.add(deployedComponent);
this.deployedStorageAccessMap.put(deployedStorage, newList);
} else {
final List<DeployedComponent> accessedByList = this.deployedStorageAccessMap.get(deployedStorage);
if (!accessedByList.contains(deployedComponent)) {
if (accessedByList.size() == 1) {
this.moveStorageAccessToSeparateComponent(deployedStorage, accessedByList.get(0));
}
accessedByList.add(deployedComponent);
this.deployedStorageAccessMap.put(deployedStorage, accessedByList);
}
}
return deployedStorage;
}
private AssemblyStorage findAssemblyStorage(final String sharedData) {
for (final AssemblyComponent assemblyComponent : this.assemblyModel.getAssemblyComponents().values()) {
final AssemblyStorage assemblyStorage = assemblyComponent.getAssemblyStorages().get(sharedData);
if (assemblyStorage != null) {
return assemblyStorage;
}
}
this.logger.error("Internal error. Could not find previously defined assembly storage {}", sharedData);
return null;
}
private DeployedOperation findOperation(final DataAccess element) {
final DeploymentContext context = this.deploymentModel.getDeploymentContexts().get(0).getValue();
if (context == null) {
this.logger.error("Internal error: Data must contain at least one deployment context.");
return null;
} else {
DeployedComponent component = context.getComponents().get(element.getModule());
if (component == null) {
this.logger.warn("Cannot find deployed component for {}", element.getModule());
component = DeploymentFactory.eINSTANCE.createDeployedComponent();
component.setSignature(element.getModule());
component.setAssemblyComponent(this.findAssemblyComponent(element.getModule()));
context.getComponents().put(element.getModule(), component);
}
DeployedOperation deployedOperation = component.getContainedOperations().get(element.getOperation());
if (deployedOperation == null) {
this.logger.warn("Operation {} cannot be found in model.", element.getOperation());
final AssemblyComponent assemblyComponent = this.assemblyModel.getAssemblyComponents()
.get(element.getModule());
final AssemblyOperation assemblyOperation = assemblyComponent.getAssemblyOperations()
.get(element.getOperation());
deployedOperation = DeploymentFactory.eINSTANCE.createDeployedOperation();
deployedOperation.setAssemblyOperation(assemblyOperation);
component.getContainedOperations().put(element.getOperation(), deployedOperation);
}
return deployedOperation;
}
}
private void moveStorageAccessToSeparateComponent(final DeployedStorage deployedStorage,
final DeployedComponent deployedComponent) {
final String name = deployedStorage.getAssemblyStorage().getStorageType().getName();
deployedComponent.getContainedStorages().removeKey(name);
final DeployedComponent newDeployedComponent = DeploymentFactory.eINSTANCE.createDeployedComponent();
newDeployedComponent.setAssemblyComponent(
this.findAssemblyComponent(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name));
newDeployedComponent.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name);
newDeployedComponent.getContainedStorages().put(name, deployedStorage);
this.addObjectToSource(newDeployedComponent);
this.deploymentModel.getDeploymentContexts().get(0).getValue().getComponents()
.put(newDeployedComponent.getSignature(), newDeployedComponent);
}
private AssemblyComponent findAssemblyComponent(final String signature) {
return this.assemblyModel.getAssemblyComponents().get(signature);
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
/**
* @author Reiner Jung
*
*/
public enum EDirection {
READ, WRITE, BOTH;
public static EDirection getValue(final String name) throws Exception {
for (final EDirection value : EDirection.values()) {
if (value.name().toLowerCase().equals(name)) {
return value;
}
}
throw new Exception("Illegal data access type.");
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import kieker.model.analysismodel.deployment.DeployedComponent;
import kieker.model.analysismodel.deployment.DeployedOperation;
import kieker.model.analysismodel.deployment.DeployedStorage;
import kieker.model.analysismodel.deployment.DeploymentContext;
import kieker.model.analysismodel.deployment.DeploymentModel;
import kieker.model.analysismodel.execution.AggregatedStorageAccess;
import kieker.model.analysismodel.execution.EDirection;
import kieker.model.analysismodel.execution.ExecutionFactory;
import kieker.model.analysismodel.execution.ExecutionModel;
import kieker.model.analysismodel.execution.Tuple;
import kieker.model.analysismodel.sources.SourceModel;
/**
* @author Reiner Jung
*
*/
public class ExecutionModelDataflowAssemblerStage extends AbstractDataflowAssemblerStage<DataAccess, DataAccess> {
private final ExecutionModel executionModel;
private final DeploymentModel deploymentModel;
public ExecutionModelDataflowAssemblerStage(final ExecutionModel executionModel,
final DeploymentModel deploymentModel, final SourceModel sourceModel, final String sourceLabel) {
super(sourceModel, sourceLabel);
this.executionModel = executionModel;
this.deploymentModel = deploymentModel;
}
@Override
protected void execute(final DataAccess element) throws Exception {
final DeploymentContext context = this.deploymentModel.getDeploymentContexts().get(0).getValue();
final DeployedComponent callerComponent = context.getComponents().get(element.getModule());
final DeployedOperation callerOperation = callerComponent.getContainedOperations().get(element.getOperation());
final DeployedStorage accessedStorage = this.findStorage(context, element.getSharedData());
// TODO this must check whether an access already exists.
final Tuple<DeployedOperation, DeployedStorage> key = ExecutionFactory.eINSTANCE.createTuple();
key.setFirst(callerOperation);
key.setSecond(accessedStorage);
AggregatedStorageAccess aggregatedStorageAccess = this.executionModel.getAggregatedStorageAccesses().get(key);
if (aggregatedStorageAccess == null) {
aggregatedStorageAccess = ExecutionFactory.eINSTANCE.createAggregatedStorageAccess();
aggregatedStorageAccess.setCode(callerOperation);
aggregatedStorageAccess.setStorage(accessedStorage);
aggregatedStorageAccess.setDirection(this.convertDirection(element.getDirection()));
this.executionModel.getAggregatedStorageAccesses().put(key, aggregatedStorageAccess);
} else {
final EDirection newDirection = this.convertDirection(element.getDirection());
if (aggregatedStorageAccess.getDirection() == EDirection.READ) {
if ((newDirection == EDirection.WRITE) || (newDirection == EDirection.BOTH)) {
aggregatedStorageAccess.setDirection(EDirection.BOTH);
}
} else if (aggregatedStorageAccess.getDirection() == EDirection.WRITE) {
if ((newDirection == EDirection.READ) || (newDirection == EDirection.BOTH)) {
aggregatedStorageAccess.setDirection(EDirection.BOTH);
}
}
}
}
private EDirection convertDirection(final org.oceandsl.tools.sar.stages.dataflow.EDirection direction) {
switch (direction) {
case READ:
return EDirection.READ;
case WRITE:
return EDirection.WRITE;
case BOTH:
return EDirection.BOTH;
}
return null;
}
private DeployedStorage findStorage(final DeploymentContext context, final String name) {
for (final DeployedComponent component : context.getComponents().values()) {
final DeployedStorage storage = component.getContainedStorages().get(name);
if (storage != null) {
return storage;
}
}
this.logger.error("Internal error. Cannot find storage {}", name);
return null;
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import java.nio.file.Path;
import java.nio.file.Paths;
import teetime.stage.basic.AbstractTransformation;
/**
* @author Reiner Jung
*
*/
public class FileBasedCleanupComponentInDataflowSignatureStage extends AbstractTransformation<DataAccess, DataAccess> {
private final boolean caseInsensitive;
public FileBasedCleanupComponentInDataflowSignatureStage(final boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
@Override
protected void execute(final DataAccess element) throws Exception {
element.setModule(this.convertToLowerCase(this.processComponentSignature(element.getModule())));
this.outputPort.send(element);
}
private String convertToLowerCase(final String string) {
String value;
if (string.endsWith("_")) {
value = string.substring(0, string.length() - 1);
} else {
value = string;
}
return this.caseInsensitive ? value.toLowerCase() : value;
}
private String processComponentSignature(final String signature) {
if ("<<no-file>>".equals(signature)) {
return signature;
} else {
final Path path = Paths.get(signature);
return this.convertToLowerCase(path.getName(path.getNameCount() - 1).toString());
}
}
}
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package org.oceandsl.tools.sar.stages.dataflow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import kieker.model.analysismodel.sources.SourceModel;
import kieker.model.analysismodel.type.ComponentType;
import kieker.model.analysismodel.type.OperationType;
import kieker.model.analysismodel.type.StorageType;
import kieker.model.analysismodel.type.TypeFactory;
import kieker.model.analysismodel.type.TypeModel;
/**
* Add data sorages to the model.
*
* @author Reiner Jung
* @since 1.1
*/
public class TypeModelDataflowAssemblerStage extends AbstractDataflowAssemblerStage<DataAccess, DataAccess> {
static final String GLOBAL_PACKAGE = "global";
private static final String UNKOWN_TYPE = "UNKNOWN";
private final TypeModel typeModel;
private final Map<String, StorageType> storageTypeMap = new HashMap<>();
private final Map<StorageType, List<ComponentType>> storageAccessMap = new HashMap<>();
public TypeModelDataflowAssemblerStage(final TypeModel typeModel, final SourceModel sourceModel,
final String sourceLabel) {
super(sourceModel, sourceLabel);
this.typeModel = typeModel;
}
@Override
protected void execute(final DataAccess element) throws Exception {
final OperationType operation = this.findOperation(element);
final StorageType type = this.findOrCreateDataStorage(element, operation.getComponentType());
this.addObjectToSource(type);
this.outputPort.send(element);
}
private StorageType findOrCreateDataStorage(final DataAccess element, final ComponentType componentType) {
StorageType type = this.storageTypeMap.get(element.getSharedData());
if (type == null) {
type = TypeFactory.eINSTANCE.createStorageType();
type.setName(element.getSharedData());
type.setType(TypeModelDataflowAssemblerStage.UNKOWN_TYPE);
componentType.getProvidedStorages().put(type.getName(), type);
this.storageTypeMap.put(type.getName(), type);
final List<ComponentType> newList = new ArrayList<>();
newList.add(componentType);
this.storageAccessMap.put(type, newList);
} else {
final List<ComponentType> accessedByList = this.storageAccessMap.get(type);
if (!accessedByList.contains(componentType)) {
if (accessedByList.size() == 1) {
this.moveStorageAccessToSeparateComponent(type, accessedByList.get(0));
}
accessedByList.add(componentType);
this.storageAccessMap.put(type, accessedByList);
}
}
return type;
}
private void moveStorageAccessToSeparateComponent(final StorageType storageType,
final ComponentType componentType) {
componentType.getProvidedStorages().removeKey(storageType.getName());
final ComponentType newComponentType = TypeFactory.eINSTANCE.createComponentType();
newComponentType.setName(storageType.getName());
newComponentType.setPackage(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
newComponentType.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + storageType.getName());
newComponentType.getProvidedStorages().put(storageType.getName(), storageType);
this.addObjectToSource(newComponentType);
this.typeModel.getComponentTypes().put(newComponentType.getSignature(), newComponentType);
}
private OperationType findOperation(final DataAccess element) {
ComponentType componentType = this.typeModel.getComponentTypes().get(element.getModule());
if (componentType == null) {
componentType = TypeFactory.eINSTANCE.createComponentType();
componentType.setName(element.getModule());
componentType.setSignature(element.getModule());
componentType.setPackage(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
this.typeModel.getComponentTypes().put(element.getModule(), componentType);
final OperationType operationType = this.createOperation(element.getOperation());
componentType.getProvidedOperations().put(element.getOperation(), operationType);
return operationType;
} else {
for (final OperationType operation : componentType.getProvidedOperations().values()) {
if (operation.getName().equals(element.getOperation())) {
return operation;
}
}
final OperationType operationType = this.createOperation(element.getOperation());
componentType.getProvidedOperations().put(element.getOperation(), operationType);
return operationType;
}
}
private OperationType createOperation(final String operation) {
final OperationType operationType = TypeFactory.eINSTANCE.createOperationType();
operationType.setName(operation);
operationType.setReturnType("unknown");
operationType.setSignature(operation);
return operationType;
}
}
package org.oceandsl.tools.sar.stages.dataflow;
\ No newline at end of file
/***************************************************************************
* Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
/**
* @author Reiner Jung
*
*/
package org.oceandsl.tools.sar.stages;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment