Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to ArCoTL to load ACM Code File directly #4

Merged
merged 4 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import java.io.File;
import java.util.SortedMap;

import edu.kit.kastel.mcse.ardoco.core.execution.ArDoCo;
import edu.kit.kastel.mcse.ardoco.tlr.codetraceability.SadCodeTraceabilityLinkRecovery;
import edu.kit.kastel.mcse.ardoco.core.common.util.CommonUtilities;
import edu.kit.kastel.mcse.ardoco.core.common.util.DataRepositoryHelper;
import edu.kit.kastel.mcse.ardoco.tlr.connectiongenerator.ConnectionGenerator;
import edu.kit.kastel.mcse.ardoco.core.execution.ArDoCo;
import edu.kit.kastel.mcse.ardoco.core.execution.runner.ArDoCoRunner;
import edu.kit.kastel.mcse.ardoco.tlr.codetraceability.SadCodeTraceabilityLinkRecovery;
import edu.kit.kastel.mcse.ardoco.tlr.connectiongenerator.ConnectionGenerator;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArCoTLModelProviderAgent;
import edu.kit.kastel.mcse.ardoco.tlr.recommendationgenerator.RecommendationGenerator;
import edu.kit.kastel.mcse.ardoco.tlr.text.providers.TextPreprocessingAgent;
Expand All @@ -36,7 +36,9 @@ private void definePipeline(File inputText, File inputCode, SortedMap<String, St
throw new IllegalArgumentException("Cannot deal with empty input text. Maybe there was an error reading the file.");
}
DataRepositoryHelper.putInputText(dataRepository, text);
ArCoTLModelProviderAgent arCoTLModelProviderAgent = ArCoTLModelProviderAgent.get(null, null, inputCode, additionalConfigs, dataRepository);
var codeConfiguration = ArCoTLModelProviderAgent.getCodeConfiguration(inputCode);
ArCoTLModelProviderAgent arCoTLModelProviderAgent = ArCoTLModelProviderAgent.getArCoTLModelProviderAgent(dataRepository, additionalConfigs, null,
codeConfiguration);
arDoCo.addPipelineStep(arCoTLModelProviderAgent);

arDoCo.addPipelineStep(TextPreprocessingAgent.get(additionalConfigs, dataRepository));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
import java.util.SortedMap;

import edu.kit.kastel.mcse.ardoco.core.api.models.ArchitectureModelType;
import edu.kit.kastel.mcse.ardoco.core.common.util.CommonUtilities;
import edu.kit.kastel.mcse.ardoco.core.common.util.DataRepositoryHelper;
import edu.kit.kastel.mcse.ardoco.core.execution.ArDoCo;
import edu.kit.kastel.mcse.ardoco.core.execution.runner.ArDoCoRunner;
import edu.kit.kastel.mcse.ardoco.tlr.codetraceability.SadSamCodeTraceabilityLinkRecovery;
import edu.kit.kastel.mcse.ardoco.tlr.codetraceability.SamCodeTraceabilityLinkRecovery;
import edu.kit.kastel.mcse.ardoco.core.common.util.CommonUtilities;
import edu.kit.kastel.mcse.ardoco.core.common.util.DataRepositoryHelper;
import edu.kit.kastel.mcse.ardoco.tlr.connectiongenerator.ConnectionGenerator;
import edu.kit.kastel.mcse.ardoco.core.execution.runner.ArDoCoRunner;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArCoTLModelProviderAgent;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArchitectureConfiguration;
import edu.kit.kastel.mcse.ardoco.tlr.recommendationgenerator.RecommendationGenerator;
import edu.kit.kastel.mcse.ardoco.tlr.text.providers.TextPreprocessingAgent;
import edu.kit.kastel.mcse.ardoco.tlr.textextraction.TextExtraction;
Expand Down Expand Up @@ -43,8 +44,11 @@ private void definePipeline(File inputText, File inputArchitectureModel, Archite

arDoCo.addPipelineStep(TextPreprocessingAgent.get(additionalConfigs, dataRepository));

ArCoTLModelProviderAgent arCoTLModelProviderAgent = ArCoTLModelProviderAgent.get(inputArchitectureModel, architectureModelType, inputCode,
additionalConfigs, dataRepository);
var architectureConfiguration = new ArchitectureConfiguration(inputArchitectureModel, architectureModelType);
var codeConfiguration = ArCoTLModelProviderAgent.getCodeConfiguration(inputCode);

ArCoTLModelProviderAgent arCoTLModelProviderAgent = ArCoTLModelProviderAgent.getArCoTLModelProviderAgent(dataRepository, additionalConfigs,
architectureConfiguration, codeConfiguration);
arDoCo.addPipelineStep(arCoTLModelProviderAgent);

arDoCo.addPipelineStep(TextExtraction.get(additionalConfigs, dataRepository));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import edu.kit.kastel.mcse.ardoco.core.api.models.ArchitectureModelType;
import edu.kit.kastel.mcse.ardoco.core.common.util.CommonUtilities;
import edu.kit.kastel.mcse.ardoco.core.common.util.DataRepositoryHelper;
import edu.kit.kastel.mcse.ardoco.tlr.connectiongenerator.ConnectionGenerator;
import edu.kit.kastel.mcse.ardoco.core.execution.runner.ArDoCoRunner;
import edu.kit.kastel.mcse.ardoco.tlr.connectiongenerator.ConnectionGenerator;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArCoTLModelProviderAgent;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArchitectureConfiguration;
import edu.kit.kastel.mcse.ardoco.tlr.recommendationgenerator.RecommendationGenerator;
import edu.kit.kastel.mcse.ardoco.tlr.text.providers.TextPreprocessingAgent;
import edu.kit.kastel.mcse.ardoco.tlr.textextraction.TextExtraction;
Expand Down Expand Up @@ -41,8 +42,10 @@ private void definePipeline(File inputText, File inputArchitectureModel, Archite
DataRepositoryHelper.putInputText(dataRepository, text);

this.getArDoCo().addPipelineStep(TextPreprocessingAgent.get(additionalConfigs, dataRepository));

var architectureConfiguration = new ArchitectureConfiguration(inputArchitectureModel, architectureModelType);
ArCoTLModelProviderAgent arCoTLModelProviderAgent = //
ArCoTLModelProviderAgent.get(inputArchitectureModel, architectureModelType, null, additionalConfigs, dataRepository);
ArCoTLModelProviderAgent.getArCoTLModelProviderAgent(dataRepository, additionalConfigs, architectureConfiguration, null);
this.getArDoCo().addPipelineStep(arCoTLModelProviderAgent);

this.getArDoCo().addPipelineStep(TextExtraction.get(additionalConfigs, dataRepository));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

import edu.kit.kastel.mcse.ardoco.core.api.models.ArchitectureModelType;
import edu.kit.kastel.mcse.ardoco.core.execution.ArDoCo;
import edu.kit.kastel.mcse.ardoco.tlr.codetraceability.SamCodeTraceabilityLinkRecovery;
import edu.kit.kastel.mcse.ardoco.core.execution.runner.ArDoCoRunner;
import edu.kit.kastel.mcse.ardoco.tlr.codetraceability.SamCodeTraceabilityLinkRecovery;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArCoTLModelProviderAgent;
import edu.kit.kastel.mcse.ardoco.tlr.models.agents.ArchitectureConfiguration;

public class ArDoCoForSamCodeTraceabilityLinkRecovery extends ArDoCoRunner {

Expand All @@ -28,8 +29,11 @@ private void definePipeline(File inputArchitectureModel, ArchitectureModelType a
ArDoCo arDoCo = this.getArDoCo();
var dataRepository = arDoCo.getDataRepository();

ArCoTLModelProviderAgent arCoTLModelProviderAgent = ArCoTLModelProviderAgent.get(inputArchitectureModel, architectureModelType, inputCode,
additionalConfigs, dataRepository);
var codeConfiguration = ArCoTLModelProviderAgent.getCodeConfiguration(inputCode);
var architectureConfiguration = new ArchitectureConfiguration(inputArchitectureModel, architectureModelType);

ArCoTLModelProviderAgent arCoTLModelProviderAgent = ArCoTLModelProviderAgent.getArCoTLModelProviderAgent(dataRepository, additionalConfigs,
architectureConfiguration, codeConfiguration);
arDoCo.addPipelineStep(arCoTLModelProviderAgent);
arDoCo.addPipelineStep(SamCodeTraceabilityLinkRecovery.get(additionalConfigs, dataRepository));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,13 @@
import java.util.List;
import java.util.SortedMap;

import edu.kit.kastel.mcse.ardoco.core.api.models.ArchitectureModelType;
import edu.kit.kastel.mcse.ardoco.core.api.models.arcotl.code.CodeItemRepository;
import org.slf4j.LoggerFactory;

import edu.kit.kastel.mcse.ardoco.core.data.DataRepository;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.Extractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.architecture.ArchitectureExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.architecture.pcm.PcmExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.architecture.uml.UmlExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.code.AllLanguagesExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.code.CodeExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.informants.ArCoTLModelProviderInformant;
import edu.kit.kastel.mcse.ardoco.core.pipeline.agent.Informant;
import edu.kit.kastel.mcse.ardoco.core.pipeline.agent.PipelineAgent;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.Extractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.informants.ArCoTLModelProviderInformant;

/**
* Agent that provides information from models.
Expand All @@ -27,42 +22,43 @@ public class ArCoTLModelProviderAgent extends PipelineAgent {
/**
* Instantiates a new model provider agent.
* The constructor takes a list of ModelConnectors that are executed and used to extract information from models.
* You can specify the extractors xor the code model file.
*
* @param data the DataRepository
* @param extractors the list of ModelConnectors that should be used
* @param data the DataRepository
* @param architectureConfiguration the architecture configuration
* @param codeConfiguration the code configuration
*/
public ArCoTLModelProviderAgent(DataRepository data, List<Extractor> extractors) {
super(informants(data, extractors), ArCoTLModelProviderAgent.class.getSimpleName(), data);
public ArCoTLModelProviderAgent(DataRepository data, ArchitectureConfiguration architectureConfiguration, CodeConfiguration codeConfiguration) {
super(informants(data, architectureConfiguration, codeConfiguration), ArCoTLModelProviderAgent.class.getSimpleName(), data);
}

private static List<? extends Informant> informants(DataRepository data, List<Extractor> extractors) {
return extractors.stream().map(e -> new ArCoTLModelProviderInformant(data, e)).toList();
}

public static ArCoTLModelProviderAgent get(File inputArchitectureModel, ArchitectureModelType architectureModelType, File inputCode,
SortedMap<String, String> additionalConfigs, DataRepository dataRepository) {

List<Extractor> extractors = new ArrayList<>();
private static List<? extends Informant> informants(DataRepository data, ArchitectureConfiguration architectureConfiguration,
CodeConfiguration codeConfiguration) {
List<Informant> informants = new ArrayList<>();
if (architectureConfiguration != null) {
informants.add(new ArCoTLModelProviderInformant(data, architectureConfiguration.extractor()));
}

if (inputArchitectureModel != null && architectureModelType != null) {
ArchitectureExtractor architectureExtractor = switch (architectureModelType) {
case PCM -> new PcmExtractor(inputArchitectureModel.getAbsolutePath());
case UML -> new UmlExtractor(inputArchitectureModel.getAbsolutePath());
};
extractors.add(architectureExtractor);
if (codeConfiguration != null && codeConfiguration.type() == CodeConfiguration.CodeConfigurationType.ACM_FILE) {
informants.add(new ArCoTLModelProviderInformant(data, codeConfiguration.code()));
}

if (inputCode != null) {
CodeItemRepository codeItemRepository = new CodeItemRepository();
CodeExtractor codeExtractor = new AllLanguagesExtractor(codeItemRepository, inputCode.getAbsolutePath());
extractors.add(codeExtractor);
if (codeConfiguration != null && codeConfiguration.type() == CodeConfiguration.CodeConfigurationType.DIRECTORY) {
for (Extractor e : codeConfiguration.extractors()) {
informants.add(new ArCoTLModelProviderInformant(data, e));
}
}

if (extractors.isEmpty()) {
throw new IllegalArgumentException("No model extractor was provided.");
return informants;
}

public static ArCoTLModelProviderAgent getArCoTLModelProviderAgent(DataRepository dataRepository, SortedMap<String, String> additionalConfigs,
ArchitectureConfiguration architectureConfiguration, CodeConfiguration codeConfiguration) {
if (architectureConfiguration == null && codeConfiguration == null) {
throw new IllegalArgumentException("At least one configuration must be provided");
}

ArCoTLModelProviderAgent agent = new ArCoTLModelProviderAgent(dataRepository, extractors);
var agent = new ArCoTLModelProviderAgent(dataRepository, architectureConfiguration, codeConfiguration);
agent.applyConfiguration(additionalConfigs);
return agent;
}
Expand All @@ -71,4 +67,24 @@ public static ArCoTLModelProviderAgent get(File inputArchitectureModel, Architec
protected void delegateApplyConfigurationToInternalObjects(SortedMap<String, String> additionalConfiguration) {
// empty
}

public static CodeConfiguration getCodeConfiguration(File inputCode) {
if (inputCode == null) {
throw new IllegalArgumentException("Code file must not be null");
}

if (inputCode.isFile()) {
return new CodeConfiguration(inputCode, CodeConfiguration.CodeConfigurationType.ACM_FILE);
}

// Legacy Support for only ACM_FILE in a directory
// TODO: Maybe delete in the future
if (inputCode.isDirectory() && new File(inputCode, "codeModel.acm").exists()) {
var logger = LoggerFactory.getLogger(ArCoTLModelProviderAgent.class);
logger.error("Legacy support for only ACM_FILE in a directory. Please use the ACM_FILE directly.");
return new CodeConfiguration(new File(inputCode, "codeModel.acm"), CodeConfiguration.CodeConfigurationType.ACM_FILE);
}

return new CodeConfiguration(inputCode, CodeConfiguration.CodeConfigurationType.DIRECTORY);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Licensed under MIT 2024. */
package edu.kit.kastel.mcse.ardoco.tlr.models.agents;

import java.io.File;

import edu.kit.kastel.mcse.ardoco.core.api.models.ArchitectureModelType;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.Extractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.architecture.pcm.PcmExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.architecture.uml.UmlExtractor;

public record ArchitectureConfiguration(File architectureFile, ArchitectureModelType type) {
public ArchitectureConfiguration {
if (architectureFile == null || type == null) {
throw new IllegalArgumentException("Architecture file and type must not be null");
}
if (!architectureFile.exists() || !architectureFile.isFile()) {
throw new IllegalArgumentException("Architecture file must exist and be a file");
}
}

public Extractor extractor() {
return switch (type) {
case PCM -> new PcmExtractor(architectureFile.getAbsolutePath());
case UML -> new UmlExtractor(architectureFile.getAbsolutePath());
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* Licensed under MIT 2024. */
package edu.kit.kastel.mcse.ardoco.tlr.models.agents;

import java.io.File;
import java.util.List;

import edu.kit.kastel.mcse.ardoco.core.api.models.arcotl.code.CodeItemRepository;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.Extractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.code.AllLanguagesExtractor;
import edu.kit.kastel.mcse.ardoco.tlr.models.connectors.generators.code.CodeExtractor;

public record CodeConfiguration(File code, CodeConfigurationType type) {

public CodeConfiguration {
if (code == null || type == null) {
throw new IllegalArgumentException("Code file and type must not be null");
}

if (!code.exists()) {
throw new IllegalArgumentException("Code file must exist");
}

if (type == CodeConfigurationType.DIRECTORY && code.isFile()) {
throw new IllegalArgumentException("Code file must be a directory in DIRECTORY mode");
}

if (type == CodeConfigurationType.ACM_FILE && !code.isFile()) {
throw new IllegalArgumentException("Code file must be a file in ACM_FILE mode");
}
}

public List<Extractor> extractors() {
if (type == CodeConfigurationType.DIRECTORY) {
CodeItemRepository codeItemRepository = new CodeItemRepository();
CodeExtractor codeExtractor = new AllLanguagesExtractor(codeItemRepository, code.getAbsolutePath());
return List.of(codeExtractor);
}
throw new IllegalStateException("CodeConfigurationType not supported");
}

public enum CodeConfigurationType {
DIRECTORY, ACM_FILE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ public void writeOutCodeModel(CodeModel codeModel) {
writeOutCodeModel(codeModel, file);
}

public CodeModel readInCodeModel() {
File codeModelFile = new File(this.getCodeModelFileString());
return readInCodeModel(codeModelFile);
}

public static CodeModel readInCodeModel(File codeModelFile) {
if (codeModelFile != null && codeModelFile.isFile()) {
logger.info("Reading in existing code model.");
Expand Down
Loading
Loading