From afe9aeaf19891bbfa3cfac02bae95b3c592e7676 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 23 Dec 2021 12:15:38 +0100 Subject: [PATCH 01/46] feat[DE]: Add AnnotationSchema --- .../Annotations/AnnotationSchemaService.cs | 111 ++++++++++++++ .../Annotations/IAnnotationSchemaService.cs | 22 +++ .../Annotations/Model/CodeSmellDefinition.cs | 46 ++++++ .../Annotations/Model/CodeSmellHeuristic.cs | 22 +++ .../Annotations/Model/Heuristic.cs | 28 ++++ .../AnnotationSchemaDatabaseRepository.cs | 88 +++++++++++ .../Repository/IAnnotationSchemaRepository.cs | 19 +++ .../Annotations/Model/SeverityRange.cs | 21 +++ .../Annotations/AnnotationSchemaController.cs | 143 ++++++++++++++++++ .../DTOs/CodeSmellDefinitionDTO.cs | 14 ++ .../Annotations/DTOs/HeuristicDTO.cs | 9 ++ .../Annotations/DTOs/SeverityRangeDTO.cs | 9 ++ .../Annotations/Mappers/AnnotationProfile.cs | 4 + .../Database/DataSetExplorerContext.cs | 11 ++ DataSetExplorer/Startup.cs | 3 + 15 files changed, 550 insertions(+) create mode 100644 DataSetExplorer/Annotations/AnnotationSchemaService.cs create mode 100644 DataSetExplorer/Annotations/IAnnotationSchemaService.cs create mode 100644 DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs create mode 100644 DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs create mode 100644 DataSetExplorer/Annotations/Model/Heuristic.cs create mode 100644 DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs create mode 100644 DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs create mode 100644 DataSetExplorer/Annotations/Model/SeverityRange.cs create mode 100644 DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs create mode 100644 DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs create mode 100644 DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs create mode 100644 DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs diff --git a/DataSetExplorer/Annotations/AnnotationSchemaService.cs b/DataSetExplorer/Annotations/AnnotationSchemaService.cs new file mode 100644 index 00000000..780ffc0c --- /dev/null +++ b/DataSetExplorer/Annotations/AnnotationSchemaService.cs @@ -0,0 +1,111 @@ +using DataSetExplorer.Annotations.Model; +using DataSetExplorer.Annotations.Model.Repository; +using FluentResults; +using System.Collections.Generic; + +namespace DataSetExplorer.Annotations +{ + public class AnnotationSchemaService : IAnnotationSchemaService + { + private readonly IAnnotationSchemaRepository _annotationSchemaRepository; + + public AnnotationSchemaService(IAnnotationSchemaRepository annotationSchemaRepository) + { + _annotationSchemaRepository = annotationSchemaRepository; + } + + public Result GetCodeSmellDefinition(int id) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + return Result.Ok(codeSmellDefinition); + } + + public Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) + { + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + return Result.Ok(codeSmellDefinition); + } + + public Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + foreach (var h in heuristics) + { + var heuristic = _annotationSchemaRepository.GetHeuristic(h.Id); + if (heuristic == default) return Result.Fail($"Heuristic with id: {id} does not exist."); + } + + foreach (var h in heuristics) + { + var heuristic = _annotationSchemaRepository.GetHeuristic(h.Id); + var codeSmellHeuristic = new CodeSmellHeuristic(codeSmellDefinition, heuristic); + _annotationSchemaRepository.SaveCodeSmellHeuristic(codeSmellHeuristic); + } + + return Result.Ok(heuristics); + } + + public Result> GetHeuristicsForCodeSmell(int id) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + + IEnumerable heuristics = _annotationSchemaRepository.GetHeuristicsForCodeSmell(id); + return Result.Ok(heuristics); + } + + public Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) + { + var codeSmellHeuristic = _annotationSchemaRepository.DeleteHeuristicFromCodeSmell(smellId, heuristicId); + return Result.Ok(codeSmellHeuristic); + } + + public Result> GetAllCodeSmellDefinitions() + { + return Result.Ok(_annotationSchemaRepository.GetAllCodeSmellDefinitions()); + } + + public Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition) + { + var existingCodeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (existingCodeSmellDefinition == default) return Result.Fail($"CodeSmellDefinition with id: {id} does not exist."); + existingCodeSmellDefinition.Update(codeSmellDefinition); + _annotationSchemaRepository.SaveCodeSmellDefinition(existingCodeSmellDefinition); + return Result.Ok(codeSmellDefinition); + } + + public Result DeleteCodeSmellDefinition(int id) + { + var codeSmellDefinition = _annotationSchemaRepository.DeleteCodeSmellDefinition(id); + return Result.Ok(codeSmellDefinition); + } + + public Result> GetAllHeuristics() + { + return Result.Ok(_annotationSchemaRepository.GetAllHeuristics()); + } + + public Result UpdateHeuristic(int id, Heuristic heuristic) + { + var existingHeuristic = _annotationSchemaRepository.GetHeuristic(id); + if (existingHeuristic == default) return Result.Fail($"Heuristic with id: {id} does not exist."); + existingHeuristic.Update(heuristic); + _annotationSchemaRepository.SaveHeuristic(existingHeuristic); + return Result.Ok(heuristic); + } + + public Result DeleteHeuristic(int id) + { + var heuristic = _annotationSchemaRepository.DeleteHeuristic(id); + return Result.Ok(heuristic); + } + + public Result CreateHeuristic(Heuristic heuristic) + { + _annotationSchemaRepository.SaveHeuristic(heuristic); + return Result.Ok(heuristic); + } + } +} diff --git a/DataSetExplorer/Annotations/IAnnotationSchemaService.cs b/DataSetExplorer/Annotations/IAnnotationSchemaService.cs new file mode 100644 index 00000000..3001c587 --- /dev/null +++ b/DataSetExplorer/Annotations/IAnnotationSchemaService.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using DataSetExplorer.Annotations.Model; +using FluentResults; + +namespace DataSetExplorer.Annotations +{ + public interface IAnnotationSchemaService + { + Result GetCodeSmellDefinition(int id); + Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); + Result> GetAllCodeSmellDefinitions(); + Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition); + Result DeleteCodeSmellDefinition(int id); + Result> GetAllHeuristics(); + Result CreateHeuristic(Heuristic heuristic); + Result UpdateHeuristic(int id, Heuristic heuristic); + Result DeleteHeuristic(int id); + Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics); + Result> GetHeuristicsForCodeSmell(int id); + Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); + } +} diff --git a/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs b/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs new file mode 100644 index 00000000..8bfae4a6 --- /dev/null +++ b/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using DataSetExplorer.DataSets.Model; + +namespace DataSetExplorer.Annotations.Model +{ + public class CodeSmellDefinition + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public SnippetType SnippetType { get; set; } + public SeverityRange SeverityRange { get; set; } + public List SeverityValues { get; set; } + public ICollection CodeSmellHeuristics { get; set; } + + public CodeSmellDefinition(string name, string description, SnippetType snippetType) + { + Name = name; + Description = description; + SnippetType = snippetType; + } + + private CodeSmellDefinition() + { + } + + public void Update(CodeSmellDefinition other) + { + Name = other.Name; + Description = other.Description; + SnippetType = other.SnippetType; + SeverityRange = other.SeverityRange; + SeverityValues = other.SeverityValues; + } + + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + public override bool Equals(object other) + { + return other is CodeSmellDefinition smell && Name.Equals(smell.Name); + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs b/DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs new file mode 100644 index 00000000..6b929adf --- /dev/null +++ b/DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs @@ -0,0 +1,22 @@ +namespace DataSetExplorer.Annotations.Model +{ + public class CodeSmellHeuristic + { + public int CodeSmellDefinitionId { get; set; } + public CodeSmellDefinition CodeSmellDefinition { get; set; } + public int HeuristicId { get; set; } + public Heuristic Heuristic { get; set; } + + public CodeSmellHeuristic(CodeSmellDefinition codeSmellDefinition, Heuristic heuristic) + { + CodeSmellDefinition = codeSmellDefinition; + CodeSmellDefinitionId = codeSmellDefinition.Id; + Heuristic = heuristic; + HeuristicId = heuristic.Id; + } + + public CodeSmellHeuristic() + { + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Annotations/Model/Heuristic.cs b/DataSetExplorer/Annotations/Model/Heuristic.cs new file mode 100644 index 00000000..9185bbcb --- /dev/null +++ b/DataSetExplorer/Annotations/Model/Heuristic.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace DataSetExplorer.Annotations.Model +{ + public class Heuristic + { + public int Id { get; private set; } + public string Name { get; set; } + public string Description { get; set; } + public ICollection CodeSmellHeuristics { get; set; } + + public Heuristic(string name, string description) + { + Name = name; + Description = description; + } + + private Heuristic() + { + } + + public void Update(Heuristic other) + { + Name = other.Name; + Description = other.Description; + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs new file mode 100644 index 00000000..2564e4c7 --- /dev/null +++ b/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Linq; +using DataSetExplorer.Database; +using Microsoft.EntityFrameworkCore; + +namespace DataSetExplorer.Annotations.Model.Repository +{ + public class AnnotationSchemaDatabaseRepository : IAnnotationSchemaRepository + { + private readonly DataSetExplorerContext _dbContext; + + public AnnotationSchemaDatabaseRepository(DataSetExplorerContext dbContext) + { + _dbContext = dbContext; + } + + public CodeSmellDefinition GetCodeSmellDefinition(int id) + { + return _dbContext.CodeSmellDefinitions + .Include(c => c.SeverityRange) + .FirstOrDefault(c => c.Id == id); + } + + public void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) + { + _dbContext.Update(codeSmellDefinition); + _dbContext.SaveChanges(); + } + + public void SaveCodeSmellHeuristic(CodeSmellHeuristic codeSmellHeuristic) + { + _dbContext.Add(codeSmellHeuristic); + _dbContext.SaveChanges(); + } + + public IEnumerable GetHeuristicsForCodeSmell(int id) + { + return _dbContext.Heuristics.Where(h => h.CodeSmellHeuristics.Any(ch => ch.CodeSmellDefinitionId == id)); + } + + public CodeSmellHeuristic DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) + { + var codeSmellHeuristic = _dbContext.CodeSmellHeuristics + .First(ch => ch.CodeSmellDefinitionId == smellId && ch.HeuristicId == heuristicId); + + _dbContext.Remove(codeSmellHeuristic); + _dbContext.SaveChanges(); + return codeSmellHeuristic; + } + + public IEnumerable GetAllCodeSmellDefinitions() + { + return _dbContext.CodeSmellDefinitions + .Include(c => c.SeverityRange); + } + + public CodeSmellDefinition DeleteCodeSmellDefinition(int id) + { + var deletedCodeSmell = _dbContext.CodeSmellDefinitions.Remove(_dbContext.CodeSmellDefinitions.Find(id)).Entity; + _dbContext.SaveChanges(); + return deletedCodeSmell; + } + + public IEnumerable GetAllHeuristics() + { + return _dbContext.Heuristics; + } + + public Heuristic DeleteHeuristic(int id) + { + var deletedHeuristic = _dbContext.Heuristics.Remove(_dbContext.Heuristics.Find(id)).Entity; + _dbContext.SaveChanges(); + return deletedHeuristic; + } + + public void SaveHeuristic(Heuristic heuristic) + { + _dbContext.Update(heuristic); + _dbContext.SaveChanges(); + } + + public Heuristic GetHeuristic(int id) + { + return _dbContext.Heuristics + .FirstOrDefault(h => h.Id == id); + } + } +} diff --git a/DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs new file mode 100644 index 00000000..51235e15 --- /dev/null +++ b/DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace DataSetExplorer.Annotations.Model.Repository +{ + public interface IAnnotationSchemaRepository + { + CodeSmellDefinition GetCodeSmellDefinition(int id); + void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); + IEnumerable GetAllCodeSmellDefinitions(); + CodeSmellDefinition DeleteCodeSmellDefinition(int id); + IEnumerable GetAllHeuristics(); + Heuristic DeleteHeuristic(int id); + void SaveHeuristic(Heuristic heuristic); + Heuristic GetHeuristic(int id); + void SaveCodeSmellHeuristic(CodeSmellHeuristic codeSmellHeuristic); + IEnumerable GetHeuristicsForCodeSmell(int id); + CodeSmellHeuristic DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); + } +} diff --git a/DataSetExplorer/Annotations/Model/SeverityRange.cs b/DataSetExplorer/Annotations/Model/SeverityRange.cs new file mode 100644 index 00000000..55f30db4 --- /dev/null +++ b/DataSetExplorer/Annotations/Model/SeverityRange.cs @@ -0,0 +1,21 @@ +namespace DataSetExplorer.Annotations.Model +{ + public class SeverityRange + { + public int Id { get; private set; } + public double MinValue { get; set; } + public double MaxValue { get; set; } + public double Step { get; set; } + + public SeverityRange(double minValue, double maxValue, double step) + { + MinValue = minValue; + MaxValue = maxValue; + Step = step; + } + + private SeverityRange() + { + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs b/DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs new file mode 100644 index 00000000..4e795bef --- /dev/null +++ b/DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs @@ -0,0 +1,143 @@ +using System.Collections.Generic; +using AutoMapper; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using DataSetExplorer.Annotations; +using DataSetExplorer.Annotations.Model; +using DataSetExplorer.Controllers.Annotations.DTOs; + +namespace DataSetExplorer.Controllers.Annotations +{ + [Route("api/annotation-schema/")] + [ApiController] + public class AnnotationSchemaController : ControllerBase + { + private readonly IMapper _mapper; + private readonly IConfiguration _configuration; + private readonly IAnnotationSchemaService _annotationSchemaService; + + public AnnotationSchemaController(IMapper mapper, IConfiguration configuration, IAnnotationSchemaService annotationSchemaService) + { + _mapper = mapper; + _configuration = configuration; + _annotationSchemaService = annotationSchemaService; + } + + [HttpGet] + [Route("code-smell-definition")] + public IActionResult GetAllCodeSmellDefinitions() + { + var result = _annotationSchemaService.GetAllCodeSmellDefinitions(); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpGet] + [Route("{id}")] + public IActionResult GetCodeSmellDefinition([FromRoute] int id) + { + var result = _annotationSchemaService.GetCodeSmellDefinition(id); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPost] + [Route("code-smell-definition")] + public IActionResult CreateCodeSmellDefinition([FromBody] CodeSmellDefinitionDTO codeSmellDefinitionDto) + { + var codeSmellDefinition = _mapper.Map(codeSmellDefinitionDto); + var result = _annotationSchemaService.CreateCodeSmellDefinition(codeSmellDefinition); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPost] + [Route("code-smell-definition/{id}/heuristic")] + public IActionResult AddHeuristicsToCodeSmell([FromRoute] int id, [FromBody] List heuristicsDto) + { + var heuristics = new List(); + foreach (var heuristic in heuristicsDto) + { + heuristics.Add(_mapper.Map(heuristic)); + } + var result = _annotationSchemaService.AddHeuristicsToCodeSmell(id, heuristics); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpDelete] + [Route("code-smell-definition/{smellId}/heuristic/{heuristicId}")] + public IActionResult RemoveHeuristicFromCodeSmell([FromRoute] int smellId, [FromRoute] int heuristicId) + { + var result = _annotationSchemaService.DeleteHeuristicFromCodeSmell(smellId, heuristicId); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpGet] + [Route("code-smell-definition/{id}/heuristic")] + public IActionResult GetHeuristicsForCodeSmell([FromRoute] int id) + { + var result = _annotationSchemaService.GetHeuristicsForCodeSmell(id); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPut] + [Route("code-smell-definition/{id}")] + public IActionResult UpdateCodeSmellDefinition([FromRoute] int id, [FromBody] CodeSmellDefinitionDTO codeSmellDefinitionDto) + { + var codeSmellDefinition = _mapper.Map(codeSmellDefinitionDto); + var result = _annotationSchemaService.UpdateCodeSmellDefinition(id, codeSmellDefinition); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpDelete] + [Route("code-smell-definition/{id}")] + public IActionResult DeleteCodeSmellDefinition([FromRoute] int id) + { + var result = _annotationSchemaService.DeleteCodeSmellDefinition(id); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpGet] + [Route("heuristic")] + public IActionResult GetAllHeuristics() + { + var result = _annotationSchemaService.GetAllHeuristics(); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPut] + [Route("heuristic/{id}")] + public IActionResult UpdateHeuristic([FromRoute] int id, [FromBody] HeuristicDTO heuristicDto) + { + var heuristic = _mapper.Map(heuristicDto); + var result = _annotationSchemaService.UpdateHeuristic(id, heuristic); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpDelete] + [Route("heuristic/{id}")] + public IActionResult DeleteHeuristic([FromRoute] int id) + { + var result = _annotationSchemaService.DeleteHeuristic(id); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPost] + [Route("heuristic")] + public IActionResult CreateHeuristic([FromBody] HeuristicDTO heuristicDto) + { + var heuristic = _mapper.Map(heuristicDto); + var result = _annotationSchemaService.CreateHeuristic(heuristic); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + } +} diff --git a/DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs b/DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs new file mode 100644 index 00000000..545d4e2b --- /dev/null +++ b/DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace DataSetExplorer.Controllers.Annotations.DTOs +{ + public class CodeSmellDefinitionDTO + { + public string Name { get; set; } + public string Description { get; set; } + public string SnippetType { get; set; } + public List Heuristics { get; set; } + public SeverityRangeDTO SeverityRange { get; set; } + public List SeverityValues { get; set; } + } +} diff --git a/DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs b/DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs new file mode 100644 index 00000000..028e4524 --- /dev/null +++ b/DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs @@ -0,0 +1,9 @@ +namespace DataSetExplorer.Controllers.Annotations.DTOs +{ + public class HeuristicDTO + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } +} diff --git a/DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs b/DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs new file mode 100644 index 00000000..27ca7da1 --- /dev/null +++ b/DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs @@ -0,0 +1,9 @@ +namespace DataSetExplorer.Controllers.Annotations.DTOs +{ + public class SeverityRangeDTO + { + public double MinValue { get; set; } + public double MaxValue { get; set; } + public double Step { get; set; } + } +} diff --git a/DataSetExplorer/Controllers/Annotations/Mappers/AnnotationProfile.cs b/DataSetExplorer/Controllers/Annotations/Mappers/AnnotationProfile.cs index f0fd888f..0a989d3d 100644 --- a/DataSetExplorer/Controllers/Annotations/Mappers/AnnotationProfile.cs +++ b/DataSetExplorer/Controllers/Annotations/Mappers/AnnotationProfile.cs @@ -2,6 +2,7 @@ using DataSetExplorer.DataSets.Model; using DataSetExplorer.Controllers.Annotations.DTOs; using System.Collections.Generic; +using DataSetExplorer.Annotations.Model; namespace DataSetExplorer.Controllers.Annotations.Mappers { @@ -12,6 +13,9 @@ public AnnotationProfile() CreateMap() .IgnoreAllPropertiesWithAnInaccessibleSetter() .ConstructUsing(src => new Annotation(src.CodeSmell, src.Severity, new Annotator(src.AnnotatorId), CreateHeuristics(src.ApplicableHeuristics))); + CreateMap(); + CreateMap(); + CreateMap(); } private List CreateHeuristics(List heuristics) diff --git a/DataSetExplorer/Database/DataSetExplorerContext.cs b/DataSetExplorer/Database/DataSetExplorerContext.cs index 9f677906..e7cf7419 100644 --- a/DataSetExplorer/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Database/DataSetExplorerContext.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using System.Collections.Generic; +using DataSetExplorer.Annotations.Model; namespace DataSetExplorer.Database { @@ -15,6 +16,9 @@ public class DataSetExplorerContext : DbContext public DbSet DataSetInstances { get; set; } public DbSet DataSets { get; set; } public DbSet DataSetProjects { get; set; } + public DbSet CodeSmellDefinitions { get; set; } + public DbSet Heuristics { get; set; } + public DbSet CodeSmellHeuristics { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { } @@ -27,6 +31,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) m => JsonConvert.SerializeObject(m), m => JsonConvert.DeserializeObject>(m)); + modelBuilder.Entity().HasKey(ch => new { ch.CodeSmellDefinitionId, ch.HeuristicId }); + modelBuilder.Entity().HasOne().WithMany(d => d.SupportedCodeSmells) .OnDelete(DeleteBehavior.Cascade); @@ -50,6 +56,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasOne().WithMany(a => a.ApplicableHeuristics) .OnDelete(DeleteBehavior.Cascade); + + modelBuilder + .Entity() + .Property(c => c.SnippetType) + .HasConversion(); } } } diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index 216460ee..7bc9c2b9 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -10,6 +10,7 @@ using System; using DataSetExplorer.AnnotationConsistency; using DataSetExplorer.Annotations; +using DataSetExplorer.Annotations.Model.Repository; namespace DataSetExplorer { @@ -45,6 +46,8 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); } From c1e8996f7cec77dc0f4d4b15b594e4237cf81fba Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 27 Apr 2022 12:26:08 +0200 Subject: [PATCH 02/46] Fix imports --- DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs | 2 +- .../Model/Repository/AnnotationSchemaDatabaseRepository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs b/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs index 8bfae4a6..4db70b00 100644 --- a/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs +++ b/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using DataSetExplorer.DataSets.Model; +using DataSetExplorer.Core.DataSets.Model; namespace DataSetExplorer.Annotations.Model { diff --git a/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs index 2564e4c7..d3281c5c 100644 --- a/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using DataSetExplorer.Database; +using DataSetExplorer.Infrastructure.Database; using Microsoft.EntityFrameworkCore; namespace DataSetExplorer.Annotations.Model.Repository From 1f778530095f89eebe9034ef10f114f7b7551866 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 27 Apr 2022 13:07:38 +0200 Subject: [PATCH 03/46] feat[DE]: Move files and folders --- .../AnnotationSchemaService.cs | 24 +++++++++---------- .../IAnnotationSchemaService.cs | 16 ++++++------- .../Model/CodeSmellDefinition.cs | 2 +- .../Model/CodeSmellHeuristic.cs | 6 ++--- .../Model/HeuristicDefinition.cs} | 10 ++++---- .../AnnotationSchema}/Model/SeverityRange.cs | 2 +- .../AnnotationSchemaDatabaseRepository.cs | 13 +++++----- .../Repository/IAnnotationSchemaRepository.cs | 13 +++++----- .../Database/DataSetExplorerContext.cs | 4 ++-- DataSetExplorer/Startup.cs | 4 ++-- .../AnnotationSchemaController.cs | 22 ++++++++--------- .../DTOs/CodeSmellDefinitionDTO.cs | 4 ++-- .../DTOs/HeuristicDefinitionDTO.cs} | 4 ++-- .../DTOs/SeverityRangeDTO.cs | 2 +- .../Annotations/Mappers/AnnotationProfile.cs | 6 ++--- 15 files changed, 67 insertions(+), 65 deletions(-) rename DataSetExplorer/{Annotations => Core/AnnotationSchema}/AnnotationSchemaService.cs (81%) rename DataSetExplorer/{Annotations => Core/AnnotationSchema}/IAnnotationSchemaService.cs (51%) rename DataSetExplorer/{Annotations => Core/AnnotationSchema}/Model/CodeSmellDefinition.cs (96%) rename DataSetExplorer/{Annotations => Core/AnnotationSchema}/Model/CodeSmellHeuristic.cs (77%) rename DataSetExplorer/{Annotations/Model/Heuristic.cs => Core/AnnotationSchema/Model/HeuristicDefinition.cs} (65%) rename DataSetExplorer/{Annotations => Core/AnnotationSchema}/Model/SeverityRange.cs (89%) rename DataSetExplorer/{Annotations/Model => Core/AnnotationSchema}/Repository/AnnotationSchemaDatabaseRepository.cs (85%) rename DataSetExplorer/{Annotations/Model => Core/AnnotationSchema}/Repository/IAnnotationSchemaRepository.cs (56%) rename DataSetExplorer/{Controllers/Annotations => UI/Controllers/AnnotationSchema}/AnnotationSchemaController.cs (89%) rename DataSetExplorer/{Controllers/Annotations => UI/Controllers/AnnotationSchema}/DTOs/CodeSmellDefinitionDTO.cs (72%) rename DataSetExplorer/{Controllers/Annotations/DTOs/HeuristicDTO.cs => UI/Controllers/AnnotationSchema/DTOs/HeuristicDefinitionDTO.cs} (57%) rename DataSetExplorer/{Controllers/Annotations => UI/Controllers/AnnotationSchema}/DTOs/SeverityRangeDTO.cs (73%) diff --git a/DataSetExplorer/Annotations/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs similarity index 81% rename from DataSetExplorer/Annotations/AnnotationSchemaService.cs rename to DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index 780ffc0c..de75dd61 100644 --- a/DataSetExplorer/Annotations/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -1,9 +1,9 @@ -using DataSetExplorer.Annotations.Model; -using DataSetExplorer.Annotations.Model.Repository; +using System.Collections.Generic; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.Core.AnnotationSchema.Repository; using FluentResults; -using System.Collections.Generic; -namespace DataSetExplorer.Annotations +namespace DataSetExplorer.Core.AnnotationSchema { public class AnnotationSchemaService : IAnnotationSchemaService { @@ -27,7 +27,7 @@ public Result CreateCodeSmellDefinition(CodeSmellDefinition return Result.Ok(codeSmellDefinition); } - public Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics) + public Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics) { var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); @@ -47,12 +47,12 @@ public Result> AddHeuristicsToCodeSmell(int id, IEnumerab return Result.Ok(heuristics); } - public Result> GetHeuristicsForCodeSmell(int id) + public Result> GetHeuristicsForCodeSmell(int id) { var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); - IEnumerable heuristics = _annotationSchemaRepository.GetHeuristicsForCodeSmell(id); + IEnumerable heuristics = _annotationSchemaRepository.GetHeuristicsForCodeSmell(id); return Result.Ok(heuristics); } @@ -82,27 +82,27 @@ public Result DeleteCodeSmellDefinition(int id) return Result.Ok(codeSmellDefinition); } - public Result> GetAllHeuristics() + public Result> GetAllHeuristics() { return Result.Ok(_annotationSchemaRepository.GetAllHeuristics()); } - public Result UpdateHeuristic(int id, Heuristic heuristic) + public Result UpdateHeuristic(int id, HeuristicDefinition heuristic) { var existingHeuristic = _annotationSchemaRepository.GetHeuristic(id); - if (existingHeuristic == default) return Result.Fail($"Heuristic with id: {id} does not exist."); + if (existingHeuristic == default) return Result.Fail($"Heuristic with id: {id} does not exist."); existingHeuristic.Update(heuristic); _annotationSchemaRepository.SaveHeuristic(existingHeuristic); return Result.Ok(heuristic); } - public Result DeleteHeuristic(int id) + public Result DeleteHeuristic(int id) { var heuristic = _annotationSchemaRepository.DeleteHeuristic(id); return Result.Ok(heuristic); } - public Result CreateHeuristic(Heuristic heuristic) + public Result CreateHeuristic(HeuristicDefinition heuristic) { _annotationSchemaRepository.SaveHeuristic(heuristic); return Result.Ok(heuristic); diff --git a/DataSetExplorer/Annotations/IAnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs similarity index 51% rename from DataSetExplorer/Annotations/IAnnotationSchemaService.cs rename to DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs index 3001c587..b15d1a6c 100644 --- a/DataSetExplorer/Annotations/IAnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using DataSetExplorer.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; using FluentResults; -namespace DataSetExplorer.Annotations +namespace DataSetExplorer.Core.AnnotationSchema { public interface IAnnotationSchemaService { @@ -11,12 +11,12 @@ public interface IAnnotationSchemaService Result> GetAllCodeSmellDefinitions(); Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition); Result DeleteCodeSmellDefinition(int id); - Result> GetAllHeuristics(); - Result CreateHeuristic(Heuristic heuristic); - Result UpdateHeuristic(int id, Heuristic heuristic); - Result DeleteHeuristic(int id); - Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics); - Result> GetHeuristicsForCodeSmell(int id); + Result> GetAllHeuristics(); + Result CreateHeuristic(HeuristicDefinition heuristic); + Result UpdateHeuristic(int id, HeuristicDefinition heuristic); + Result DeleteHeuristic(int id); + Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics); + Result> GetHeuristicsForCodeSmell(int id); Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); } } diff --git a/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs similarity index 96% rename from DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs rename to DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs index 4db70b00..6ceb03a3 100644 --- a/DataSetExplorer/Annotations/Model/CodeSmellDefinition.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using DataSetExplorer.Core.DataSets.Model; -namespace DataSetExplorer.Annotations.Model +namespace DataSetExplorer.Core.AnnotationSchema.Model { public class CodeSmellDefinition { diff --git a/DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs similarity index 77% rename from DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs rename to DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs index 6b929adf..054f1156 100644 --- a/DataSetExplorer/Annotations/Model/CodeSmellHeuristic.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs @@ -1,13 +1,13 @@ -namespace DataSetExplorer.Annotations.Model +namespace DataSetExplorer.Core.AnnotationSchema.Model { public class CodeSmellHeuristic { public int CodeSmellDefinitionId { get; set; } public CodeSmellDefinition CodeSmellDefinition { get; set; } public int HeuristicId { get; set; } - public Heuristic Heuristic { get; set; } + public HeuristicDefinition Heuristic { get; set; } - public CodeSmellHeuristic(CodeSmellDefinition codeSmellDefinition, Heuristic heuristic) + public CodeSmellHeuristic(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristic) { CodeSmellDefinition = codeSmellDefinition; CodeSmellDefinitionId = codeSmellDefinition.Id; diff --git a/DataSetExplorer/Annotations/Model/Heuristic.cs b/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs similarity index 65% rename from DataSetExplorer/Annotations/Model/Heuristic.cs rename to DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs index 9185bbcb..36644542 100644 --- a/DataSetExplorer/Annotations/Model/Heuristic.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs @@ -1,25 +1,25 @@ using System.Collections.Generic; -namespace DataSetExplorer.Annotations.Model +namespace DataSetExplorer.Core.AnnotationSchema.Model { - public class Heuristic + public class HeuristicDefinition { public int Id { get; private set; } public string Name { get; set; } public string Description { get; set; } public ICollection CodeSmellHeuristics { get; set; } - public Heuristic(string name, string description) + public HeuristicDefinition(string name, string description) { Name = name; Description = description; } - private Heuristic() + private HeuristicDefinition() { } - public void Update(Heuristic other) + public void Update(HeuristicDefinition other) { Name = other.Name; Description = other.Description; diff --git a/DataSetExplorer/Annotations/Model/SeverityRange.cs b/DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs similarity index 89% rename from DataSetExplorer/Annotations/Model/SeverityRange.cs rename to DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs index 55f30db4..14310697 100644 --- a/DataSetExplorer/Annotations/Model/SeverityRange.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs @@ -1,4 +1,4 @@ -namespace DataSetExplorer.Annotations.Model +namespace DataSetExplorer.Core.AnnotationSchema.Model { public class SeverityRange { diff --git a/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs similarity index 85% rename from DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs rename to DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index d3281c5c..ee4df397 100644 --- a/DataSetExplorer/Annotations/Model/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; using System.Linq; +using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Infrastructure.Database; using Microsoft.EntityFrameworkCore; -namespace DataSetExplorer.Annotations.Model.Repository +namespace DataSetExplorer.Core.AnnotationSchema.Repository { public class AnnotationSchemaDatabaseRepository : IAnnotationSchemaRepository { @@ -33,7 +34,7 @@ public void SaveCodeSmellHeuristic(CodeSmellHeuristic codeSmellHeuristic) _dbContext.SaveChanges(); } - public IEnumerable GetHeuristicsForCodeSmell(int id) + public IEnumerable GetHeuristicsForCodeSmell(int id) { return _dbContext.Heuristics.Where(h => h.CodeSmellHeuristics.Any(ch => ch.CodeSmellDefinitionId == id)); } @@ -61,25 +62,25 @@ public CodeSmellDefinition DeleteCodeSmellDefinition(int id) return deletedCodeSmell; } - public IEnumerable GetAllHeuristics() + public IEnumerable GetAllHeuristics() { return _dbContext.Heuristics; } - public Heuristic DeleteHeuristic(int id) + public HeuristicDefinition DeleteHeuristic(int id) { var deletedHeuristic = _dbContext.Heuristics.Remove(_dbContext.Heuristics.Find(id)).Entity; _dbContext.SaveChanges(); return deletedHeuristic; } - public void SaveHeuristic(Heuristic heuristic) + public void SaveHeuristic(HeuristicDefinition heuristic) { _dbContext.Update(heuristic); _dbContext.SaveChanges(); } - public Heuristic GetHeuristic(int id) + public HeuristicDefinition GetHeuristic(int id) { return _dbContext.Heuristics .FirstOrDefault(h => h.Id == id); diff --git a/DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs similarity index 56% rename from DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs rename to DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs index 51235e15..5b73dae9 100644 --- a/DataSetExplorer/Annotations/Model/Repository/IAnnotationSchemaRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; +using DataSetExplorer.Core.AnnotationSchema.Model; -namespace DataSetExplorer.Annotations.Model.Repository +namespace DataSetExplorer.Core.AnnotationSchema.Repository { public interface IAnnotationSchemaRepository { @@ -8,12 +9,12 @@ public interface IAnnotationSchemaRepository void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); IEnumerable GetAllCodeSmellDefinitions(); CodeSmellDefinition DeleteCodeSmellDefinition(int id); - IEnumerable GetAllHeuristics(); - Heuristic DeleteHeuristic(int id); - void SaveHeuristic(Heuristic heuristic); - Heuristic GetHeuristic(int id); + IEnumerable GetAllHeuristics(); + HeuristicDefinition DeleteHeuristic(int id); + void SaveHeuristic(HeuristicDefinition heuristic); + HeuristicDefinition GetHeuristic(int id); void SaveCodeSmellHeuristic(CodeSmellHeuristic codeSmellHeuristic); - IEnumerable GetHeuristicsForCodeSmell(int id); + IEnumerable GetHeuristicsForCodeSmell(int id); CodeSmellHeuristic DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); } } diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index a358d60b..0d9ad719 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Newtonsoft.Json; -using DataSetExplorer.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; namespace DataSetExplorer.Infrastructure.Database { @@ -19,7 +19,7 @@ public class DataSetExplorerContext : DbContext public DbSet DataSets { get; set; } public DbSet DataSetProjects { get; set; } public DbSet CodeSmellDefinitions { get; set; } - public DbSet Heuristics { get; set; } + public DbSet Heuristics { get; set; } public DbSet CodeSmellHeuristics { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index ff872fd6..110569fc 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -4,10 +4,10 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System; -using DataSetExplorer.Annotations; -using DataSetExplorer.Annotations.Model.Repository; using DataSetExplorer.Core.AnnotationConsistency; using DataSetExplorer.Core.Annotations; +using DataSetExplorer.Core.AnnotationSchema; +using DataSetExplorer.Core.AnnotationSchema.Repository; using DataSetExplorer.Core.DataSets; using DataSetExplorer.Core.DataSets.Repository; using DataSetExplorer.Infrastructure.Database; diff --git a/DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs similarity index 89% rename from DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs rename to DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs index 4e795bef..94d5e308 100644 --- a/DataSetExplorer/Controllers/Annotations/AnnotationSchemaController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using AutoMapper; +using DataSetExplorer.Core.AnnotationSchema; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; -using DataSetExplorer.Annotations; -using DataSetExplorer.Annotations.Model; -using DataSetExplorer.Controllers.Annotations.DTOs; -namespace DataSetExplorer.Controllers.Annotations +namespace DataSetExplorer.UI.Controllers.AnnotationSchema { [Route("api/annotation-schema/")] [ApiController] @@ -53,12 +53,12 @@ public IActionResult CreateCodeSmellDefinition([FromBody] CodeSmellDefinitionDTO [HttpPost] [Route("code-smell-definition/{id}/heuristic")] - public IActionResult AddHeuristicsToCodeSmell([FromRoute] int id, [FromBody] List heuristicsDto) + public IActionResult AddHeuristicsToCodeSmell([FromRoute] int id, [FromBody] List heuristicsDto) { - var heuristics = new List(); + var heuristics = new List(); foreach (var heuristic in heuristicsDto) { - heuristics.Add(_mapper.Map(heuristic)); + heuristics.Add(_mapper.Map(heuristic)); } var result = _annotationSchemaService.AddHeuristicsToCodeSmell(id, heuristics); if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); @@ -113,9 +113,9 @@ public IActionResult GetAllHeuristics() [HttpPut] [Route("heuristic/{id}")] - public IActionResult UpdateHeuristic([FromRoute] int id, [FromBody] HeuristicDTO heuristicDto) + public IActionResult UpdateHeuristic([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) { - var heuristic = _mapper.Map(heuristicDto); + var heuristic = _mapper.Map(heuristicDto); var result = _annotationSchemaService.UpdateHeuristic(id, heuristic); if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); return Ok(result.Value); @@ -132,9 +132,9 @@ public IActionResult DeleteHeuristic([FromRoute] int id) [HttpPost] [Route("heuristic")] - public IActionResult CreateHeuristic([FromBody] HeuristicDTO heuristicDto) + public IActionResult CreateHeuristic([FromBody] HeuristicDefinitionDTO heuristicDto) { - var heuristic = _mapper.Map(heuristicDto); + var heuristic = _mapper.Map(heuristicDto); var result = _annotationSchemaService.CreateHeuristic(heuristic); if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); return Ok(result.Value); diff --git a/DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs similarity index 72% rename from DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs rename to DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs index 545d4e2b..7a6a005e 100644 --- a/DataSetExplorer/Controllers/Annotations/DTOs/CodeSmellDefinitionDTO.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; -namespace DataSetExplorer.Controllers.Annotations.DTOs +namespace DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs { public class CodeSmellDefinitionDTO { public string Name { get; set; } public string Description { get; set; } public string SnippetType { get; set; } - public List Heuristics { get; set; } + public List Heuristics { get; set; } public SeverityRangeDTO SeverityRange { get; set; } public List SeverityValues { get; set; } } diff --git a/DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/HeuristicDefinitionDTO.cs similarity index 57% rename from DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs rename to DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/HeuristicDefinitionDTO.cs index 028e4524..96f267bc 100644 --- a/DataSetExplorer/Controllers/Annotations/DTOs/HeuristicDTO.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/HeuristicDefinitionDTO.cs @@ -1,6 +1,6 @@ -namespace DataSetExplorer.Controllers.Annotations.DTOs +namespace DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs { - public class HeuristicDTO + public class HeuristicDefinitionDTO { public int Id { get; set; } public string Name { get; set; } diff --git a/DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs similarity index 73% rename from DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs rename to DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs index 27ca7da1..976c66fe 100644 --- a/DataSetExplorer/Controllers/Annotations/DTOs/SeverityRangeDTO.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs @@ -1,4 +1,4 @@ -namespace DataSetExplorer.Controllers.Annotations.DTOs +namespace DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs { public class SeverityRangeDTO { diff --git a/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs b/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs index aefefc9b..e10619ca 100644 --- a/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs +++ b/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs @@ -2,8 +2,8 @@ using AutoMapper; using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.UI.Controllers.Annotations.DTOs; -using DataSetExplorer.Controllers.Annotations.DTOs; -using DataSetExplorer.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs; namespace DataSetExplorer.UI.Controllers.Annotations.Mappers { @@ -15,7 +15,7 @@ public AnnotationProfile() .IgnoreAllPropertiesWithAnInaccessibleSetter() .ConstructUsing(src => new Annotation(src.CodeSmell, src.Severity, new Annotator(src.AnnotatorId), CreateHeuristics(src.ApplicableHeuristics), src.Note)); CreateMap(); - CreateMap(); + CreateMap(); CreateMap(); } From 2af5e695c838950bc485505f0b5274d9be6e3baf Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 27 Apr 2022 13:09:56 +0200 Subject: [PATCH 04/46] fix[DE]: Delete blank line --- .../Infrastructure/Database/DataSetExplorerContext.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index 0d9ad719..202f5602 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -39,7 +39,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) m => JsonConvert.SerializeObject(m), m => JsonConvert.DeserializeObject>(m)); - modelBuilder.Entity().HasKey(ch => new { ch.CodeSmellDefinitionId, ch.HeuristicId }); modelBuilder.Entity().HasOne().WithMany(d => d.SupportedCodeSmells) From 64f692c2b1c0b389d1f309b741a9878e09c75b57 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 27 Apr 2022 13:29:05 +0200 Subject: [PATCH 05/46] feat[DE]: Refactor AnnotationSchema controllers --- ...er.cs => CodeSmellDefinitionController.cs} | 83 +++++-------------- .../HeuristicDefinitionController.cs | 58 +++++++++++++ 2 files changed, 78 insertions(+), 63 deletions(-) rename DataSetExplorer/UI/Controllers/AnnotationSchema/{AnnotationSchemaController.cs => CodeSmellDefinitionController.cs} (62%) create mode 100644 DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/CodeSmellDefinitionController.cs similarity index 62% rename from DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs rename to DataSetExplorer/UI/Controllers/AnnotationSchema/CodeSmellDefinitionController.cs index 94d5e308..7e057903 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/CodeSmellDefinitionController.cs @@ -4,27 +4,23 @@ using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; namespace DataSetExplorer.UI.Controllers.AnnotationSchema { - [Route("api/annotation-schema/")] + [Route("api/annotation-schema/code-smells/")] [ApiController] - public class AnnotationSchemaController : ControllerBase + public class CodeSmellDefinitionController : ControllerBase { private readonly IMapper _mapper; - private readonly IConfiguration _configuration; private readonly IAnnotationSchemaService _annotationSchemaService; - public AnnotationSchemaController(IMapper mapper, IConfiguration configuration, IAnnotationSchemaService annotationSchemaService) + public CodeSmellDefinitionController(IMapper mapper, IAnnotationSchemaService annotationSchemaService) { _mapper = mapper; - _configuration = configuration; _annotationSchemaService = annotationSchemaService; } [HttpGet] - [Route("code-smell-definition")] public IActionResult GetAllCodeSmellDefinitions() { var result = _annotationSchemaService.GetAllCodeSmellDefinitions(); @@ -42,7 +38,6 @@ public IActionResult GetCodeSmellDefinition([FromRoute] int id) } [HttpPost] - [Route("code-smell-definition")] public IActionResult CreateCodeSmellDefinition([FromBody] CodeSmellDefinitionDTO codeSmellDefinitionDto) { var codeSmellDefinition = _mapper.Map(codeSmellDefinitionDto); @@ -51,40 +46,8 @@ public IActionResult CreateCodeSmellDefinition([FromBody] CodeSmellDefinitionDTO return Ok(result.Value); } - [HttpPost] - [Route("code-smell-definition/{id}/heuristic")] - public IActionResult AddHeuristicsToCodeSmell([FromRoute] int id, [FromBody] List heuristicsDto) - { - var heuristics = new List(); - foreach (var heuristic in heuristicsDto) - { - heuristics.Add(_mapper.Map(heuristic)); - } - var result = _annotationSchemaService.AddHeuristicsToCodeSmell(id, heuristics); - if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } - - [HttpDelete] - [Route("code-smell-definition/{smellId}/heuristic/{heuristicId}")] - public IActionResult RemoveHeuristicFromCodeSmell([FromRoute] int smellId, [FromRoute] int heuristicId) - { - var result = _annotationSchemaService.DeleteHeuristicFromCodeSmell(smellId, heuristicId); - if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } - - [HttpGet] - [Route("code-smell-definition/{id}/heuristic")] - public IActionResult GetHeuristicsForCodeSmell([FromRoute] int id) - { - var result = _annotationSchemaService.GetHeuristicsForCodeSmell(id); - if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } - [HttpPut] - [Route("code-smell-definition/{id}")] + [Route("{id}")] public IActionResult UpdateCodeSmellDefinition([FromRoute] int id, [FromBody] CodeSmellDefinitionDTO codeSmellDefinitionDto) { var codeSmellDefinition = _mapper.Map(codeSmellDefinitionDto); @@ -94,7 +57,7 @@ public IActionResult UpdateCodeSmellDefinition([FromRoute] int id, [FromBody] Co } [HttpDelete] - [Route("code-smell-definition/{id}")] + [Route("{id}")] public IActionResult DeleteCodeSmellDefinition([FromRoute] int id) { var result = _annotationSchemaService.DeleteCodeSmellDefinition(id); @@ -103,41 +66,35 @@ public IActionResult DeleteCodeSmellDefinition([FromRoute] int id) } [HttpGet] - [Route("heuristic")] - public IActionResult GetAllHeuristics() + [Route("{id}/heuristics")] + public IActionResult GetHeuristicsForCodeSmell([FromRoute] int id) { - var result = _annotationSchemaService.GetAllHeuristics(); + var result = _annotationSchemaService.GetHeuristicsForCodeSmell(id); if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } - [HttpPut] - [Route("heuristic/{id}")] - public IActionResult UpdateHeuristic([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) + [HttpPost] + [Route("{id}/heuristics")] + public IActionResult AddHeuristicsToCodeSmell([FromRoute] int id, [FromBody] List heuristicsDto) { - var heuristic = _mapper.Map(heuristicDto); - var result = _annotationSchemaService.UpdateHeuristic(id, heuristic); + var heuristics = new List(); + foreach (var heuristic in heuristicsDto) + { + heuristics.Add(_mapper.Map(heuristic)); + } + var result = _annotationSchemaService.AddHeuristicsToCodeSmell(id, heuristics); if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); return Ok(result.Value); } [HttpDelete] - [Route("heuristic/{id}")] - public IActionResult DeleteHeuristic([FromRoute] int id) + [Route("{smellId}/heuristics/{heuristicId}")] + public IActionResult RemoveHeuristicFromCodeSmell([FromRoute] int smellId, [FromRoute] int heuristicId) { - var result = _annotationSchemaService.DeleteHeuristic(id); + var result = _annotationSchemaService.DeleteHeuristicFromCodeSmell(smellId, heuristicId); if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } - - [HttpPost] - [Route("heuristic")] - public IActionResult CreateHeuristic([FromBody] HeuristicDefinitionDTO heuristicDto) - { - var heuristic = _mapper.Map(heuristicDto); - var result = _annotationSchemaService.CreateHeuristic(heuristic); - if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } } } diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs new file mode 100644 index 00000000..1fe874b2 --- /dev/null +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs @@ -0,0 +1,58 @@ +using AutoMapper; +using DataSetExplorer.Core.AnnotationSchema; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs; +using Microsoft.AspNetCore.Mvc; + +namespace DataSetExplorer.UI.Controllers.AnnotationSchema +{ + [Route("api/annotation-schema/heuristics/")] + [ApiController] + public class HeuristicDefinitionController : ControllerBase + { + private readonly IMapper _mapper; + private readonly IAnnotationSchemaService _annotationSchemaService; + + public HeuristicDefinitionController(IMapper mapper, IAnnotationSchemaService annotationSchemaService) + { + _mapper = mapper; + _annotationSchemaService = annotationSchemaService; + } + + [HttpGet] + public IActionResult GetAllHeuristics() + { + var result = _annotationSchemaService.GetAllHeuristics(); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPost] + public IActionResult CreateHeuristic([FromBody] HeuristicDefinitionDTO heuristicDto) + { + var heuristic = _mapper.Map(heuristicDto); + var result = _annotationSchemaService.CreateHeuristic(heuristic); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPut] + [Route("{id}")] + public IActionResult UpdateHeuristic([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) + { + var heuristic = _mapper.Map(heuristicDto); + var result = _annotationSchemaService.UpdateHeuristic(id, heuristic); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpDelete] + [Route("{id}")] + public IActionResult DeleteHeuristic([FromRoute] int id) + { + var result = _annotationSchemaService.DeleteHeuristic(id); + if (result.IsFailed) return BadRequest(new {message = result.Reasons[0].Message}); + return Ok(result.Value); + } + } +} From 8350e357dbaffb150097604b5ec1f5fdf1281f6b Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Mon, 9 May 2022 14:45:50 +0200 Subject: [PATCH 06/46] feat[DE]: Remove smell-independent heuristics --- .../AnnotationSchemaService.cs | 59 +++++-------------- .../IAnnotationSchemaService.cs | 9 +-- .../Model/CodeSmellDefinition.cs | 3 +- .../Model/CodeSmellHeuristic.cs | 22 ------- .../Model/HeuristicDefinition.cs | 1 - .../AnnotationSchemaDatabaseRepository.cs | 28 ++------- .../Repository/IAnnotationSchemaRepository.cs | 3 - .../Database/DataSetExplorerContext.cs | 8 +-- ...oller.cs => AnnotationSchemaController.cs} | 27 +++++---- .../HeuristicDefinitionController.cs | 58 ------------------ 10 files changed, 45 insertions(+), 173 deletions(-) delete mode 100644 DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs rename DataSetExplorer/UI/Controllers/AnnotationSchema/{CodeSmellDefinitionController.cs => AnnotationSchemaController.cs} (78%) delete mode 100644 DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs diff --git a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index de75dd61..731b2fce 100644 --- a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -27,39 +27,31 @@ public Result CreateCodeSmellDefinition(CodeSmellDefinition return Result.Ok(codeSmellDefinition); } - public Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics) + public Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic) { var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); - foreach (var h in heuristics) - { - var heuristic = _annotationSchemaRepository.GetHeuristic(h.Id); - if (heuristic == default) return Result.Fail($"Heuristic with id: {id} does not exist."); - } - - foreach (var h in heuristics) - { - var heuristic = _annotationSchemaRepository.GetHeuristic(h.Id); - var codeSmellHeuristic = new CodeSmellHeuristic(codeSmellDefinition, heuristic); - _annotationSchemaRepository.SaveCodeSmellHeuristic(codeSmellHeuristic); - } - return Result.Ok(heuristics); + codeSmellDefinition.Heuristics.Add(heuristic); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + return Result.Ok(heuristic); } public Result> GetHeuristicsForCodeSmell(int id) { var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); - - IEnumerable heuristics = _annotationSchemaRepository.GetHeuristicsForCodeSmell(id); - return Result.Ok(heuristics); + return Result.Ok((IEnumerable)codeSmellDefinition.Heuristics); } - public Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) + public Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) { - var codeSmellHeuristic = _annotationSchemaRepository.DeleteHeuristicFromCodeSmell(smellId, heuristicId); - return Result.Ok(codeSmellHeuristic); + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(smellId); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {smellId} does not exist."); + + codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristicId)); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + return Result.Ok(codeSmellDefinition); } public Result> GetAllCodeSmellDefinitions() @@ -82,30 +74,11 @@ public Result DeleteCodeSmellDefinition(int id) return Result.Ok(codeSmellDefinition); } - public Result> GetAllHeuristics() + public Result UpdateHeuristicInCodeSmell(int id, HeuristicDefinition heuristic) { - return Result.Ok(_annotationSchemaRepository.GetAllHeuristics()); - } - - public Result UpdateHeuristic(int id, HeuristicDefinition heuristic) - { - var existingHeuristic = _annotationSchemaRepository.GetHeuristic(id); - if (existingHeuristic == default) return Result.Fail($"Heuristic with id: {id} does not exist."); - existingHeuristic.Update(heuristic); - _annotationSchemaRepository.SaveHeuristic(existingHeuristic); - return Result.Ok(heuristic); - } - - public Result DeleteHeuristic(int id) - { - var heuristic = _annotationSchemaRepository.DeleteHeuristic(id); - return Result.Ok(heuristic); - } - - public Result CreateHeuristic(HeuristicDefinition heuristic) - { - _annotationSchemaRepository.SaveHeuristic(heuristic); - return Result.Ok(heuristic); + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristic.Id)); + return AddHeuristicToCodeSmell(id, heuristic); } } } diff --git a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs index b15d1a6c..770bd71f 100644 --- a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs @@ -11,12 +11,9 @@ public interface IAnnotationSchemaService Result> GetAllCodeSmellDefinitions(); Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition); Result DeleteCodeSmellDefinition(int id); - Result> GetAllHeuristics(); - Result CreateHeuristic(HeuristicDefinition heuristic); - Result UpdateHeuristic(int id, HeuristicDefinition heuristic); - Result DeleteHeuristic(int id); - Result> AddHeuristicsToCodeSmell(int id, IEnumerable heuristics); + Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic); Result> GetHeuristicsForCodeSmell(int id); - Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); + Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); + Result UpdateHeuristicInCodeSmell(int id, HeuristicDefinition heuristic); } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs index 6ceb03a3..c526ec11 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs @@ -11,13 +11,14 @@ public class CodeSmellDefinition public SnippetType SnippetType { get; set; } public SeverityRange SeverityRange { get; set; } public List SeverityValues { get; set; } - public ICollection CodeSmellHeuristics { get; set; } + public List Heuristics { get; set; } public CodeSmellDefinition(string name, string description, SnippetType snippetType) { Name = name; Description = description; SnippetType = snippetType; + Heuristics = new List(); } private CodeSmellDefinition() diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs deleted file mode 100644 index 054f1156..00000000 --- a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellHeuristic.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace DataSetExplorer.Core.AnnotationSchema.Model -{ - public class CodeSmellHeuristic - { - public int CodeSmellDefinitionId { get; set; } - public CodeSmellDefinition CodeSmellDefinition { get; set; } - public int HeuristicId { get; set; } - public HeuristicDefinition Heuristic { get; set; } - - public CodeSmellHeuristic(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristic) - { - CodeSmellDefinition = codeSmellDefinition; - CodeSmellDefinitionId = codeSmellDefinition.Id; - Heuristic = heuristic; - HeuristicId = heuristic.Id; - } - - public CodeSmellHeuristic() - { - } - } -} \ No newline at end of file diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs index 36644542..346b264e 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs @@ -7,7 +7,6 @@ public class HeuristicDefinition public int Id { get; private set; } public string Name { get; set; } public string Description { get; set; } - public ICollection CodeSmellHeuristics { get; set; } public HeuristicDefinition(string name, string description) { diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index ee4df397..d103e9d9 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -19,6 +19,7 @@ public CodeSmellDefinition GetCodeSmellDefinition(int id) { return _dbContext.CodeSmellDefinitions .Include(c => c.SeverityRange) + .Include(c => c.Heuristics) .FirstOrDefault(c => c.Id == id); } @@ -28,27 +29,6 @@ public void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) _dbContext.SaveChanges(); } - public void SaveCodeSmellHeuristic(CodeSmellHeuristic codeSmellHeuristic) - { - _dbContext.Add(codeSmellHeuristic); - _dbContext.SaveChanges(); - } - - public IEnumerable GetHeuristicsForCodeSmell(int id) - { - return _dbContext.Heuristics.Where(h => h.CodeSmellHeuristics.Any(ch => ch.CodeSmellDefinitionId == id)); - } - - public CodeSmellHeuristic DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) - { - var codeSmellHeuristic = _dbContext.CodeSmellHeuristics - .First(ch => ch.CodeSmellDefinitionId == smellId && ch.HeuristicId == heuristicId); - - _dbContext.Remove(codeSmellHeuristic); - _dbContext.SaveChanges(); - return codeSmellHeuristic; - } - public IEnumerable GetAllCodeSmellDefinitions() { return _dbContext.CodeSmellDefinitions @@ -64,12 +44,12 @@ public CodeSmellDefinition DeleteCodeSmellDefinition(int id) public IEnumerable GetAllHeuristics() { - return _dbContext.Heuristics; + return _dbContext.HeuristicDefinitions; } public HeuristicDefinition DeleteHeuristic(int id) { - var deletedHeuristic = _dbContext.Heuristics.Remove(_dbContext.Heuristics.Find(id)).Entity; + var deletedHeuristic = _dbContext.HeuristicDefinitions.Remove(_dbContext.HeuristicDefinitions.Find(id)).Entity; _dbContext.SaveChanges(); return deletedHeuristic; } @@ -82,7 +62,7 @@ public void SaveHeuristic(HeuristicDefinition heuristic) public HeuristicDefinition GetHeuristic(int id) { - return _dbContext.Heuristics + return _dbContext.HeuristicDefinitions .FirstOrDefault(h => h.Id == id); } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs index 5b73dae9..43802254 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs @@ -13,8 +13,5 @@ public interface IAnnotationSchemaRepository HeuristicDefinition DeleteHeuristic(int id); void SaveHeuristic(HeuristicDefinition heuristic); HeuristicDefinition GetHeuristic(int id); - void SaveCodeSmellHeuristic(CodeSmellHeuristic codeSmellHeuristic); - IEnumerable GetHeuristicsForCodeSmell(int id); - CodeSmellHeuristic DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); } } diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index 202f5602..6c44b212 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -19,8 +19,7 @@ public class DataSetExplorerContext : DbContext public DbSet DataSets { get; set; } public DbSet DataSetProjects { get; set; } public DbSet CodeSmellDefinitions { get; set; } - public DbSet Heuristics { get; set; } - public DbSet CodeSmellHeuristics { get; set; } + public DbSet HeuristicDefinitions { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { } @@ -39,8 +38,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) m => JsonConvert.SerializeObject(m), m => JsonConvert.DeserializeObject>(m)); - modelBuilder.Entity().HasKey(ch => new { ch.CodeSmellDefinitionId, ch.HeuristicId }); - modelBuilder.Entity().HasOne().WithMany(d => d.SupportedCodeSmells) .OnDelete(DeleteBehavior.Cascade); @@ -73,6 +70,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(i => i.RelationType) .HasConversion(new EnumToStringConverter()); + modelBuilder.Entity().HasOne().WithMany(d => d.Heuristics) + .OnDelete(DeleteBehavior.Cascade); + modelBuilder .Entity() .Property(c => c.SnippetType) diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/CodeSmellDefinitionController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs similarity index 78% rename from DataSetExplorer/UI/Controllers/AnnotationSchema/CodeSmellDefinitionController.cs rename to DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs index 7e057903..435180f2 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/CodeSmellDefinitionController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using AutoMapper; +using AutoMapper; using DataSetExplorer.Core.AnnotationSchema; using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs; @@ -9,12 +8,12 @@ namespace DataSetExplorer.UI.Controllers.AnnotationSchema { [Route("api/annotation-schema/code-smells/")] [ApiController] - public class CodeSmellDefinitionController : ControllerBase + public class AnnotationSchemaController : ControllerBase { private readonly IMapper _mapper; private readonly IAnnotationSchemaService _annotationSchemaService; - public CodeSmellDefinitionController(IMapper mapper, IAnnotationSchemaService annotationSchemaService) + public AnnotationSchemaController(IMapper mapper, IAnnotationSchemaService annotationSchemaService) { _mapper = mapper; _annotationSchemaService = annotationSchemaService; @@ -76,14 +75,10 @@ public IActionResult GetHeuristicsForCodeSmell([FromRoute] int id) [HttpPost] [Route("{id}/heuristics")] - public IActionResult AddHeuristicsToCodeSmell([FromRoute] int id, [FromBody] List heuristicsDto) + public IActionResult AddHeuristicToCodeSmell([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) { - var heuristics = new List(); - foreach (var heuristic in heuristicsDto) - { - heuristics.Add(_mapper.Map(heuristic)); - } - var result = _annotationSchemaService.AddHeuristicsToCodeSmell(id, heuristics); + var heuristic = _mapper.Map(heuristicDto); + var result = _annotationSchemaService.AddHeuristicToCodeSmell(id, heuristic); if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); return Ok(result.Value); } @@ -96,5 +91,15 @@ public IActionResult RemoveHeuristicFromCodeSmell([FromRoute] int smellId, [From if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } + + [HttpPut] + [Route("{id}/heuristics")] + public IActionResult UpdateHeuristicInCodeSmell([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) + { + var heuristic = _mapper.Map(heuristicDto); + var result = _annotationSchemaService.UpdateHeuristicInCodeSmell(id, heuristic); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } } } diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs deleted file mode 100644 index 1fe874b2..00000000 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/HeuristicDefinitionController.cs +++ /dev/null @@ -1,58 +0,0 @@ -using AutoMapper; -using DataSetExplorer.Core.AnnotationSchema; -using DataSetExplorer.Core.AnnotationSchema.Model; -using DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs; -using Microsoft.AspNetCore.Mvc; - -namespace DataSetExplorer.UI.Controllers.AnnotationSchema -{ - [Route("api/annotation-schema/heuristics/")] - [ApiController] - public class HeuristicDefinitionController : ControllerBase - { - private readonly IMapper _mapper; - private readonly IAnnotationSchemaService _annotationSchemaService; - - public HeuristicDefinitionController(IMapper mapper, IAnnotationSchemaService annotationSchemaService) - { - _mapper = mapper; - _annotationSchemaService = annotationSchemaService; - } - - [HttpGet] - public IActionResult GetAllHeuristics() - { - var result = _annotationSchemaService.GetAllHeuristics(); - if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } - - [HttpPost] - public IActionResult CreateHeuristic([FromBody] HeuristicDefinitionDTO heuristicDto) - { - var heuristic = _mapper.Map(heuristicDto); - var result = _annotationSchemaService.CreateHeuristic(heuristic); - if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } - - [HttpPut] - [Route("{id}")] - public IActionResult UpdateHeuristic([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) - { - var heuristic = _mapper.Map(heuristicDto); - var result = _annotationSchemaService.UpdateHeuristic(id, heuristic); - if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); - return Ok(result.Value); - } - - [HttpDelete] - [Route("{id}")] - public IActionResult DeleteHeuristic([FromRoute] int id) - { - var result = _annotationSchemaService.DeleteHeuristic(id); - if (result.IsFailed) return BadRequest(new {message = result.Reasons[0].Message}); - return Ok(result.Value); - } - } -} From 37962ac3d29c5ea1b7dcc344d8c69ed4f36e33a5 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Mon, 16 May 2022 16:22:53 +0200 Subject: [PATCH 07/46] feat[DE]: Remove SeverityRange from CodeSmellDefinition --- .../Model/CodeSmellDefinition.cs | 2 -- .../AnnotationSchema/Model/SeverityRange.cs | 21 ------------------- .../AnnotationSchemaDatabaseRepository.cs | 4 +--- .../DTOs/CodeSmellDefinitionDTO.cs | 1 - .../AnnotationSchema/DTOs/SeverityRangeDTO.cs | 9 -------- .../Annotations/Mappers/AnnotationProfile.cs | 1 - 6 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs delete mode 100644 DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs index c526ec11..7a0fbaed 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs @@ -9,7 +9,6 @@ public class CodeSmellDefinition public string Name { get; set; } public string Description { get; set; } public SnippetType SnippetType { get; set; } - public SeverityRange SeverityRange { get; set; } public List SeverityValues { get; set; } public List Heuristics { get; set; } @@ -30,7 +29,6 @@ public void Update(CodeSmellDefinition other) Name = other.Name; Description = other.Description; SnippetType = other.SnippetType; - SeverityRange = other.SeverityRange; SeverityValues = other.SeverityValues; } diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs b/DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs deleted file mode 100644 index 14310697..00000000 --- a/DataSetExplorer/Core/AnnotationSchema/Model/SeverityRange.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace DataSetExplorer.Core.AnnotationSchema.Model -{ - public class SeverityRange - { - public int Id { get; private set; } - public double MinValue { get; set; } - public double MaxValue { get; set; } - public double Step { get; set; } - - public SeverityRange(double minValue, double maxValue, double step) - { - MinValue = minValue; - MaxValue = maxValue; - Step = step; - } - - private SeverityRange() - { - } - } -} \ No newline at end of file diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index d103e9d9..c80ad291 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -18,7 +18,6 @@ public AnnotationSchemaDatabaseRepository(DataSetExplorerContext dbContext) public CodeSmellDefinition GetCodeSmellDefinition(int id) { return _dbContext.CodeSmellDefinitions - .Include(c => c.SeverityRange) .Include(c => c.Heuristics) .FirstOrDefault(c => c.Id == id); } @@ -31,8 +30,7 @@ public void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) public IEnumerable GetAllCodeSmellDefinitions() { - return _dbContext.CodeSmellDefinitions - .Include(c => c.SeverityRange); + return _dbContext.CodeSmellDefinitions; } public CodeSmellDefinition DeleteCodeSmellDefinition(int id) diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs index 7a6a005e..38ce8d8f 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/CodeSmellDefinitionDTO.cs @@ -8,7 +8,6 @@ public class CodeSmellDefinitionDTO public string Description { get; set; } public string SnippetType { get; set; } public List Heuristics { get; set; } - public SeverityRangeDTO SeverityRange { get; set; } public List SeverityValues { get; set; } } } diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs deleted file mode 100644 index 976c66fe..00000000 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityRangeDTO.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs -{ - public class SeverityRangeDTO - { - public double MinValue { get; set; } - public double MaxValue { get; set; } - public double Step { get; set; } - } -} diff --git a/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs b/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs index e10619ca..955fa97e 100644 --- a/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs +++ b/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs @@ -16,7 +16,6 @@ public AnnotationProfile() .ConstructUsing(src => new Annotation(src.CodeSmell, src.Severity, new Annotator(src.AnnotatorId), CreateHeuristics(src.ApplicableHeuristics), src.Note)); CreateMap(); CreateMap(); - CreateMap(); } private List CreateHeuristics(List heuristics) From 4e0990a4e431c921402380bdaaecb2e71beabdef Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 18 May 2022 19:49:34 +0200 Subject: [PATCH 08/46] feat[DE]: Get smells and heuristics from annotation schema --- .../AnnotationSchemaService.cs | 73 +++++++++++-------- .../IAnnotationSchemaService.cs | 7 +- .../AnnotationSchemaDatabaseRepository.cs | 30 ++++---- .../Repository/IAnnotationSchemaRepository.cs | 6 +- .../Database/DataSetExplorerContext.cs | 4 + .../AnnotationSchemaController.cs | 9 +++ .../Annotations/AnnotationController.cs | 17 +---- DataSetExplorer/appsettings.Development.json | 11 --- 8 files changed, 80 insertions(+), 77 deletions(-) diff --git a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index 731b2fce..3df6ab31 100644 --- a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Core.AnnotationSchema.Repository; using FluentResults; @@ -21,44 +22,17 @@ public Result GetCodeSmellDefinition(int id) return Result.Ok(codeSmellDefinition); } - public Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) - { - _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); - return Result.Ok(codeSmellDefinition); - } - - public Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic) - { - var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); - if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); - - codeSmellDefinition.Heuristics.Add(heuristic); - _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); - return Result.Ok(heuristic); - } - - public Result> GetHeuristicsForCodeSmell(int id) + public Result> GetAllCodeSmellDefinitions() { - var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); - if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); - return Result.Ok((IEnumerable)codeSmellDefinition.Heuristics); + return Result.Ok(_annotationSchemaRepository.GetAllCodeSmellDefinitions()); } - public Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) + public Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) { - var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(smellId); - if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {smellId} does not exist."); - - codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristicId)); _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); return Result.Ok(codeSmellDefinition); } - public Result> GetAllCodeSmellDefinitions() - { - return Result.Ok(_annotationSchemaRepository.GetAllCodeSmellDefinitions()); - } - public Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition) { var existingCodeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); @@ -74,11 +48,50 @@ public Result DeleteCodeSmellDefinition(int id) return Result.Ok(codeSmellDefinition); } + public Result> GetHeuristicsForCodeSmell(int id) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + return Result.Ok((IEnumerable)codeSmellDefinition.Heuristics); + } + + public Result> GetHeuristicsForEachCodeSmell() + { + IDictionary result = new Dictionary(); + var codeSmellDefinitions = _annotationSchemaRepository.GetAllCodeSmellDefinitions(); + foreach (var codeSmellDefinition in codeSmellDefinitions) + { + var heuristics = GetHeuristicsForCodeSmell(codeSmellDefinition.Id); + result[codeSmellDefinition.Name] = heuristics.Value.ToArray(); + } + return Result.Ok(result); + } + + public Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + + codeSmellDefinition.Heuristics.Add(heuristic); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + return Result.Ok(heuristic); + } + public Result UpdateHeuristicInCodeSmell(int id, HeuristicDefinition heuristic) { var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristic.Id)); return AddHeuristicToCodeSmell(id, heuristic); } + + public Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(smellId); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {smellId} does not exist."); + + codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristicId)); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + return Result.Ok(codeSmellDefinition); + } } } diff --git a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs index 770bd71f..f2cca196 100644 --- a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs @@ -7,13 +7,14 @@ namespace DataSetExplorer.Core.AnnotationSchema public interface IAnnotationSchemaService { Result GetCodeSmellDefinition(int id); - Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); Result> GetAllCodeSmellDefinitions(); + Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition); Result DeleteCodeSmellDefinition(int id); - Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic); Result> GetHeuristicsForCodeSmell(int id); - Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); + Result> GetHeuristicsForEachCodeSmell(); + Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic); Result UpdateHeuristicInCodeSmell(int id, HeuristicDefinition heuristic); + Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index c80ad291..ab3dd49b 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -21,16 +21,16 @@ public CodeSmellDefinition GetCodeSmellDefinition(int id) .Include(c => c.Heuristics) .FirstOrDefault(c => c.Id == id); } - - public void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) + + public IEnumerable GetAllCodeSmellDefinitions() { - _dbContext.Update(codeSmellDefinition); - _dbContext.SaveChanges(); + return _dbContext.CodeSmellDefinitions.ToList(); } - public IEnumerable GetAllCodeSmellDefinitions() + public void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition) { - return _dbContext.CodeSmellDefinitions; + _dbContext.Update(codeSmellDefinition); + _dbContext.SaveChanges(); } public CodeSmellDefinition DeleteCodeSmellDefinition(int id) @@ -40,16 +40,15 @@ public CodeSmellDefinition DeleteCodeSmellDefinition(int id) return deletedCodeSmell; } - public IEnumerable GetAllHeuristics() + public HeuristicDefinition GetHeuristic(int id) { - return _dbContext.HeuristicDefinitions; + return _dbContext.HeuristicDefinitions + .FirstOrDefault(h => h.Id == id); } - public HeuristicDefinition DeleteHeuristic(int id) + public IEnumerable GetAllHeuristics() { - var deletedHeuristic = _dbContext.HeuristicDefinitions.Remove(_dbContext.HeuristicDefinitions.Find(id)).Entity; - _dbContext.SaveChanges(); - return deletedHeuristic; + return _dbContext.HeuristicDefinitions; } public void SaveHeuristic(HeuristicDefinition heuristic) @@ -58,10 +57,11 @@ public void SaveHeuristic(HeuristicDefinition heuristic) _dbContext.SaveChanges(); } - public HeuristicDefinition GetHeuristic(int id) + public HeuristicDefinition DeleteHeuristic(int id) { - return _dbContext.HeuristicDefinitions - .FirstOrDefault(h => h.Id == id); + var deletedHeuristic = _dbContext.HeuristicDefinitions.Remove(_dbContext.HeuristicDefinitions.Find(id)).Entity; + _dbContext.SaveChanges(); + return deletedHeuristic; } } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs index 43802254..caaccbe1 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs @@ -6,12 +6,12 @@ namespace DataSetExplorer.Core.AnnotationSchema.Repository public interface IAnnotationSchemaRepository { CodeSmellDefinition GetCodeSmellDefinition(int id); - void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); IEnumerable GetAllCodeSmellDefinitions(); + void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); CodeSmellDefinition DeleteCodeSmellDefinition(int id); + HeuristicDefinition GetHeuristic(int id); IEnumerable GetAllHeuristics(); - HeuristicDefinition DeleteHeuristic(int id); void SaveHeuristic(HeuristicDefinition heuristic); - HeuristicDefinition GetHeuristic(int id); + HeuristicDefinition DeleteHeuristic(int id); } } diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index 6c44b212..f67de316 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -77,6 +77,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Entity() .Property(c => c.SnippetType) .HasConversion(); + + modelBuilder.Entity(codeSmell => { + codeSmell.HasIndex(c => c.Name).IsUnique(); + }); } } } diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs index 435180f2..f11d5e26 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs @@ -73,6 +73,15 @@ public IActionResult GetHeuristicsForCodeSmell([FromRoute] int id) return Ok(result.Value); } + [HttpGet] + [Route("heuristics")] + public IActionResult GetHeuristicsForEachCodeSmell() + { + var result = _annotationSchemaService.GetHeuristicsForEachCodeSmell(); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + [HttpPost] [Route("{id}/heuristics")] public IActionResult AddHeuristicToCodeSmell([FromRoute] int id, [FromBody] HeuristicDefinitionDTO heuristicDto) diff --git a/DataSetExplorer/UI/Controllers/Annotations/AnnotationController.cs b/DataSetExplorer/UI/Controllers/Annotations/AnnotationController.cs index 7112b24f..45d5b576 100644 --- a/DataSetExplorer/UI/Controllers/Annotations/AnnotationController.cs +++ b/DataSetExplorer/UI/Controllers/Annotations/AnnotationController.cs @@ -20,7 +20,8 @@ public class AnnotationController : ControllerBase private readonly IAnnotationService _annotationService; private readonly IDataSetAnalysisService _dataSetAnalysisService; - public AnnotationController(IMapper mapper, IConfiguration configuration, IAnnotationService annotationService, IDataSetAnalysisService dataSetAnalysisService) + public AnnotationController(IMapper mapper, IConfiguration configuration, IAnnotationService annotationService, + IDataSetAnalysisService dataSetAnalysisService) { _mapper = mapper; _configuration = configuration; @@ -28,13 +29,6 @@ public AnnotationController(IMapper mapper, IConfiguration configuration, IAnnot _dataSetAnalysisService = dataSetAnalysisService; } - [HttpGet] - [Route("available-code-smells")] - public IActionResult GetAllCodeSmells() - { - return Ok(_configuration.GetSection("Annotating:AvailableCodeSmells").Get>()); - } - [HttpGet] [Route("available-metrics")] public IActionResult GetAllMetrics() @@ -42,13 +36,6 @@ public IActionResult GetAllMetrics() return Ok(_configuration.GetSection("Annotating:AvailableMetrics").Get>()); } - [HttpGet] - [Route("available-heuristics")] - public IActionResult GetAllAvailableHeuristics() - { - return Ok(_configuration.GetSection("Annotating:AvailableHeuristics").Get>()); - } - [HttpPost] public IActionResult AddDataSetAnnotation([FromBody] AnnotationDTO annotation) { diff --git a/DataSetExplorer/appsettings.Development.json b/DataSetExplorer/appsettings.Development.json index 74401403..09f47bed 100644 --- a/DataSetExplorer/appsettings.Development.json +++ b/DataSetExplorer/appsettings.Development.json @@ -3,17 +3,6 @@ "GitClonePath": "../../ClonedProjects/" }, "Annotating": { - "AvailableCodeSmells": { - "Class": [ "Large_Class", "Data_Class", "Refused_Bequest" ], - "Function": [ "Long_Method", "Feature_Envy" ] - }, - "AvailableHeuristics": { - "Large_Class": [ "Class is too long.", "Class is too complex.", "Class has multiple concerns." ], - "Data_Class": [ "No logic in methods.", "Not DTO, DAO,..." ], - "Refused_Bequest": [ "Few parent members used.", "Many members overriden.", "Unnecessary hierarchy." ], - "Long_Method": [ "Function is too long.", "Function is too complex.", "Function does multiple things." ], - "Feature_Envy": [ "Function has method chains.", "Function uses foreign data.", "Function has few foreign providers.", "Function does not belong here (semantic)." ] - }, "AvailableMetrics": { "Class": [ "CLOC", "CELOC", "LCOM", "LCOM3", "LCOM4", "NMD", "NAD", "NMD_NAD", "WMC", "WMC_NO_CASE", "ATFD", "ATFD_10", "TCC", "CNOR", "CNOL", "CNOC", "CNOA", "NOPM", "NOPF", "DIT", "DCC", "CMNB", "RFC", "CBO", "NIC", "WOC", "NOPA", "NOPP", "WMCNAMM", "BUR", "BOvR" ], "Function": [ "CYCLO", "CYCLO_SWITCH", "MLOC", "MELOC", "NOP", "NOLV", "NOTC", "MNOL", "MNOR", "MNOC", "MNOA", "NONL", "NOSL", "NOMO", "NOPE", "NOLE", "MMNB", "NOUW", "AID" ] From 15dbdba832031e82e72eef9a3183c4b2b167d275 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Tue, 24 May 2022 15:12:21 +0200 Subject: [PATCH 09/46] feat[DE]: Get code smell definition by name --- .../Core/AnnotationSchema/AnnotationSchemaService.cs | 7 +++++++ .../Core/AnnotationSchema/IAnnotationSchemaService.cs | 1 + .../Repository/AnnotationSchemaDatabaseRepository.cs | 7 +++++++ .../Repository/IAnnotationSchemaRepository.cs | 1 + .../AnnotationSchema/AnnotationSchemaController.cs | 9 +++++++++ 5 files changed, 25 insertions(+) diff --git a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index 3df6ab31..1dde534b 100644 --- a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -22,6 +22,13 @@ public Result GetCodeSmellDefinition(int id) return Result.Ok(codeSmellDefinition); } + public Result GetCodeSmellDefinitionByName(string name) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinitionByName(name); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with name: {name} does not exist."); + return Result.Ok(codeSmellDefinition); + } + public Result> GetAllCodeSmellDefinitions() { return Result.Ok(_annotationSchemaRepository.GetAllCodeSmellDefinitions()); diff --git a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs index f2cca196..668c2e1f 100644 --- a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs @@ -7,6 +7,7 @@ namespace DataSetExplorer.Core.AnnotationSchema public interface IAnnotationSchemaService { Result GetCodeSmellDefinition(int id); + Result GetCodeSmellDefinitionByName(string name); Result> GetAllCodeSmellDefinitions(); Result CreateCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); Result UpdateCodeSmellDefinition(int id, CodeSmellDefinition codeSmellDefinition); diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index ab3dd49b..5cdbdfa0 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -22,6 +22,13 @@ public CodeSmellDefinition GetCodeSmellDefinition(int id) .FirstOrDefault(c => c.Id == id); } + public CodeSmellDefinition GetCodeSmellDefinitionByName(string name) + { + return _dbContext.CodeSmellDefinitions + .Include(c => c.Heuristics) + .FirstOrDefault(c => c.Name.Equals(name)); + } + public IEnumerable GetAllCodeSmellDefinitions() { return _dbContext.CodeSmellDefinitions.ToList(); diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs index caaccbe1..03c8fc19 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs @@ -6,6 +6,7 @@ namespace DataSetExplorer.Core.AnnotationSchema.Repository public interface IAnnotationSchemaRepository { CodeSmellDefinition GetCodeSmellDefinition(int id); + CodeSmellDefinition GetCodeSmellDefinitionByName(string name); IEnumerable GetAllCodeSmellDefinitions(); void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); CodeSmellDefinition DeleteCodeSmellDefinition(int id); diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs index f11d5e26..c0e7ef7b 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs @@ -36,6 +36,15 @@ public IActionResult GetCodeSmellDefinition([FromRoute] int id) return Ok(result.Value); } + [HttpGet] + [Route("name/{name}")] + public IActionResult GetCodeSmellDefinitionByName([FromRoute] string name) + { + var result = _annotationSchemaService.GetCodeSmellDefinitionByName(name); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + [HttpPost] public IActionResult CreateCodeSmellDefinition([FromBody] CodeSmellDefinitionDTO codeSmellDefinitionDto) { From 516b2ab2fcd487b88b444ff7f8ad96c44480dd89 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 26 May 2022 11:48:18 +0200 Subject: [PATCH 10/46] feat[DE]: Add annotator name --- DataSetExplorer/Core/Annotations/Model/Annotator.cs | 7 +++++-- DataSetExplorer/UI/ConsoleApp/DataSetIO.cs | 2 +- DataSetExplorerTests/Unit/ImporterTests.cs | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/DataSetExplorer/Core/Annotations/Model/Annotator.cs b/DataSetExplorer/Core/Annotations/Model/Annotator.cs index 5608b060..f474fa42 100644 --- a/DataSetExplorer/Core/Annotations/Model/Annotator.cs +++ b/DataSetExplorer/Core/Annotations/Model/Annotator.cs @@ -5,6 +5,7 @@ namespace DataSetExplorer.Core.Annotations.Model public class Annotator { public int Id { get; private set; } + public string Name { get; private set; } public int YearsOfExperience { get; private set; } public int Ranking { get; private set; } @@ -13,9 +14,10 @@ public Annotator(int id) Id = id; } - public Annotator(int id, int yearsOfExperience, int ranking) + public Annotator(int id, string name, int yearsOfExperience, int ranking) { Id = id; + Name = name; YearsOfExperience = yearsOfExperience; Ranking = ranking; } @@ -29,13 +31,14 @@ public bool Equals(Annotator other) { return other != null && Id == other.Id && + Name == other.Name && YearsOfExperience == other.YearsOfExperience && Ranking == other.Ranking; } public override int GetHashCode() { - return HashCode.Combine(Id, YearsOfExperience, Ranking); + return HashCode.Combine(Id, Name, YearsOfExperience, Ranking); } } } \ No newline at end of file diff --git a/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs b/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs index a2d49ed4..1478a44e 100644 --- a/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs +++ b/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs @@ -29,7 +29,7 @@ internal static List GetAnnotators() foreach (string line in lines) { string[] columns = line.Split(','); - annotators.Add(new Annotator(int.Parse(columns[0]), int.Parse(columns[1]), int.Parse(columns[2]))); + annotators.Add(new Annotator(int.Parse(columns[0]), columns[1], int.Parse(columns[2]), int.Parse(columns[3]))); } return annotators; } diff --git a/DataSetExplorerTests/Unit/ImporterTests.cs b/DataSetExplorerTests/Unit/ImporterTests.cs index 9fbf213c..c04b9a1c 100644 --- a/DataSetExplorerTests/Unit/ImporterTests.cs +++ b/DataSetExplorerTests/Unit/ImporterTests.cs @@ -38,9 +38,9 @@ public void Imports_data_set_instances_and_annotations() var annotators = new List() { - new Annotator(1, 6, 1), - new Annotator(2, 2, 2), - new Annotator(3, 2, 3) + new Annotator(1, "Nikola Luburic", 6, 1), + new Annotator(2, "Simona Prokic", 2, 2), + new Annotator(3, "Katarina-Glorija Grujic", 2, 3) }; JoinInstancesAndAnnotators(distinctClasses.ToList(), annotators); From 23cca1df87fb1e59117e95a8b2f9b6ef8e9522c6 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Fri, 27 May 2022 17:35:38 +0200 Subject: [PATCH 11/46] feat[DE]: Add snippet type to code smell --- .../Core/Annotations/Model/CodeSmell.cs | 40 ++++--------------- .../ViewModel/ColumnHeuristicsModel.cs | 11 ++--- .../Core/DataSets/DataSetCreationService.cs | 2 +- .../Core/DataSets/IDataSetCreationService.cs | 3 +- .../Core/DataSets/InstanceFilter.cs | 4 +- .../Repository/DataSetDatabaseRepository.cs | 11 ++--- .../DataSets/Repository/IDataSetRepository.cs | 3 +- .../Database/DataSetExplorerContext.cs | 5 +++ DataSetExplorerTests/Unit/ImporterTests.cs | 4 +- 9 files changed, 31 insertions(+), 52 deletions(-) diff --git a/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs b/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs index d6c47f09..9e8b61bc 100644 --- a/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs +++ b/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs @@ -1,15 +1,18 @@ -using System; -using System.Collections.Generic; -using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Core.DataSets.Model; namespace DataSetExplorer.Core.Annotations.Model { public class CodeSmell { + public CodeSmell(string smell, SnippetType snippetType) + { + Name = smell; + SnippetType = snippetType; + } + public CodeSmell(string smell) { Name = smell; - Validate(); } private CodeSmell() @@ -18,34 +21,7 @@ private CodeSmell() public int Id { get; private set; } public string Name { get; private set; } - - public void Validate() - { - switch (Name) - { - case "Large_Class": - case "Long_Method": - case "Feature_Envy": - case "Data_Class": - case "Refused_Bequest": - return; - default: - throw new InvalidOperationException("Unsupported code smell type."); - } - } - - public List RelevantSnippetTypes() - { - return Name switch - { - "Large_Class" => new List {SnippetType.Class}, - "Long_Method" => new List {SnippetType.Function}, - "Feature_Envy" => new List { SnippetType.Function }, - "Data_Class" => new List { SnippetType.Class }, - "Refused_Bequest" => new List { SnippetType.Class }, - _ => null - }; - } + public SnippetType SnippetType { get; private set; } public override int GetHashCode() { diff --git a/DataSetExplorer/Core/DataSetSerializer/ViewModel/ColumnHeuristicsModel.cs b/DataSetExplorer/Core/DataSetSerializer/ViewModel/ColumnHeuristicsModel.cs index 4c0090c6..f52521c5 100644 --- a/DataSetExplorer/Core/DataSetSerializer/ViewModel/ColumnHeuristicsModel.cs +++ b/DataSetExplorer/Core/DataSetSerializer/ViewModel/ColumnHeuristicsModel.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.DataSets.Model; namespace DataSetExplorer.Core.DataSetSerializer.ViewModel { @@ -12,11 +13,11 @@ internal ColumnHeuristicsModel() { _heuristics = new Dictionary>(); //TODO: Load from DB or config. - _heuristics.Add(new CodeSmell("Large_Class"), LCHeuristics()); - _heuristics.Add(new CodeSmell("Long_Method"), LMHeuristics()); - _heuristics.Add(new CodeSmell("Feature_Envy"), FEHeuristics()); - _heuristics.Add(new CodeSmell("Data_Class"), DCHeuristics()); - _heuristics.Add(new CodeSmell("Refused_Bequest"), RBHeuristics()); + _heuristics.Add(new CodeSmell("Large_Class", SnippetType.Class), LCHeuristics()); + _heuristics.Add(new CodeSmell("Long_Method", SnippetType.Function), LMHeuristics()); + _heuristics.Add(new CodeSmell("Feature_Envy", SnippetType.Function), FEHeuristics()); + _heuristics.Add(new CodeSmell("Data_Class", SnippetType.Class), DCHeuristics()); + _heuristics.Add(new CodeSmell("Refused_Bequest", SnippetType.Class), RBHeuristics()); } internal List GetHeuristics(CodeSmell smell) diff --git a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs index f2322dc0..9c0d2894 100644 --- a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs @@ -138,7 +138,7 @@ private string ExportToExcel(string basePath, string projectName, NewSpreadSheet return fileName; } - public Result>> GetDataSetCodeSmells(int id) + public Result> GetDataSetCodeSmells(int id) { var codeSmells = _dataSetRepository.GetDataSetCodeSmells(id); if (codeSmells == default) return Result.Fail($"DataSet with id: {id} does not exist."); diff --git a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs index cd98fc42..342b4f06 100644 --- a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Core.DataSetSerializer.ViewModel; using DataSetExplorer.UI.Controllers.Dataset.DTOs; @@ -18,7 +19,7 @@ public interface IDataSetCreationService Result GetDataSetForExport(int id); Result> GetAllDataSets(); Result GetDataSetProject(int id); - Result>> GetDataSetCodeSmells(int id); + Result> GetDataSetCodeSmells(int id); Result DeleteDataSet(int id); Result UpdateDataSet(DataSet dataset); Result DeleteDataSetProject(int id); diff --git a/DataSetExplorer/Core/DataSets/InstanceFilter.cs b/DataSetExplorer/Core/DataSets/InstanceFilter.cs index 92ad41ef..ac61fe06 100644 --- a/DataSetExplorer/Core/DataSets/InstanceFilter.cs +++ b/DataSetExplorer/Core/DataSets/InstanceFilter.cs @@ -10,7 +10,7 @@ namespace DataSetExplorer.Core.DataSets internal class InstanceFilter { public List SmellFilters { get; } - + public InstanceFilter(List smellFilters) { SmellFilters = smellFilters; @@ -33,7 +33,7 @@ public List FilterInstances(CodeSmell codeSmell, List instan private static bool ValidSnippetTypeForSmell(Instance instance, CodeSmell codeSmell) { - return codeSmell.RelevantSnippetTypes()[0].ToString().Equals(instance.Type.ToString()); + return codeSmell.SnippetType.Equals(instance.Type); } private static bool InstancePassesMetricThresholds(Instance instance, List metricsThreholds) diff --git a/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs index e6abccc1..95a12933 100644 --- a/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using AutoMapper.Internal; +using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Infrastructure.Database; using DataSetExplorer.UI.Controllers.Dataset.DTOs.Summary; @@ -97,17 +98,11 @@ public DataSet Update(DataSet dataSet) return updatedDataset; } - public Dictionary> GetDataSetCodeSmells(int id) + public List GetDataSetCodeSmells(int id) { - var result = new Dictionary>(); var dataSet = _dbContext.DataSets.Include(d => d.SupportedCodeSmells).FirstOrDefault(s => s.Id == id); if (dataSet == null) return null; - - foreach (var smell in dataSet.SupportedCodeSmells) - { - result.Add(smell.Name, smell.RelevantSnippetTypes().Select(t => t.ToString()).ToList()); - } - return result; + return dataSet.SupportedCodeSmells; } public DataSet Delete(int id) diff --git a/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs index c9f09b32..534f209e 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.UI.Controllers.Dataset.DTOs.Summary; @@ -12,7 +13,7 @@ public interface IDataSetRepository DataSet GetDataSetWithProjectsAndCodeSmells(int id); IEnumerable GetAll(); DataSet Update(DataSet dataSet); - Dictionary> GetDataSetCodeSmells(int id); + List GetDataSetCodeSmells(int id); DataSet Delete(int id); } } diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index f67de316..3b826d86 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -78,6 +78,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(c => c.SnippetType) .HasConversion(); + modelBuilder + .Entity() + .Property(c => c.SnippetType) + .HasConversion(); + modelBuilder.Entity(codeSmell => { codeSmell.HasIndex(c => c.Name).IsUnique(); }); diff --git a/DataSetExplorerTests/Unit/ImporterTests.cs b/DataSetExplorerTests/Unit/ImporterTests.cs index c04b9a1c..a12ef4fa 100644 --- a/DataSetExplorerTests/Unit/ImporterTests.cs +++ b/DataSetExplorerTests/Unit/ImporterTests.cs @@ -16,8 +16,8 @@ public void Imports_data_set_instances_and_annotations() { var codeSmells = new List { - new CodeSmell("Long_Method"), - new CodeSmell("Large_Class") + new CodeSmell("Long_Method", SnippetType.Function), + new CodeSmell("Large_Class", SnippetType.Class) }; var dataSet = new DataSet("Test", codeSmells); ExcelImporter importer = new ExcelImporter(new ExcelFactory().GetTestDataFolder()); From 097255a15505db002bd156bd7ab1d86b54dae354 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Fri, 27 May 2022 18:40:08 +0200 Subject: [PATCH 12/46] feat[DE]: Return created project --- DataSetExplorer/Core/DataSets/DataSetCreationService.cs | 4 ++-- DataSetExplorer/Core/DataSets/IDataSetCreationService.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs index 9c0d2894..362609eb 100644 --- a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs @@ -36,7 +36,7 @@ public Result CreateEmptyDataSet(string dataSetName, List co return Result.Ok(dataSet); } - public Result AddProjectToDataSet(int dataSetId, string basePath, DataSetProject project, List smellFilters, ProjectBuildSettingsDTO projectBuildSettings) + public Result AddProjectToDataSet(int dataSetId, string basePath, DataSetProject project, List smellFilters, ProjectBuildSettingsDTO projectBuildSettings) { var initialDataSet = _dataSetRepository.GetDataSetWithProjectsAndCodeSmells(dataSetId); if (initialDataSet == default) return Result.Fail($"DataSet with id: {dataSetId} does not exist."); @@ -45,7 +45,7 @@ public Result AddProjectToDataSet(int dataSetId, string basePath, DataS initialDataSet.AddProject(project); _dataSetRepository.Update(initialDataSet); - return Result.Ok(initialDataSet); + return Result.Ok(project); } public Result CreateDataSetSpreadsheet(string dataSetName, string basePath, IDictionary projects, List codeSmells) diff --git a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs index 342b4f06..788b8808 100644 --- a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs @@ -14,7 +14,7 @@ public interface IDataSetCreationService Result CreateDataSetSpreadsheet(string dataSetName, string basePath, IDictionary projects, List codeSmells); Result CreateDataSetSpreadsheet(string dataSetName, string basePath, IDictionary projects, List codeSmells, NewSpreadSheetColumnModel columnModel); Result CreateEmptyDataSet(string dataSetName, List codeSmells); - Result AddProjectToDataSet(int dataSetId, string basePath, DataSetProject project, List smellFilters, ProjectBuildSettingsDTO projectBuildSettings); + Result AddProjectToDataSet(int dataSetId, string basePath, DataSetProject project, List smellFilters, ProjectBuildSettingsDTO projectBuildSettings); Result GetDataSet(int id); Result GetDataSetForExport(int id); Result> GetAllDataSets(); From 1ece616133e63bb643dcb57896a2b2c0ad141830 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Tue, 31 May 2022 15:21:10 +0200 Subject: [PATCH 13/46] feat[DE]: Delete heuristic after schema update --- .../AnnotationSchemaService.cs | 10 ++++++- .../Core/Annotations/AnnotationService.cs | 30 +++++++++++++++++-- .../Core/Annotations/IAnnotationService.cs | 2 ++ .../Core/DataSets/DataSetCreationService.cs | 6 ++++ .../Core/DataSets/IDataSetCreationService.cs | 1 + .../Core/DataSets/IInstanceService.cs | 3 ++ .../Core/DataSets/InstanceService.cs | 24 +++++++++++++-- .../AnnotationDatabaseRepository.cs | 7 +++++ .../Repository/DataSetDatabaseRepository.cs | 25 +++++++++++++++- .../Repository/IAnnotationRepository.cs | 1 + .../DataSets/Repository/IDataSetRepository.cs | 1 + 11 files changed, 103 insertions(+), 7 deletions(-) diff --git a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index 1dde534b..f7a46079 100644 --- a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using DataSetExplorer.Core.Annotations; using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Core.AnnotationSchema.Repository; using FluentResults; @@ -9,10 +10,13 @@ namespace DataSetExplorer.Core.AnnotationSchema public class AnnotationSchemaService : IAnnotationSchemaService { private readonly IAnnotationSchemaRepository _annotationSchemaRepository; + private readonly IAnnotationService _annotationService; - public AnnotationSchemaService(IAnnotationSchemaRepository annotationSchemaRepository) + public AnnotationSchemaService(IAnnotationSchemaRepository annotationSchemaRepository, + IAnnotationService annotationService) { _annotationSchemaRepository = annotationSchemaRepository; + _annotationService = annotationService; } public Result GetCodeSmellDefinition(int id) @@ -96,8 +100,12 @@ public Result DeleteHeuristicFromCodeSmell(int smellId, int var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(smellId); if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {smellId} does not exist."); + var heuristic = codeSmellDefinition.Heuristics.Find(h => h.Id == heuristicId); codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristicId)); _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + + _annotationService.UpdateAnnotationsAfterHeuristicDeletion(codeSmellDefinition, heuristic); + return Result.Ok(codeSmellDefinition); } } diff --git a/DataSetExplorer/Core/Annotations/AnnotationService.cs b/DataSetExplorer/Core/Annotations/AnnotationService.cs index fbcfcd05..c2fec260 100644 --- a/DataSetExplorer/Core/Annotations/AnnotationService.cs +++ b/DataSetExplorer/Core/Annotations/AnnotationService.cs @@ -1,7 +1,9 @@ -using AutoMapper; -using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.Core.DataSets; using DataSetExplorer.Core.DataSets.Repository; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.Annotations { @@ -9,11 +11,14 @@ public class AnnotationService : IAnnotationService { private readonly IInstanceRepository _instanceRepository; private readonly IAnnotationRepository _annotationRepository; + private readonly IInstanceService _instanceService; - public AnnotationService(IMapper mapper, IInstanceRepository instanceRepository, IAnnotationRepository annotationRepository) + public AnnotationService(IInstanceRepository instanceRepository, IAnnotationRepository annotationRepository, + IInstanceService instanceService) { _instanceRepository = instanceRepository; _annotationRepository = annotationRepository; + _instanceService = instanceService; } public Result AddAnnotation(Annotation annotation, int instanceId, int annotatorId) @@ -41,5 +46,24 @@ public Result UpdateAnnotation(Annotation changed, int annotationId, _annotationRepository.Update(annotation); return Result.Ok(annotation); } + + public Result UpdateAnnotationsAfterHeuristicDeletion(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristic) + { + foreach (var instance in _instanceService.GetInstancesForSmell(codeSmellDefinition.Name).Value) + { + RemoveDeletedHeuristicFromAnnotations(instance.Annotations, heuristic); + } + return Result.Ok(); + } + + private void RemoveDeletedHeuristicFromAnnotations(ISet annotations, HeuristicDefinition heuristic) + { + foreach (var annotation in annotations) + { + var appliedHeuristic = annotation.ApplicableHeuristics.Find(h => h.Description.Equals(heuristic.Name)); + if (appliedHeuristic == null) continue; + _annotationRepository.DeleteHeuristic(appliedHeuristic.Id); + } + } } } diff --git a/DataSetExplorer/Core/Annotations/IAnnotationService.cs b/DataSetExplorer/Core/Annotations/IAnnotationService.cs index 0cf6b5bd..ba61a7ab 100644 --- a/DataSetExplorer/Core/Annotations/IAnnotationService.cs +++ b/DataSetExplorer/Core/Annotations/IAnnotationService.cs @@ -1,4 +1,5 @@ using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; using FluentResults; namespace DataSetExplorer.Core.Annotations @@ -7,5 +8,6 @@ public interface IAnnotationService { Result AddAnnotation(Annotation annotation, int instanceId, int annotatorId); Result UpdateAnnotation(Annotation changed, int annotationId, int annotatorId); + Result UpdateAnnotationsAfterHeuristicDeletion(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristicId); } } diff --git a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs index 362609eb..9ee09f87 100644 --- a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs @@ -87,6 +87,12 @@ public Result> GetAllDataSets() return Result.Ok(dataSets); } + public Result> GetDataSetsByCodeSmell(string codeSmellName) + { + var dataSets = _dataSetRepository.GetAllByCodeSmell(codeSmellName); + return Result.Ok(dataSets); + } + public Result GetDataSetProject(int id) { var project = _projectRepository.Get(id); diff --git a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs index 788b8808..12ff3b12 100644 --- a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs @@ -18,6 +18,7 @@ public interface IDataSetCreationService Result GetDataSet(int id); Result GetDataSetForExport(int id); Result> GetAllDataSets(); + Result> GetDataSetsByCodeSmell(string codeSmellName); Result GetDataSetProject(int id); Result> GetDataSetCodeSmells(int id); Result DeleteDataSet(int id); diff --git a/DataSetExplorer/Core/DataSets/IInstanceService.cs b/DataSetExplorer/Core/DataSets/IInstanceService.cs index a2989d8d..21328c37 100644 --- a/DataSetExplorer/Core/DataSets/IInstanceService.cs +++ b/DataSetExplorer/Core/DataSets/IInstanceService.cs @@ -1,6 +1,8 @@ +using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.UI.Controllers.Dataset.DTOs; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.DataSets { @@ -8,5 +10,6 @@ public interface IInstanceService { Result GetInstanceWithRelatedInstances(int id); Result GetInstanceWithAnnotations(int id); + Result> GetInstancesForSmell(string codeSmellName); } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/InstanceService.cs b/DataSetExplorer/Core/DataSets/InstanceService.cs index 67f01b40..4cfdf1fd 100644 --- a/DataSetExplorer/Core/DataSets/InstanceService.cs +++ b/DataSetExplorer/Core/DataSets/InstanceService.cs @@ -1,18 +1,20 @@ -using AutoMapper; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Core.DataSets.Repository; using DataSetExplorer.UI.Controllers.Dataset.DTOs; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.DataSets { public class InstanceService : IInstanceService { private readonly IInstanceRepository _instanceRepository; + private readonly IDataSetCreationService _dataSetCreationService; - public InstanceService(IMapper mapper, IInstanceRepository instanceRepository) + public InstanceService(IInstanceRepository instanceRepository, IDataSetCreationService dataSetCreationService) { _instanceRepository = instanceRepository; + _dataSetCreationService = dataSetCreationService; } public Result GetInstanceWithRelatedInstances(int id) @@ -28,5 +30,23 @@ public Result GetInstanceWithAnnotations(int id) if (instance == default) return Result.Fail($"Instance with id: {id} does not exist."); return Result.Ok(instance); } + + public Result> GetInstancesForSmell(string codeSmellName) + { + List instances = new List(); + var datasets = _dataSetCreationService.GetDataSetsByCodeSmell(codeSmellName).Value; + foreach (var dataset in datasets) + { + foreach (var project in dataset.Projects) + { + foreach (var candidate in project.CandidateInstances) + { + if (!candidate.CodeSmell.Name.Equals(codeSmellName)) continue; + instances.AddRange(candidate.Instances); + } + } + } + return Result.Ok(instances); + } } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs index 28ab510e..4980003a 100644 --- a/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs @@ -36,5 +36,12 @@ public void Update(Annotation annotation) _dbContext.Update(annotation); _dbContext.SaveChanges(); } + + public SmellHeuristic DeleteHeuristic(int id) + { + var deletedHeuristic = _dbContext.SmellHeuristics.Remove(_dbContext.SmellHeuristics.Find(id)).Entity; + _dbContext.SaveChanges(); + return deletedHeuristic; + } } } diff --git a/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs index 95a12933..71cabd49 100644 --- a/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/DataSetDatabaseRepository.cs @@ -72,7 +72,7 @@ public DataSet GetDataSetWithProjectsAndCodeSmells(int id) { return _dbContext.DataSets .Include(d => d.SupportedCodeSmells) - .Include(s => s.Projects) + .Include(d => d.Projects) .FirstOrDefault(d => d.Id == id); } @@ -83,6 +83,29 @@ public IEnumerable GetAll() return result; } + public IEnumerable GetAllByCodeSmell(string codeSmellName) + { + var datasets = _dbContext.DataSets + .Include(d => d.SupportedCodeSmells) + .Include(d => d.Projects) + .ThenInclude(p => p.CandidateInstances) + .ThenInclude(c => c.Instances) + .ThenInclude(i => i.Annotations) + .ThenInclude(a => a.Annotator) + .Include(d => d.Projects) + .ThenInclude(p => p.CandidateInstances) + .ThenInclude(c => c.Instances) + .ThenInclude(i => i.Annotations) + .ThenInclude(a => a.ApplicableHeuristics); + + var result = new List(); + foreach(var dataset in datasets) + { + if (dataset.SupportedCodeSmells.Exists(s => s.Name.Equals(codeSmellName))) result.Add(dataset); + } + return result; + } + private DatasetSummaryDTO GetDatasetSummary(int id) { var dataset = _dbContext.DataSets.FirstOrDefault(d => d.Id == id); diff --git a/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs index a4b3bdc0..2555f2d3 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs @@ -8,5 +8,6 @@ public interface IAnnotationRepository Annotator GetAnnotator(int id); CodeSmell GetCodeSmell(string name); void Update(Annotation annotation); + SmellHeuristic DeleteHeuristic(int id); } } diff --git a/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs index 534f209e..eb174be2 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IDataSetRepository.cs @@ -12,6 +12,7 @@ public interface IDataSetRepository DataSet GetDataSetForExport(int id); DataSet GetDataSetWithProjectsAndCodeSmells(int id); IEnumerable GetAll(); + IEnumerable GetAllByCodeSmell(string codeSmellName); DataSet Update(DataSet dataSet); List GetDataSetCodeSmells(int id); DataSet Delete(int id); From f0279fc30bde856db6b510392b933c46ab33cff6 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Tue, 31 May 2022 17:12:16 +0200 Subject: [PATCH 14/46] feat[DE]: Cascade deletion after code smell definition deletion --- .../AnnotationSchema/AnnotationSchemaService.cs | 6 +++++- DataSetExplorer/Core/DataSets/IInstanceService.cs | 1 + DataSetExplorer/Core/DataSets/InstanceService.cs | 14 +++++++++++++- .../Repository/AnnotationDatabaseRepository.cs | 15 ++++++++++++++- .../DataSets/Repository/IAnnotationRepository.cs | 4 ++++ .../DataSets/Repository/IInstanceRepository.cs | 2 ++ .../Repository/InstanceDatabaseRepository.cs | 13 +++++++++++++ .../Database/DataSetExplorerContext.cs | 1 + 8 files changed, 53 insertions(+), 3 deletions(-) diff --git a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index f7a46079..bd456ab0 100644 --- a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -3,6 +3,7 @@ using DataSetExplorer.Core.Annotations; using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Core.AnnotationSchema.Repository; +using DataSetExplorer.Core.DataSets; using FluentResults; namespace DataSetExplorer.Core.AnnotationSchema @@ -11,12 +12,14 @@ public class AnnotationSchemaService : IAnnotationSchemaService { private readonly IAnnotationSchemaRepository _annotationSchemaRepository; private readonly IAnnotationService _annotationService; + private readonly IInstanceService _instanceService; public AnnotationSchemaService(IAnnotationSchemaRepository annotationSchemaRepository, - IAnnotationService annotationService) + IAnnotationService annotationService, IInstanceService instanceService) { _annotationSchemaRepository = annotationSchemaRepository; _annotationService = annotationService; + _instanceService = instanceService; } public Result GetCodeSmellDefinition(int id) @@ -56,6 +59,7 @@ public Result UpdateCodeSmellDefinition(int id, CodeSmellDe public Result DeleteCodeSmellDefinition(int id) { var codeSmellDefinition = _annotationSchemaRepository.DeleteCodeSmellDefinition(id); + _instanceService.DeleteCandidateInstancesForSmell(codeSmellDefinition); return Result.Ok(codeSmellDefinition); } diff --git a/DataSetExplorer/Core/DataSets/IInstanceService.cs b/DataSetExplorer/Core/DataSets/IInstanceService.cs index 21328c37..5605fc13 100644 --- a/DataSetExplorer/Core/DataSets/IInstanceService.cs +++ b/DataSetExplorer/Core/DataSets/IInstanceService.cs @@ -11,5 +11,6 @@ public interface IInstanceService Result GetInstanceWithRelatedInstances(int id); Result GetInstanceWithAnnotations(int id); Result> GetInstancesForSmell(string codeSmellName); + Result> DeleteCandidateInstancesForSmell(CodeSmellDefinition codeSmellDefinition); } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/InstanceService.cs b/DataSetExplorer/Core/DataSets/InstanceService.cs index 4cfdf1fd..c877d633 100644 --- a/DataSetExplorer/Core/DataSets/InstanceService.cs +++ b/DataSetExplorer/Core/DataSets/InstanceService.cs @@ -1,3 +1,4 @@ +using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Core.DataSets.Repository; using DataSetExplorer.UI.Controllers.Dataset.DTOs; @@ -10,11 +11,14 @@ public class InstanceService : IInstanceService { private readonly IInstanceRepository _instanceRepository; private readonly IDataSetCreationService _dataSetCreationService; + private readonly IAnnotationRepository _annotationRepository; - public InstanceService(IInstanceRepository instanceRepository, IDataSetCreationService dataSetCreationService) + public InstanceService(IInstanceRepository instanceRepository, IDataSetCreationService dataSetCreationService, + IAnnotationRepository annotationRepository) { _instanceRepository = instanceRepository; _dataSetCreationService = dataSetCreationService; + _annotationRepository = annotationRepository; } public Result GetInstanceWithRelatedInstances(int id) @@ -48,5 +52,13 @@ public Result> GetInstancesForSmell(string codeSmellName) } return Result.Ok(instances); } + + public Result> DeleteCandidateInstancesForSmell(CodeSmellDefinition codeSmellDefinition) + { + var codeSmells = _annotationRepository.GetCodeSmellsByDefinition(codeSmellDefinition); + var deletedCandidates = _instanceRepository.DeleteCandidateInstancesBySmell(codeSmells); + _annotationRepository.DeleteCodeSmells(codeSmells); + return Result.Ok(deletedCandidates); + } } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs index 4980003a..8b5fcc7d 100644 --- a/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs @@ -1,5 +1,7 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; using DataSetExplorer.Infrastructure.Database; using Microsoft.EntityFrameworkCore; @@ -43,5 +45,16 @@ public SmellHeuristic DeleteHeuristic(int id) _dbContext.SaveChanges(); return deletedHeuristic; } + + public List GetCodeSmellsByDefinition(CodeSmellDefinition codeSmellDefinition) + { + return _dbContext.CodeSmells.Where(s => s.Name.Equals(codeSmellDefinition.Name)).ToList(); + } + + public void DeleteCodeSmells(List codeSmells) + { + _dbContext.CodeSmells.RemoveRange(codeSmells); + _dbContext.SaveChanges(); + } } } diff --git a/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs index 2555f2d3..35adfc3e 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs @@ -1,4 +1,6 @@ using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; +using System.Collections.Generic; namespace DataSetExplorer.Core.DataSets.Repository { @@ -9,5 +11,7 @@ public interface IAnnotationRepository CodeSmell GetCodeSmell(string name); void Update(Annotation annotation); SmellHeuristic DeleteHeuristic(int id); + List GetCodeSmellsByDefinition(CodeSmellDefinition codeSmellDefinition); + void DeleteCodeSmells(List codeSmells); } } diff --git a/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs index c0da305e..bf9ae4ed 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.UI.Controllers.Dataset.DTOs; @@ -12,5 +13,6 @@ public interface IInstanceRepository IEnumerable GetAnnotatedInstances(int projectId); void Update(Instance instance); Instance GetInstanceWithAnnotations(int id); + List DeleteCandidateInstancesBySmell(List codeSmells); } } diff --git a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs index 15e33d6b..ba7a351a 100644 --- a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Infrastructure.Database; using DataSetExplorer.UI.Controllers.Dataset.DTOs; @@ -73,5 +74,17 @@ public void Update(Instance instance) _dbContext.Update(instance); _dbContext.SaveChanges(); } + + public List DeleteCandidateInstancesBySmell(List codeSmells) + { + var candidatesToDelete = new List(); + foreach (var codeSmell in codeSmells) + { + candidatesToDelete.AddRange(_dbContext.SmellCandidateInstances.Where(c => c.CodeSmell.Id == codeSmell.Id)); + } + _dbContext.SmellCandidateInstances.RemoveRange(candidatesToDelete); + _dbContext.SaveChanges(); + return candidatesToDelete; + } } } diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index 3b826d86..cd12e955 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -20,6 +20,7 @@ public class DataSetExplorerContext : DbContext public DbSet DataSetProjects { get; set; } public DbSet CodeSmellDefinitions { get; set; } public DbSet HeuristicDefinitions { get; set; } + public DbSet SmellCandidateInstances { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { } From 864f8dfd8d7b2ab82083a61995a3af5725417d67 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 2 Jun 2022 14:24:15 +0200 Subject: [PATCH 15/46] feat[DE]: Change severity type; Manage severity in schema --- .../AnnotationConsistencyService.cs | 8 +- .../Core/AnnotationConsistency/AnovaTest.cs | 23 +++--- .../IAnnotationConsistencyService.cs | 9 +-- .../IAnnotatorsConsistencyTester.cs | 2 +- .../IMetricsSignificanceTester.cs | 2 +- .../Core/AnnotationConsistency/ManovaTest.cs | 26 ++++--- .../AnnotationSchemaService.cs | 75 ++++++++++++++++++- .../IAnnotationSchemaService.cs | 5 ++ .../Model/CodeSmellDefinition.cs | 4 +- .../Model/HeuristicDefinition.cs | 4 +- .../Model/SeverityDefinition.cs | 25 +++++++ .../AnnotationSchemaDatabaseRepository.cs | 26 +++++++ .../Repository/IAnnotationSchemaRepository.cs | 4 + .../Core/Annotations/AnnotationService.cs | 68 +++++++++++++++++ .../Annotations/DataSetAnalysisService.cs | 4 +- .../Core/Annotations/IAnnotationService.cs | 8 +- .../Core/Annotations/Model/Annotation.cs | 11 +-- .../Core/Annotations/Model/CodeSmell.cs | 2 +- .../Core/Annotations/Model/SmellHeuristic.cs | 2 +- .../AnnotationConsistencyByMetricsExporter.cs | 6 +- .../Core/DataSetSerializer/ExcelImporter.cs | 5 +- .../DataSetSerializer/TextFileExporter.cs | 2 +- .../Core/DataSets/Model/Instance.cs | 10 +-- .../AnnotationDatabaseRepository.cs | 22 +++++- .../Repository/IAnnotationRepository.cs | 3 + .../Repository/InstanceDatabaseRepository.cs | 6 +- .../Database/DataSetExplorerContext.cs | 8 +- .../AnnotationConsistencySubmenu.cs | 8 +- .../AnnotationConsistencyController.cs | 4 +- .../AnnotationSchemaController.cs | 47 ++++++++++++ .../DTOs/SeverityDefinitionDTO.cs | 9 +++ .../Annotations/DTOs/AnnotationDTO.cs | 2 +- .../Annotations/Mappers/AnnotationProfile.cs | 1 + 33 files changed, 366 insertions(+), 75 deletions(-) create mode 100644 DataSetExplorer/Core/AnnotationSchema/Model/SeverityDefinition.cs create mode 100644 DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityDefinitionDTO.cs diff --git a/DataSetExplorer/Core/AnnotationConsistency/AnnotationConsistencyService.cs b/DataSetExplorer/Core/AnnotationConsistency/AnnotationConsistencyService.cs index 53bcfcaa..77a1d663 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/AnnotationConsistencyService.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/AnnotationConsistencyService.cs @@ -16,7 +16,7 @@ public AnnotationConsistencyService(FullDataSetFactory fullDataSetFactory) _fullDataSetFactory = fullDataSetFactory; } - public Result CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int severity, IDictionary projects, List annotators) + public Result CheckMetricsSignificanceBetweenAnnotatorsForSeverity(string severity, IDictionary projects, List annotators) { var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projects, annotators, annotatorId: null); IMetricsSignificanceTester tester = new AnovaTest(); @@ -42,7 +42,7 @@ public Result CheckMetricsSignificanceInAnnotationsForAnnotator(int anno return Result.Ok(); } - public Result CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int severity, IDictionary projects, List annotators) + public Result CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(string severity, IDictionary projects, List annotators) { var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projects, annotators, annotatorId: null); IAnnotatorsConsistencyTester tester = new ManovaTest(); @@ -67,7 +67,7 @@ public Result> CheckAnnotationConsistencyForAnnotator return tester.TestConsistencyOfSingleAnnotator(annotatorId, instancesGroupedBySmells); } - public Result> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, int severity) + public Result> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, string severity) { var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projectId, annotatorId: null); IAnnotatorsConsistencyTester tester = new ManovaTest(); @@ -81,7 +81,7 @@ public Result>> CheckMetricsSignif return tester.TestForSingleAnnotator(annotatorId, instancesGroupedBySmells); } - public Result>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, int severity) + public Result>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, string severity) { var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projectId, annotatorId: null); IMetricsSignificanceTester tester = new AnovaTest(); diff --git a/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs b/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs index 89138393..bd3bc943 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs @@ -22,15 +22,18 @@ public class AnovaTest : IMetricsSignificanceTester public Result>> TestForSingleAnnotator(int annotatorId, List instancesGroupedBySmells) { - return Test(annotatorId, instancesGroupedBySmells, TestCodeSmellForAnnotator); - } - - public Result>> TestBetweenAnnotators(int severity, List instancesGroupedBySmells) - { - return Test(severity, instancesGroupedBySmells, TestCodeSmellBetweenAnnotators); + var results = new Dictionary>(); + foreach (var codeSmellGroup in instancesGroupedBySmells) + { + var codeSmell = codeSmellGroup.CodeSmell.Name; + var metrics = codeSmellGroup.Instances.First().MetricFeatures.Keys.ToList(); + var instances = codeSmellGroup.Instances; + results[codeSmell] = TestCodeSmellForAnnotator(annotatorId, instances, codeSmell, metrics); + } + return Result.Ok(results); } - private Result>> Test(int id, List instancesGroupedBySmells, TestCodeSmellDelegate testCodeSmell) + public Result>> TestBetweenAnnotators(string severity, List instancesGroupedBySmells) { var results = new Dictionary>(); foreach (var codeSmellGroup in instancesGroupedBySmells) @@ -38,7 +41,7 @@ private Result>> Test(int id, List var codeSmell = codeSmellGroup.CodeSmell.Name; var metrics = codeSmellGroup.Instances.First().MetricFeatures.Keys.ToList(); var instances = codeSmellGroup.Instances; - results[codeSmell] = testCodeSmell(id, instances, codeSmell, metrics); + results[codeSmell] = TestCodeSmellBetweenAnnotators(severity, instances, codeSmell, metrics); } return Result.Ok(results); } @@ -55,7 +58,7 @@ private Dictionary TestCodeSmellForAnnotator(int annotatorId, Li return results; } - private Dictionary TestCodeSmellBetweenAnnotators(int severity, List instances, string codeSmell, List metrics) + private Dictionary TestCodeSmellBetweenAnnotators(string severity, List instances, string codeSmell, List metrics) { var results = new Dictionary(); string exportedAnnotationsFile = ExportAnnotationsForSeverity(severity, instances, codeSmell); @@ -75,7 +78,7 @@ private string ExportAnnotationsForAnnotator(int annotatorId, List ins return exportedAnnotationsFile; } - private string ExportAnnotationsForSeverity(int severity, List instances, string codeSmell) + private string ExportAnnotationsForSeverity(string severity, List instances, string codeSmell) { var exportedAnnotationsFile = "MetricsSignificance_" + codeSmell + "_Severity_" + severity; var exporter = new AnnotationConsistencyByMetricsExporter(_annotatedInstancesFolderPath); diff --git a/DataSetExplorer/Core/AnnotationConsistency/IAnnotationConsistencyService.cs b/DataSetExplorer/Core/AnnotationConsistency/IAnnotationConsistencyService.cs index b0fe08f9..36447dc7 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/IAnnotationConsistencyService.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/IAnnotationConsistencyService.cs @@ -6,14 +6,13 @@ namespace DataSetExplorer.Core.AnnotationConsistency { public interface IAnnotationConsistencyService { - Result CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int severity, IDictionary projects, List annotators); + Result CheckMetricsSignificanceBetweenAnnotatorsForSeverity(string severity, IDictionary projects, List annotators); Result CheckMetricsSignificanceInAnnotationsForAnnotator(int annotatorId, IDictionary projects, List annotators); - Result CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int severity, IDictionary projects, List annotators); + Result CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(string severity, IDictionary projects, List annotators); Result CheckAnnotationConsistencyForAnnotator(int annotatorId, IDictionary projects, List annotators); - Result> CheckAnnotationConsistencyForAnnotator(int projectId, int annotatorId); - Result> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, int severity); + Result> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, string severity); Result>> CheckMetricsSignificanceInAnnotationsForAnnotator(int projectId, int annotatorId); - Result>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, int severity); + Result>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, string severity); } } diff --git a/DataSetExplorer/Core/AnnotationConsistency/IAnnotatorsConsistencyTester.cs b/DataSetExplorer/Core/AnnotationConsistency/IAnnotatorsConsistencyTester.cs index 06a654dd..fa5f2227 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/IAnnotatorsConsistencyTester.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/IAnnotatorsConsistencyTester.cs @@ -6,7 +6,7 @@ namespace DataSetExplorer.Core.AnnotationConsistency { internal interface IAnnotatorsConsistencyTester { - public Result> TestConsistencyBetweenAnnotators(int severity, List instancesGroupedBySmells); + public Result> TestConsistencyBetweenAnnotators(string severity, List instancesGroupedBySmells); public Result> TestConsistencyOfSingleAnnotator(int annotatorId, List instancesGroupedBySmells); } diff --git a/DataSetExplorer/Core/AnnotationConsistency/IMetricsSignificanceTester.cs b/DataSetExplorer/Core/AnnotationConsistency/IMetricsSignificanceTester.cs index 2efd463a..5522cbfb 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/IMetricsSignificanceTester.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/IMetricsSignificanceTester.cs @@ -8,6 +8,6 @@ internal interface IMetricsSignificanceTester { public Result>> TestForSingleAnnotator(int annotatorId, List instancesGroupedBySmells); - public Result>> TestBetweenAnnotators(int severity, List instancesGroupedBySmells); + public Result>> TestBetweenAnnotators(string severity, List instancesGroupedBySmells); } } \ No newline at end of file diff --git a/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs b/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs index 190021f8..0f470e1b 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs @@ -20,18 +20,22 @@ public class ManovaTest : IAnnotatorsConsistencyTester private delegate void PrepareTestDelegate(int id, List instances, string codeSmell, List metrics); - public Result> TestConsistencyBetweenAnnotators(int severity, List instancesGroupedBySmells) + public Result> TestConsistencyBetweenAnnotators(string severity, List instancesGroupedBySmells) { - return Test(severity, instancesGroupedBySmells, PrepareDataForBetweenAnnotators); - } + var results = new Dictionary(); + foreach (var codeSmellGroup in instancesGroupedBySmells) + { + var codeSmell = codeSmellGroup.CodeSmell.Name; + var metrics = codeSmellGroup.Instances.First().MetricFeatures.Keys.ToList(); + var instances = codeSmellGroup.Instances; - public Result> TestConsistencyOfSingleAnnotator(int annotatorId, List instancesGroupedBySmells) - { - return Test(annotatorId, instancesGroupedBySmells, PrepareDataForSingleAnnotator); + PrepareDataForBetweenAnnotators(severity, instances, codeSmell, metrics); + results[codeSmell] = StartProcess(); + } + return Result.Ok(results); } - private Result> Test(int id, List instancesGroupedBySmells, - PrepareTestDelegate prepareTest) + public Result> TestConsistencyOfSingleAnnotator(int annotatorId, List instancesGroupedBySmells) { var results = new Dictionary(); foreach (var codeSmellGroup in instancesGroupedBySmells) @@ -40,13 +44,13 @@ private Result> Test(int id, List instances, string codeSmell, List metrics) + private void PrepareDataForBetweenAnnotators(string severity, List instances, string codeSmell, List metrics) { string exportedAnnotatorsFile = ExportAnnotatorsForSeverity(severity, instances, codeSmell); SetupTestArguments(exportedAnnotatorsFile, metrics, "Annotator"); @@ -57,7 +61,7 @@ private void PrepareDataForSingleAnnotator(int annotatorId, List insta SetupTestArguments(exportedAnnotationsFile, metrics, "Annotation"); } - private string ExportAnnotatorsForSeverity(int severity, List instances, string codeSmell) + private string ExportAnnotatorsForSeverity(string severity, List instances, string codeSmell) { var exportedAnnotatorsFile = "SanityCheck_" + codeSmell + "_Severity_" + severity; var exporter = new AnnotationConsistencyByMetricsExporter(_annotatedInstancesFolderPath); diff --git a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs index bd456ab0..330ee9b8 100644 --- a/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/AnnotationSchemaService.cs @@ -51,8 +51,20 @@ public Result UpdateCodeSmellDefinition(int id, CodeSmellDe { var existingCodeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); if (existingCodeSmellDefinition == default) return Result.Fail($"CodeSmellDefinition with id: {id} does not exist."); + + var codeSmells = _annotationService.GetCodeSmellsByDefinition(existingCodeSmellDefinition).Value; + foreach (var codeSmell in codeSmells) + { + if (codeSmell.Name.Equals(existingCodeSmellDefinition.Name)) + { + codeSmell.Name = codeSmellDefinition.Name; + _annotationService.UpdateCodeSmell(codeSmell); + } + } + existingCodeSmellDefinition.Update(codeSmellDefinition); _annotationSchemaRepository.SaveCodeSmellDefinition(existingCodeSmellDefinition); + return Result.Ok(codeSmellDefinition); } @@ -95,8 +107,12 @@ public Result AddHeuristicToCodeSmell(int id, HeuristicDefi public Result UpdateHeuristicInCodeSmell(int id, HeuristicDefinition heuristic) { var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); - codeSmellDefinition.Heuristics.RemoveAt(codeSmellDefinition.Heuristics.FindIndex(h => h.Id == heuristic.Id)); - return AddHeuristicToCodeSmell(id, heuristic); + var oldHeuristic = codeSmellDefinition.Heuristics.Find(h => h.Id == heuristic.Id); + codeSmellDefinition.Heuristics.Remove(oldHeuristic); + codeSmellDefinition.Heuristics.Add(heuristic); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + _annotationService.UpdateAnnotationsAfterHeuristicUpdate(codeSmellDefinition, heuristic, oldHeuristic); + return Result.Ok(heuristic); } public Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId) @@ -112,5 +128,60 @@ public Result DeleteHeuristicFromCodeSmell(int smellId, int return Result.Ok(codeSmellDefinition); } + + public Result> GetSeveritiesForCodeSmell(int id) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + return Result.Ok((IEnumerable)codeSmellDefinition.Severities); + } + + public Result> GetSeveritiesForEachCodeSmell() + { + IDictionary result = new Dictionary(); + var codeSmellDefinitions = _annotationSchemaRepository.GetAllCodeSmellDefinitions(); + foreach (var codeSmellDefinition in codeSmellDefinitions) + { + var severities = GetSeveritiesForCodeSmell(codeSmellDefinition.Id); + result[codeSmellDefinition.Name] = severities.Value.ToArray(); + } + return Result.Ok(result); + } + + public Result AddSeverityToCodeSmell(int id, SeverityDefinition severity) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {id} does not exist."); + + codeSmellDefinition.Severities.Add(severity); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + return Result.Ok(severity); + } + + public Result UpdateSeverityInCodeSmell(int id, SeverityDefinition severity) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(id); + var oldSeverity = codeSmellDefinition.Severities.Find(s => s.Id == severity.Id); + codeSmellDefinition.Severities.RemoveAt(codeSmellDefinition.Severities.FindIndex(s => s.Id == severity.Id)); + codeSmellDefinition.Severities.Add(severity); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + + _annotationService.UpdateAnnotationsAfterSeverityUpdate(codeSmellDefinition, severity, oldSeverity); + return Result.Ok(severity); + } + + public Result DeleteSeverityFromCodeSmell(int smellId, int severityId) + { + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinition(smellId); + if (codeSmellDefinition == default) return Result.Fail($"Code smell definition with id: {smellId} does not exist."); + + var severity = codeSmellDefinition.Severities.Find(s => s.Id == severityId); + codeSmellDefinition.Severities.RemoveAt(codeSmellDefinition.Severities.FindIndex(s => s.Id == severityId)); + _annotationSchemaRepository.SaveCodeSmellDefinition(codeSmellDefinition); + + _annotationService.UpdateAnnotationsAfterSeverityDeletion(codeSmellDefinition, severity); + + return Result.Ok(codeSmellDefinition); + } } } diff --git a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs index 668c2e1f..71481fce 100644 --- a/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs +++ b/DataSetExplorer/Core/AnnotationSchema/IAnnotationSchemaService.cs @@ -17,5 +17,10 @@ public interface IAnnotationSchemaService Result AddHeuristicToCodeSmell(int id, HeuristicDefinition heuristic); Result UpdateHeuristicInCodeSmell(int id, HeuristicDefinition heuristic); Result DeleteHeuristicFromCodeSmell(int smellId, int heuristicId); + Result> GetSeveritiesForCodeSmell(int id); + Result> GetSeveritiesForEachCodeSmell(); + Result AddSeverityToCodeSmell(int id, SeverityDefinition severity); + Result UpdateSeverityInCodeSmell(int id, SeverityDefinition severity); + Result DeleteSeverityFromCodeSmell(int smellId, int severityId); } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs index 7a0fbaed..953d8cac 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/CodeSmellDefinition.cs @@ -9,7 +9,7 @@ public class CodeSmellDefinition public string Name { get; set; } public string Description { get; set; } public SnippetType SnippetType { get; set; } - public List SeverityValues { get; set; } + public List Severities { get; set; } public List Heuristics { get; set; } public CodeSmellDefinition(string name, string description, SnippetType snippetType) @@ -18,6 +18,7 @@ public CodeSmellDefinition(string name, string description, SnippetType snippetT Description = description; SnippetType = snippetType; Heuristics = new List(); + Severities = new List(); } private CodeSmellDefinition() @@ -29,7 +30,6 @@ public void Update(CodeSmellDefinition other) Name = other.Name; Description = other.Description; SnippetType = other.SnippetType; - SeverityValues = other.SeverityValues; } public override int GetHashCode() diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs index 346b264e..cc52bb7e 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Model/HeuristicDefinition.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace DataSetExplorer.Core.AnnotationSchema.Model +namespace DataSetExplorer.Core.AnnotationSchema.Model { public class HeuristicDefinition { diff --git a/DataSetExplorer/Core/AnnotationSchema/Model/SeverityDefinition.cs b/DataSetExplorer/Core/AnnotationSchema/Model/SeverityDefinition.cs new file mode 100644 index 00000000..1f322c19 --- /dev/null +++ b/DataSetExplorer/Core/AnnotationSchema/Model/SeverityDefinition.cs @@ -0,0 +1,25 @@ +namespace DataSetExplorer.Core.AnnotationSchema.Model +{ + public class SeverityDefinition + { + public int Id { get; private set; } + public string Value { get; set; } + public string Description { get; set; } + + public SeverityDefinition(string value, string description) + { + Value = value; + Description = description; + } + + private SeverityDefinition() + { + } + + public void Update(SeverityDefinition other) + { + Value = other.Value; + Description = other.Description; + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index 5cdbdfa0..7452d6a6 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -19,6 +19,7 @@ public CodeSmellDefinition GetCodeSmellDefinition(int id) { return _dbContext.CodeSmellDefinitions .Include(c => c.Heuristics) + .Include(c => c.Severities) .FirstOrDefault(c => c.Id == id); } @@ -26,6 +27,7 @@ public CodeSmellDefinition GetCodeSmellDefinitionByName(string name) { return _dbContext.CodeSmellDefinitions .Include(c => c.Heuristics) + .Include(c => c.Severities) .FirstOrDefault(c => c.Name.Equals(name)); } @@ -70,5 +72,29 @@ public HeuristicDefinition DeleteHeuristic(int id) _dbContext.SaveChanges(); return deletedHeuristic; } + + public SeverityDefinition GetSeverity(int id) + { + return _dbContext.SeverityDefinitions + .FirstOrDefault(s => s.Id == id); + } + + public IEnumerable GetAllSeverities() + { + return _dbContext.SeverityDefinitions; + } + + public void SaveSeverity(SeverityDefinition severity) + { + _dbContext.Update(severity); + _dbContext.SaveChanges(); + } + + public SeverityDefinition DeleteSeverity(int id) + { + var deletedSeverity = _dbContext.SeverityDefinitions.Remove(_dbContext.SeverityDefinitions.Find(id)).Entity; + _dbContext.SaveChanges(); + return deletedSeverity; + } } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs index 03c8fc19..72aa8e06 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs @@ -14,5 +14,9 @@ public interface IAnnotationSchemaRepository IEnumerable GetAllHeuristics(); void SaveHeuristic(HeuristicDefinition heuristic); HeuristicDefinition DeleteHeuristic(int id); + SeverityDefinition GetSeverity(int id); + IEnumerable GetAllSeverities(); + void SaveSeverity(SeverityDefinition severity); + SeverityDefinition DeleteSeverity(int id); } } diff --git a/DataSetExplorer/Core/Annotations/AnnotationService.cs b/DataSetExplorer/Core/Annotations/AnnotationService.cs index c2fec260..9dbcc69c 100644 --- a/DataSetExplorer/Core/Annotations/AnnotationService.cs +++ b/DataSetExplorer/Core/Annotations/AnnotationService.cs @@ -65,5 +65,73 @@ private void RemoveDeletedHeuristicFromAnnotations(ISet annotations, _annotationRepository.DeleteHeuristic(appliedHeuristic.Id); } } + + public Result UpdateAnnotationsAfterSeverityDeletion(CodeSmellDefinition codeSmellDefinition, SeverityDefinition severity) + { + foreach (var instance in _instanceService.GetInstancesForSmell(codeSmellDefinition.Name).Value) + { + DeleteAnnotationsWithDeletedSeverity(instance.Annotations, severity); + } + return Result.Ok(); + } + + private void DeleteAnnotationsWithDeletedSeverity(ISet annotations, SeverityDefinition severity) + { + foreach (var annotation in annotations) + { + if (annotation.Severity.Equals(severity.Value)) _annotationRepository.Delete(annotation.Id); + } + } + + public Result UpdateAnnotationsAfterSeverityUpdate(CodeSmellDefinition codeSmellDefinition, SeverityDefinition severity, SeverityDefinition oldSeverity) + { + foreach (var instance in _instanceService.GetInstancesForSmell(codeSmellDefinition.Name).Value) + { + if (instance.Annotations.Count > 0) UpdateAnnotationsWithUpdatedSeverity(instance.Annotations, severity, oldSeverity); + } + return Result.Ok(); + } + + private void UpdateAnnotationsWithUpdatedSeverity(ISet annotations, SeverityDefinition severity, SeverityDefinition oldSeverity) + { + foreach (var annotation in annotations) + { + if (annotation.Severity.Equals(oldSeverity.Value)) + { + annotation.Severity = severity.Value; + _annotationRepository.Update(annotation); + } + } + } + + public Result UpdateAnnotationsAfterHeuristicUpdate(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristic, HeuristicDefinition oldHeuristic) + { + foreach (var instance in _instanceService.GetInstancesForSmell(codeSmellDefinition.Name).Value) + { + UpdateAnnotationsWithUpdatedHeuristic(instance.Annotations, heuristic, oldHeuristic); + } + return Result.Ok(); + } + + private void UpdateAnnotationsWithUpdatedHeuristic(ISet annotations, HeuristicDefinition heuristic, HeuristicDefinition oldHeuristic) + { + foreach (var annotation in annotations) + { + var appliedHeuristic = annotation.ApplicableHeuristics.Find(h => h.Description.Equals(oldHeuristic.Name)); + if (appliedHeuristic == null) continue; + appliedHeuristic.Description = heuristic.Name; + _annotationRepository.UpdateAppliedHeuristic(appliedHeuristic); + } + } + + public Result> GetCodeSmellsByDefinition(CodeSmellDefinition codeSmellDefinition) + { + return Result.Ok(_annotationRepository.GetCodeSmellsByDefinition(codeSmellDefinition)); + } + + public Result UpdateCodeSmell(CodeSmell codeSmell) + { + return Result.Ok(_annotationRepository.UpdateCodeSmell(codeSmell)); + } } } diff --git a/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs b/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs index b49c2723..4c28718a 100644 --- a/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs +++ b/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs @@ -82,7 +82,7 @@ public Result ExportMembersFromAnnotatedClasses(IDictionary>(); + var classesGroupedBySeverity = new Dictionary>(); var annotatedInstances = LoadAnnotatedInstances(datasetPath); foreach (var projectUrl in projects.Keys) @@ -101,7 +101,7 @@ public Result ExportMembersFromAnnotatedClasses(IDictionary> classesGroupedBySeverity, List annotatedInstances, CaDETProject cadetProject) + private static void GroupInstancesBySeverity(Dictionary> classesGroupedBySeverity, List annotatedInstances, CaDETProject cadetProject) { foreach (var instance in annotatedInstances) { diff --git a/DataSetExplorer/Core/Annotations/IAnnotationService.cs b/DataSetExplorer/Core/Annotations/IAnnotationService.cs index ba61a7ab..3c450ab6 100644 --- a/DataSetExplorer/Core/Annotations/IAnnotationService.cs +++ b/DataSetExplorer/Core/Annotations/IAnnotationService.cs @@ -1,6 +1,7 @@ using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.AnnotationSchema.Model; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.Annotations { @@ -8,6 +9,11 @@ public interface IAnnotationService { Result AddAnnotation(Annotation annotation, int instanceId, int annotatorId); Result UpdateAnnotation(Annotation changed, int annotationId, int annotatorId); - Result UpdateAnnotationsAfterHeuristicDeletion(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristicId); + Result UpdateAnnotationsAfterHeuristicDeletion(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristic); + Result UpdateAnnotationsAfterSeverityDeletion(CodeSmellDefinition codeSmellDefinition, SeverityDefinition severity); + Result UpdateAnnotationsAfterSeverityUpdate(CodeSmellDefinition codeSmellDefinition, SeverityDefinition severity, SeverityDefinition oldSeverity); + Result UpdateAnnotationsAfterHeuristicUpdate(CodeSmellDefinition codeSmellDefinition, HeuristicDefinition heuristic, HeuristicDefinition oldHeuristic); + Result> GetCodeSmellsByDefinition(CodeSmellDefinition codeSmellDefinition); + Result UpdateCodeSmell(CodeSmell codeSmell); } } diff --git a/DataSetExplorer/Core/Annotations/Model/Annotation.cs b/DataSetExplorer/Core/Annotations/Model/Annotation.cs index f9564cb6..797fe00a 100644 --- a/DataSetExplorer/Core/Annotations/Model/Annotation.cs +++ b/DataSetExplorer/Core/Annotations/Model/Annotation.cs @@ -7,24 +7,23 @@ public class Annotation { public int Id { get; private set; } public CodeSmell InstanceSmell { get; private set; } - public int Severity { get; private set; } + public string Severity { get; set; } public List ApplicableHeuristics { get; private set; } public Annotator Annotator { get; set; } public string Note { get; private set; } - - public Annotation(string instanceSmell, int severity, Annotator annotator, List applicableHeuristics, String note) : + + public Annotation(string instanceSmell, string severity, Annotator annotator, List applicableHeuristics, String note) : this(new CodeSmell(instanceSmell), severity, annotator, applicableHeuristics, note) { } - public Annotation(CodeSmell instanceSmell, int severity, Annotator annotator, List applicableHeuristics, String note) + public Annotation(CodeSmell instanceSmell, string severity, Annotator annotator, List applicableHeuristics, String note) { InstanceSmell = instanceSmell; Severity = severity; Annotator = annotator; ApplicableHeuristics = applicableHeuristics; Note = note; - Validate(); } private Annotation() @@ -42,9 +41,7 @@ public void Update(Annotation other) private void Validate() { - if (Severity < 0 || Severity > 3) throw new ArgumentException("Accepted severity ranges from 0 to 3, but was " + Severity); if (Annotator.Id == 0) throw new ArgumentException("Annotator ID is required."); - if (Severity > 0 && ApplicableHeuristics.Count < 1) throw new ArgumentException("Annotations made by " + Annotator.Id + " with severity " + Severity + " must have at least one applicable heuristic."); } public override int GetHashCode() => (Annotator.Id, InstanceSmell: InstanceSmell.Name).GetHashCode(); diff --git a/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs b/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs index 9e8b61bc..1846d9ee 100644 --- a/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs +++ b/DataSetExplorer/Core/Annotations/Model/CodeSmell.cs @@ -20,7 +20,7 @@ private CodeSmell() } public int Id { get; private set; } - public string Name { get; private set; } + public string Name { get; set; } public SnippetType SnippetType { get; private set; } public override int GetHashCode() diff --git a/DataSetExplorer/Core/Annotations/Model/SmellHeuristic.cs b/DataSetExplorer/Core/Annotations/Model/SmellHeuristic.cs index 5f034d3d..f629b5cb 100644 --- a/DataSetExplorer/Core/Annotations/Model/SmellHeuristic.cs +++ b/DataSetExplorer/Core/Annotations/Model/SmellHeuristic.cs @@ -3,7 +3,7 @@ public class SmellHeuristic { public int Id { get; private set; } - public string Description { get; private set; } + public string Description { get; set; } public bool IsApplicable { get; private set; } public string ReasonForApplicability { get; private set; } diff --git a/DataSetExplorer/Core/DataSetSerializer/AnnotationConsistencyByMetricsExporter.cs b/DataSetExplorer/Core/DataSetSerializer/AnnotationConsistencyByMetricsExporter.cs index 58ce3426..42ff227b 100644 --- a/DataSetExplorer/Core/DataSetSerializer/AnnotationConsistencyByMetricsExporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/AnnotationConsistencyByMetricsExporter.cs @@ -28,7 +28,7 @@ public void ExportAnnotationsFromAnnotator(int annotatorId, List insta Serialize(fileName); } - public void ExportAnnotatorsForSeverity(int severity, List instances, + public void ExportAnnotatorsForSeverity(string severity, List instances, string fileName) { InitializeExcelSheet(_multipleAnnotatorsTemplatePath); @@ -53,14 +53,14 @@ private void PopulateTemplateForAnnotator(int annotatorId, List instan } } - private void PopulateTemplateForSeverity(int severity, List instances) + private void PopulateTemplateForSeverity(string severity, List instances) { var j = 0; foreach (var instance in instances) { foreach (var annotation in instance.Annotations) { - if (annotation.Severity == severity) + if (annotation.Severity.Equals(severity)) { _sheet.Cells[2 + j, 1].Value = annotation.Annotator.Id; PopulateMetrics(instance.MetricFeatures, 2 + j, 2); diff --git a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs index 29a1fd85..c960d8d2 100644 --- a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs @@ -26,6 +26,7 @@ public ExcelImporter(string sourceFolder) /// /// Name of the returned dataset project. /// A dataset project constructed from one or more excel documents. + public DataSetProject Import(string projectName) { var project = new DataSetProject(projectName); @@ -107,7 +108,7 @@ internal List ImportAnnotatedInstancesFromDataSet(string path) var finalAnnotation = sheet.Cells["AD" + row].Text; Instance instance = new Instance(codeSnippetId, projectLink); // Dummy values for DataSetAnnotation constructor to pass validations (the final annotation is the only important parameter in this case). - Annotation annotation = new Annotation(new CodeSmell("Large_Class"), int.Parse(finalAnnotation), new Annotator(1), new List() { new SmellHeuristic("", true, "") }, ""); + Annotation annotation = new Annotation(new CodeSmell("Large_Class", SnippetType.Class), finalAnnotation, new Annotator(1), new List() { new SmellHeuristic("", true, "") }, ""); instance.AddAnnotation(annotation); instances.Add(instance); } @@ -119,7 +120,7 @@ private static Annotation GetAnnotation(ExcelWorksheet sheet, int row) { try { - var smellSeverity = int.Parse(sheet.Cells["C" + row].Text); + var smellSeverity = sheet.Cells["C" + row].Text; var annotatorId = int.Parse(sheet.Cells["C2"].Text); var codeSmell = sheet.Cells["B2"].Text; var heuristics = GetHeuristics(sheet, row); diff --git a/DataSetExplorer/Core/DataSetSerializer/TextFileExporter.cs b/DataSetExplorer/Core/DataSetSerializer/TextFileExporter.cs index 20552a45..c2480315 100644 --- a/DataSetExplorer/Core/DataSetSerializer/TextFileExporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/TextFileExporter.cs @@ -56,7 +56,7 @@ private void SaveSnippetLinkToFile(List instances, string fileName) WriteToFile(sb.ToString(), fileName); } - internal void ExportMembersFromAnnotatedClasses(Dictionary> classesGroupedBySeverity, List annotatedClasses) + internal void ExportMembersFromAnnotatedClasses(Dictionary> classesGroupedBySeverity, List annotatedClasses) { foreach (var severity in classesGroupedBySeverity.Keys) { diff --git a/DataSetExplorer/Core/DataSets/Model/Instance.cs b/DataSetExplorer/Core/DataSets/Model/Instance.cs index 9d8b998a..de8a0c27 100644 --- a/DataSetExplorer/Core/DataSets/Model/Instance.cs +++ b/DataSetExplorer/Core/DataSets/Model/Instance.cs @@ -92,14 +92,14 @@ internal string GetSortedAnnotatorIds() return string.Join(",", list); } - public int GetFinalAnnotation() + public string GetFinalAnnotation() { var majorityVote = GetMajorityAnnotation(); - if (majorityVote != null) return (int)majorityVote; + if (majorityVote != null) return majorityVote; return GetAnnotationFromMostExperiencedAnnotator(); } - private int? GetMajorityAnnotation() + private string GetMajorityAnnotation() { var annotationsGroupedBySeverity = Annotations.GroupBy(a => a.Severity); if (HasMajoritySeverityVote(annotationsGroupedBySeverity)) @@ -112,14 +112,14 @@ public int GetFinalAnnotation() } private bool HasMajoritySeverityVote( - IEnumerable> annotationsGroupedBySeverity) + IEnumerable> annotationsGroupedBySeverity) { var severityCounts = annotationsGroupedBySeverity.Select(group => group.Count()); if (severityCounts.Count() == 1) return true; return severityCounts.Any(count => count != severityCounts.First()); } - private int GetAnnotationFromMostExperiencedAnnotator() + private string GetAnnotationFromMostExperiencedAnnotator() { return Annotations.OrderBy(a => a.Annotator.Ranking).First().Severity; } diff --git a/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs index 8b5fcc7d..05b516ed 100644 --- a/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/AnnotationDatabaseRepository.cs @@ -18,7 +18,7 @@ public AnnotationDatabaseRepository(DataSetExplorerContext dbContext) public Annotation Get(int id) { - return _dbContext.DataSetAnnotations + return _dbContext.Annotations .Include(a => a.Annotator) .Include(a => a.ApplicableHeuristics) .FirstOrDefault(a => a.Id == id); @@ -39,6 +39,13 @@ public void Update(Annotation annotation) _dbContext.SaveChanges(); } + public Annotation Delete(int id) + { + var deleted = _dbContext.Annotations.Remove(_dbContext.Annotations.Find(id)).Entity; + _dbContext.SaveChanges(); + return deleted; + } + public SmellHeuristic DeleteHeuristic(int id) { var deletedHeuristic = _dbContext.SmellHeuristics.Remove(_dbContext.SmellHeuristics.Find(id)).Entity; @@ -56,5 +63,18 @@ public void DeleteCodeSmells(List codeSmells) _dbContext.CodeSmells.RemoveRange(codeSmells); _dbContext.SaveChanges(); } + + public void UpdateAppliedHeuristic(SmellHeuristic heuristic) + { + _dbContext.Update(heuristic); + _dbContext.SaveChanges(); + } + + public CodeSmell UpdateCodeSmell(CodeSmell codeSmell) + { + var updated = _dbContext.Update(codeSmell).Entity; + _dbContext.SaveChanges(); + return updated; + } } } diff --git a/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs index 35adfc3e..a454bbb7 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IAnnotationRepository.cs @@ -10,8 +10,11 @@ public interface IAnnotationRepository Annotator GetAnnotator(int id); CodeSmell GetCodeSmell(string name); void Update(Annotation annotation); + Annotation Delete(int id); SmellHeuristic DeleteHeuristic(int id); List GetCodeSmellsByDefinition(CodeSmellDefinition codeSmellDefinition); void DeleteCodeSmells(List codeSmells); + void UpdateAppliedHeuristic(SmellHeuristic heuristic); + CodeSmell UpdateCodeSmell(CodeSmell codeSmell); } } diff --git a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs index ba7a351a..5653d2f1 100644 --- a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs @@ -19,19 +19,19 @@ public InstanceDatabaseRepository(DataSetExplorerContext dbContext) public Instance Get(int id) { - return _dbContext.DataSetInstances.Include(i => i.Annotations).FirstOrDefault(i => i.Id == id); + return _dbContext.Instances.Include(i => i.Annotations).FirstOrDefault(i => i.Id == id); } public InstanceDTO GetInstanceWithRelatedInstances(int id) { - return new InstanceDTO(_dbContext.DataSetInstances + return new InstanceDTO(_dbContext.Instances .Include(i => i.RelatedInstances) .FirstOrDefault(i => i.Id == id)); } public Instance GetInstanceWithAnnotations(int id) { - return _dbContext.DataSetInstances + return _dbContext.Instances .Include(i => i.Annotations).ThenInclude(a => a.Annotator) .Include(i => i.Annotations).ThenInclude(a => a.ApplicableHeuristics) .FirstOrDefault(i => i.Id == id); diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index cd12e955..ff5ddbfe 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -14,12 +14,13 @@ public class DataSetExplorerContext : DbContext public DbSet Annotators { get; set; } public DbSet CodeSmells { get; set; } public DbSet SmellHeuristics { get; set; } - public DbSet DataSetAnnotations { get; set; } - public DbSet DataSetInstances { get; set; } + public DbSet Annotations { get; set; } + public DbSet Instances { get; set; } public DbSet DataSets { get; set; } public DbSet DataSetProjects { get; set; } public DbSet CodeSmellDefinitions { get; set; } public DbSet HeuristicDefinitions { get; set; } + public DbSet SeverityDefinitions { get; set; } public DbSet SmellCandidateInstances { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { @@ -74,6 +75,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasOne().WithMany(d => d.Heuristics) .OnDelete(DeleteBehavior.Cascade); + modelBuilder.Entity().HasOne().WithMany(d => d.Severities) + .OnDelete(DeleteBehavior.Cascade); + modelBuilder .Entity() .Property(c => c.SnippetType) diff --git a/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs b/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs index 272d7d8a..6df164cb 100644 --- a/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs +++ b/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs @@ -30,16 +30,16 @@ internal void CheckAnnotationsConsistency() if (annotatorId.HasValue) _annotationConsistencyService.CheckAnnotationConsistencyForAnnotator(annotatorId.Value, projects, annotators); break; case "2": - var severityId = GetId("Severity"); - if (severityId.HasValue) _annotationConsistencyService.CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(severityId.Value, projects, annotators); + var severity = ConsoleIO.GetAnswerOnQuestion("Severity: "); + if (!severity.Equals("")) _annotationConsistencyService.CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(severity, projects, annotators); break; case "3": annotatorId = GetId("Annotator"); if (annotatorId.HasValue) _annotationConsistencyService.CheckMetricsSignificanceInAnnotationsForAnnotator(annotatorId.Value, projects, annotators); break; case "4": - severityId = GetId("Severity"); - if (severityId.HasValue) _annotationConsistencyService.CheckMetricsSignificanceBetweenAnnotatorsForSeverity(severityId.Value, projects, annotators); + severity = ConsoleIO.GetAnswerOnQuestion("Severity: "); + if (!severity.Equals("")) _annotationConsistencyService.CheckMetricsSignificanceBetweenAnnotatorsForSeverity(severity, projects, annotators); break; case "x": break; diff --git a/DataSetExplorer/UI/Controllers/AnnotationConsistency/AnnotationConsistencyController.cs b/DataSetExplorer/UI/Controllers/AnnotationConsistency/AnnotationConsistencyController.cs index cfb8bc0b..c584ab3e 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationConsistency/AnnotationConsistencyController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationConsistency/AnnotationConsistencyController.cs @@ -24,7 +24,7 @@ public IActionResult GetAnnotationConsistencyForAnnotator([FromRoute] int projec [HttpGet] [Route("annotators/{projectId}/{severity}")] - public IActionResult GetAnnotationConsistencyBetweenAnnotatorsForSeverity([FromRoute] int projectId, [FromRoute] int severity) + public IActionResult GetAnnotationConsistencyBetweenAnnotatorsForSeverity([FromRoute] int projectId, [FromRoute] string severity) { var result = _annotationConsistencyService.CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(projectId, severity); return Ok(result.Value); @@ -40,7 +40,7 @@ public IActionResult GetMetricsSignificanceInAnnotationsForAnnotator([FromRoute] [HttpGet] [Route("metrics/annotators/{projectId}/{severity}")] - public IActionResult GetMetricsSignificanceBetweenAnnotatorsForSeverity([FromRoute] int projectId, [FromRoute] int severity) + public IActionResult GetMetricsSignificanceBetweenAnnotatorsForSeverity([FromRoute] int projectId, [FromRoute] string severity) { var result = _annotationConsistencyService.CheckMetricsSignificanceBetweenAnnotatorsForSeverity(projectId, severity); return Ok(result.Value); diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs index c0e7ef7b..f9c26984 100644 --- a/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/AnnotationSchemaController.cs @@ -119,5 +119,52 @@ public IActionResult UpdateHeuristicInCodeSmell([FromRoute] int id, [FromBody] H if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } + + [HttpGet] + [Route("{id}/severities")] + public IActionResult GetSeveritiesForCodeSmell([FromRoute] int id) + { + var result = _annotationSchemaService.GetSeveritiesForCodeSmell(id); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpGet] + [Route("severities")] + public IActionResult GetSeveritiesForEachCodeSmell() + { + var result = _annotationSchemaService.GetSeveritiesForEachCodeSmell(); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPost] + [Route("{id}/severities")] + public IActionResult AddSeverityToCodeSmell([FromRoute] int id, [FromBody] SeverityDefinitionDTO severityDto) + { + var severity = _mapper.Map(severityDto); + var result = _annotationSchemaService.AddSeverityToCodeSmell(id, severity); + if (result.IsFailed) return NotFound(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpDelete] + [Route("{smellId}/severities/{severityId}")] + public IActionResult RemoveSeverityFromCodeSmell([FromRoute] int smellId, [FromRoute] int severityId) + { + var result = _annotationSchemaService.DeleteSeverityFromCodeSmell(smellId, severityId); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } + + [HttpPut] + [Route("{id}/severities")] + public IActionResult UpdateSeverityInCodeSmell([FromRoute] int id, [FromBody] SeverityDefinitionDTO severityDTO) + { + var severity = _mapper.Map(severityDTO); + var result = _annotationSchemaService.UpdateSeverityInCodeSmell(id, severity); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } } } diff --git a/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityDefinitionDTO.cs b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityDefinitionDTO.cs new file mode 100644 index 00000000..10118a0d --- /dev/null +++ b/DataSetExplorer/UI/Controllers/AnnotationSchema/DTOs/SeverityDefinitionDTO.cs @@ -0,0 +1,9 @@ +namespace DataSetExplorer.UI.Controllers.AnnotationSchema.DTOs +{ + public class SeverityDefinitionDTO + { + public int Id { get; set; } + public string Value { get; set; } + public string Description { get; set; } + } +} diff --git a/DataSetExplorer/UI/Controllers/Annotations/DTOs/AnnotationDTO.cs b/DataSetExplorer/UI/Controllers/Annotations/DTOs/AnnotationDTO.cs index 519799f2..0269179c 100644 --- a/DataSetExplorer/UI/Controllers/Annotations/DTOs/AnnotationDTO.cs +++ b/DataSetExplorer/UI/Controllers/Annotations/DTOs/AnnotationDTO.cs @@ -5,7 +5,7 @@ namespace DataSetExplorer.UI.Controllers.Annotations.DTOs public class AnnotationDTO { public int InstanceId { get; set; } - public int Severity { get; set; } + public string Severity { get; set; } public string CodeSmell { get; set; } public List ApplicableHeuristics { get; set; } public int AnnotatorId { get; set; } diff --git a/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs b/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs index 955fa97e..ad2f04f7 100644 --- a/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs +++ b/DataSetExplorer/UI/Controllers/Annotations/Mappers/AnnotationProfile.cs @@ -16,6 +16,7 @@ public AnnotationProfile() .ConstructUsing(src => new Annotation(src.CodeSmell, src.Severity, new Annotator(src.AnnotatorId), CreateHeuristics(src.ApplicableHeuristics), src.Note)); CreateMap(); CreateMap(); + CreateMap(); } private List CreateHeuristics(List heuristics) From fedfd75f9526a4fb6b5a7690f1c22888b091eab3 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 2 Jun 2022 14:52:08 +0200 Subject: [PATCH 16/46] fix[DE]: Delete blank lines --- DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs | 3 +-- DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs index c960d8d2..2b63c73a 100644 --- a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs @@ -25,8 +25,7 @@ public ExcelImporter(string sourceFolder) /// The excel documents must be formatted following these guidelines https://github.com/Clean-CaDET/platform/wiki/Dataset-Explorer#building-your-dataset /// /// Name of the returned dataset project. - /// A dataset project constructed from one or more excel documents. - + /// A dataset project constructed from one or more excel documents. public DataSetProject Import(string projectName) { var project = new DataSetProject(projectName); diff --git a/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs b/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs index 6df164cb..3d327fa0 100644 --- a/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs +++ b/DataSetExplorer/UI/ConsoleApp/AnnotationConsistencySubmenu.cs @@ -66,7 +66,6 @@ private static void WriteAnnotationsConsistencyOptions() Console.WriteLine("3. Check metrics significance for a single annotator"); Console.WriteLine("4. Check metrics significance between annotators"); Console.WriteLine("x. Exit\n"); - } } } From 5f786d9dc6fe5be2201830155db9850dffae114f Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 2 Jun 2022 16:58:41 +0200 Subject: [PATCH 17/46] fix[DE]: Fix paths to consistency tests --- DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs | 4 ++-- DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs b/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs index bd3bc943..0c964b64 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs @@ -11,8 +11,8 @@ namespace DataSetExplorer.Core.AnnotationConsistency { public class AnovaTest : IMetricsSignificanceTester { - private readonly string _anovaScriptFile = "./AnnotationConsistency/scripts/anova_test.py"; - private readonly string _pythonPath = "./AnnotationConsistency/venv/Scripts/python.exe"; + private readonly string _anovaScriptFile = "./Core/AnnotationConsistency/scripts/anova_test.py"; + private readonly string _pythonPath = "./Core/AnnotationConsistency/venv/Scripts/python.exe"; private string _annotatedInstancesFile; private string _dependentVariable; private string _independentVariable; diff --git a/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs b/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs index 0f470e1b..7f441973 100644 --- a/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs +++ b/DataSetExplorer/Core/AnnotationConsistency/ManovaTest.cs @@ -11,8 +11,8 @@ namespace DataSetExplorer.Core.AnnotationConsistency { public class ManovaTest : IAnnotatorsConsistencyTester { - private readonly string _manovaScriptFile = "./AnnotationConsistency/scripts/manova_test.py"; - private readonly string _pythonPath = "./AnnotationConsistency/venv/Scripts/python.exe"; + private readonly string _manovaScriptFile = "./Core/AnnotationConsistency/scripts/manova_test.py"; + private readonly string _pythonPath = "./Core/AnnotationConsistency/venv/Scripts/python.exe"; private string _annotatedInstancesFile; private string _dependentVariable; private string _independentVariable; From 7bdead4a38b7ebea64da6ee88ac49c837d9f5e6c Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 2 Jun 2022 16:59:31 +0200 Subject: [PATCH 18/46] feat[DE]: Add snippet type to CodeSmellDTO --- DataSetExplorer/UI/Controllers/Dataset/DTOs/CodeSmellDTO.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/DataSetExplorer/UI/Controllers/Dataset/DTOs/CodeSmellDTO.cs b/DataSetExplorer/UI/Controllers/Dataset/DTOs/CodeSmellDTO.cs index 5d239302..db910a12 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/DTOs/CodeSmellDTO.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/DTOs/CodeSmellDTO.cs @@ -3,5 +3,6 @@ public class CodeSmellDTO { public string Name { get; set; } + public string SnippetType { get; set; } } } From eeb1bc8aaadcd1d9aba6bf804580b795981bb8fc Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Fri, 3 Jun 2022 09:51:35 +0200 Subject: [PATCH 19/46] feat[DE]: Get code smell object instead of name --- .../Core/Annotations/DataSetAnalysisService.cs | 8 +++++--- .../Core/Annotations/Model/Annotation.cs | 2 +- .../Core/DataSetSerializer/ExcelImporter.cs | 18 ++++++++++++++---- .../Core/DataSets/FullDataSetFactory.cs | 9 ++++++--- DataSetExplorer/UI/ConsoleApp/MainMenu.cs | 2 +- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs b/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs index 4c28718a..42f0de35 100644 --- a/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs +++ b/DataSetExplorer/Core/Annotations/DataSetAnalysisService.cs @@ -13,9 +13,11 @@ namespace DataSetExplorer.Core.Annotations public class DataSetAnalysisService : IDataSetAnalysisService { private readonly IProjectRepository _projectRepository; - public DataSetAnalysisService(IProjectRepository projectRepository) + private readonly IAnnotationRepository _annotationRepository; + public DataSetAnalysisService(IProjectRepository projectRepository, IAnnotationRepository annotationRepository) { _projectRepository = projectRepository; + _annotationRepository = annotationRepository; } public Result FindInstancesWithAllDisagreeingAnnotations(IDictionary projects) @@ -66,13 +68,13 @@ public Result> FindInstancesRequiringAdditionalAnn private DataSetProject LoadDataSetProject(string folder, string projectName) { - var importer = new ExcelImporter(folder); + var importer = new ExcelImporter(folder, _annotationRepository); return importer.Import(projectName); } private List LoadAnnotatedInstances(string datasetPath) { - var importer = new ExcelImporter(datasetPath); + var importer = new ExcelImporter(datasetPath, _annotationRepository); return importer.ImportAnnotatedInstancesFromDataSet(datasetPath); } diff --git a/DataSetExplorer/Core/Annotations/Model/Annotation.cs b/DataSetExplorer/Core/Annotations/Model/Annotation.cs index 797fe00a..ea9fe42d 100644 --- a/DataSetExplorer/Core/Annotations/Model/Annotation.cs +++ b/DataSetExplorer/Core/Annotations/Model/Annotation.cs @@ -11,7 +11,7 @@ public class Annotation public List ApplicableHeuristics { get; private set; } public Annotator Annotator { get; set; } public string Note { get; private set; } - + public Annotation(string instanceSmell, string severity, Annotator annotator, List applicableHeuristics, String note) : this(new CodeSmell(instanceSmell), severity, annotator, applicableHeuristics, note) { diff --git a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs index 2b63c73a..15fa6e4e 100644 --- a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs @@ -4,6 +4,7 @@ using System.Linq; using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Core.DataSets.Repository; using OfficeOpenXml; namespace DataSetExplorer.Core.DataSetSerializer @@ -13,12 +14,19 @@ public class ExcelImporter private const int StartingInstanceRow = 4; private const int StartingHeuristicColumn = 4; private readonly string _sourceFolder; + private readonly IAnnotationRepository _annotationRepository; public ExcelImporter(string sourceFolder) { _sourceFolder = sourceFolder; } + public ExcelImporter(string sourceFolder, IAnnotationRepository annotationRepository) + { + _sourceFolder = sourceFolder; + _annotationRepository = annotationRepository; + } + /// /// This logic is highly dependent on the appropriate excel file structure. /// It examines excel documents in the sourceFolder directory and its subdirectories. @@ -33,7 +41,8 @@ public DataSetProject Import(string projectName) var sheets = GetWorksheets(GetExcelDocuments()); foreach (var excelWorksheet in sheets) { - project.AddCandidateInstance(new SmellCandidateInstances(new CodeSmell(excelWorksheet.Name), ExtractInstances(excelWorksheet))); + if (_annotationRepository != null) project.AddCandidateInstance(new SmellCandidateInstances(_annotationRepository.GetCodeSmell(excelWorksheet.Name), ExtractInstances(excelWorksheet))); + else project.AddCandidateInstance(new SmellCandidateInstances(new CodeSmell(excelWorksheet.Name), ExtractInstances(excelWorksheet))); } return project; @@ -115,15 +124,16 @@ internal List ImportAnnotatedInstancesFromDataSet(string path) return instances; } - private static Annotation GetAnnotation(ExcelWorksheet sheet, int row) + private Annotation GetAnnotation(ExcelWorksheet sheet, int row) { try { var smellSeverity = sheet.Cells["C" + row].Text; var annotatorId = int.Parse(sheet.Cells["C2"].Text); - var codeSmell = sheet.Cells["B2"].Text; + var codeSmellName = sheet.Cells["B2"].Text; var heuristics = GetHeuristics(sheet, row); - return new Annotation(codeSmell, smellSeverity, new Annotator(annotatorId), heuristics, ""); // TODO - extract note from sheet + if (_annotationRepository != null) return new Annotation(_annotationRepository.GetCodeSmell(codeSmellName), smellSeverity, new Annotator(annotatorId), heuristics, ""); // TODO - extract note from sheet + return new Annotation(codeSmellName, smellSeverity, new Annotator(annotatorId), heuristics, ""); // TODO - extract note from sheet } catch (InvalidOperationException e) { diff --git a/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs b/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs index e363e9b7..2c4b5f95 100644 --- a/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs +++ b/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs @@ -12,10 +12,12 @@ namespace DataSetExplorer.Core.DataSets public class FullDataSetFactory { private readonly IInstanceRepository _instanceRepository; + private readonly IAnnotationRepository _annotationRepository; - public FullDataSetFactory(IInstanceRepository instanceRepository) + public FullDataSetFactory(IInstanceRepository instanceRepository, IAnnotationRepository annotationRepository) { _instanceRepository = instanceRepository; + _annotationRepository = annotationRepository; } public FullDataSetFactory() { } @@ -28,7 +30,7 @@ public List GetAnnotatedInstancesGroupedBySmells(IDicti CodeModelFactory factory = new CodeModelFactory(); CaDETProject project = factory.CreateProjectWithCodeFileLinks(projectSourceLocation); - var importer = new ExcelImporter(projects[projectSourceLocation]); + var importer = new ExcelImporter(projects[projectSourceLocation], _annotationRepository); var annotatedCandidates = importer.Import(projectSourceLocation).CandidateInstances.ToList(); LoadAnnotators(annotators, annotatedCandidates); @@ -73,7 +75,8 @@ public List GetAnnotatedInstancesGroupedBySmells(int pr var instancesBySmell = instances.GroupBy(i => i.Annotations.ToList()[0].InstanceSmell.Name); foreach (var group in instancesBySmell) { - candidateInstances.Add(new SmellCandidateInstances(new CodeSmell(group.Key), group.ToList())); + if (_annotationRepository != null) candidateInstances.Add(new SmellCandidateInstances(_annotationRepository.GetCodeSmell(group.Key), group.ToList())); + else candidateInstances.Add(new SmellCandidateInstances(new CodeSmell(group.Key), group.ToList())); } return candidateInstances; } diff --git a/DataSetExplorer/UI/ConsoleApp/MainMenu.cs b/DataSetExplorer/UI/ConsoleApp/MainMenu.cs index c46e32a9..c50dbc10 100644 --- a/DataSetExplorer/UI/ConsoleApp/MainMenu.cs +++ b/DataSetExplorer/UI/ConsoleApp/MainMenu.cs @@ -39,7 +39,7 @@ private void ProcessChosenOption(string chosenOption) CreateDataSet(); break; case "2": - new DataSetAnalysisSubmenu(new DataSetAnalysisService(null)).AnalyzeDataSet(); + new DataSetAnalysisSubmenu(new DataSetAnalysisService(null, null)).AnalyzeDataSet(); break; case "3": ExportDataSet(); From fe5e2b7a080ee15410a35997a159bb25b6a64359 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Fri, 3 Jun 2022 09:55:16 +0200 Subject: [PATCH 20/46] fix[DE]: Remove blank line --- DataSetExplorer/UI/ConsoleApp/MainMenu.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/DataSetExplorer/UI/ConsoleApp/MainMenu.cs b/DataSetExplorer/UI/ConsoleApp/MainMenu.cs index c50dbc10..3f32722a 100644 --- a/DataSetExplorer/UI/ConsoleApp/MainMenu.cs +++ b/DataSetExplorer/UI/ConsoleApp/MainMenu.cs @@ -27,7 +27,6 @@ internal void Run() chosenOption = ConsoleIO.GetAnswerOnQuestion("Your option: "); Console.Clear(); ProcessChosenOption(chosenOption); - } while (!chosenOption.Equals("x")); } From e92fde9ff0555ee4eaf0d72c1c01585879c6583b Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 30 Jun 2022 23:13:06 +0200 Subject: [PATCH 21/46] feat[DE]: Add graph instances --- .../CommunityDetection/Model/GraphInstance.cs | 45 ++++++++++ .../Model/GraphRelatedInstance.cs | 20 +++++ .../DataSets/CaDETToDataSetProjectBuilder.cs | 84 +++++++++++++++++++ .../Core/DataSets/DataSetCreationService.cs | 1 + .../Core/DataSets/InstanceService.cs | 4 +- .../Core/DataSets/Model/DataSetProject.cs | 1 + .../Repository/ProjectDatabaseRepository.cs | 1 + .../Database/DataSetExplorerContext.cs | 14 ++++ 8 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 DataSetExplorer/Core/CommunityDetection/Model/GraphInstance.cs create mode 100644 DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs diff --git a/DataSetExplorer/Core/CommunityDetection/Model/GraphInstance.cs b/DataSetExplorer/Core/CommunityDetection/Model/GraphInstance.cs new file mode 100644 index 00000000..16d59898 --- /dev/null +++ b/DataSetExplorer/Core/CommunityDetection/Model/GraphInstance.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; + +namespace DataSetExplorer.Core.DataSets.Model +{ + public class GraphInstance + { + public int Id { get; private set; } + public string CodeSnippetId { get; private set; } + public string Link { get; private set; } + public List RelatedInstances { get; private set; } + + internal GraphInstance(string codeSnippetId, string link, List relatedInstances) + { + CodeSnippetId = codeSnippetId; + Link = link; + RelatedInstances = relatedInstances; + Validate(); + } + + private GraphInstance() + { + } + + public GraphInstance(string codeSnippetId) + { + CodeSnippetId = codeSnippetId; + } + + private void Validate() + { + if (string.IsNullOrEmpty(CodeSnippetId)) throw new ArgumentException("CodeSnippetId cannot be empty."); + } + + public override int GetHashCode() + { + return CodeSnippetId.GetHashCode(); + } + + public override bool Equals(object other) + { + return other is Instance instance && CodeSnippetId.Equals(instance.CodeSnippetId); + } + } +} diff --git a/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs b/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs new file mode 100644 index 00000000..96f0e5b3 --- /dev/null +++ b/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +namespace DataSetExplorer.Core.DataSets.Model +{ + public class GraphRelatedInstance + { + public int Id { get; private set; } + public string CodeSnippetId { get; private set; } + public Dictionary CouplingTypeAndStrength { get; private set; } + + public GraphRelatedInstance(string codeSnippetId, Dictionary couplingTypeAndStrength) + { + CodeSnippetId = codeSnippetId; + CouplingTypeAndStrength = couplingTypeAndStrength; + } + + private GraphRelatedInstance() + { + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index 11aa1d7a..65b80e5a 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -87,6 +87,7 @@ internal CaDETToDataSetProjectBuilder RandomizeMemberSelection() internal DataSetProject Build() { var builtDataSetProject = new DataSetProject(_projectName, _projectAndCommitUrl); + builtDataSetProject.GraphInstances = CaDETToGraphClasses(_cadetProject.Classes); foreach (var smell in _codeSmells) { @@ -96,6 +97,89 @@ internal DataSetProject Build() return builtDataSetProject; } + private List CaDETToGraphClasses(List cadetClasses) + { + return cadetClasses.Select(c => new GraphInstance( + c.FullName, GetCodeUrl(c.FullName), FindGraphClassRelatedInstances(c))).ToList(); + } + + private List FindGraphClassRelatedInstances(CaDETClass c) + { + var relatedInstances = new List(); + if (c.Parent != null) + { + var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt.Add(CouplingType.Parent, 1); + relatedInstances.Add(new GraphRelatedInstance(c.Parent.FullName, couplingTypeAndSt)); + } + relatedInstances.AddRange(FindReferencedGraphInstances(c)); + relatedInstances.AddRange(FindGraphInstancesThatReference(c)); + return relatedInstances; + } + + private List FindReferencedGraphInstances(CaDETClass referencingClass) + { + var relatedInstances = new List(); + GetReferencedInstances(referencingClass).ForEach(cc => CoupledClassToGraphRelatedInstance(relatedInstances, cc)); + return relatedInstances; + } + + private void CoupledClassToGraphRelatedInstance(List relatedInstances, CoupledClassStrength cc) + { + var index = relatedInstances.FindIndex(i => i.CodeSnippetId.Equals(cc.CoupledClass.FullName)); + if (index != -1) + { + try + { + relatedInstances[index].CouplingTypeAndStrength.Add(cc.CouplingType, cc.CouplingStrength); + } + catch (Exception e) + { + relatedInstances[index].CouplingTypeAndStrength[cc.CouplingType] += cc.CouplingStrength; + } + } + else + { + var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt.Add(cc.CouplingType, cc.CouplingStrength); + relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, couplingTypeAndSt)); + } + } + + private List FindGraphInstancesThatReference(CaDETClass referencedClass) + { + if (_classCouplings.TryGetValue(referencedClass, out var instancesThatReference)) + { + var relatedInstances = new List(); + instancesThatReference.ForEach(cc => + CoupledClassToGraphRelatedInstance(relatedInstances, cc, RelationType.References)); + return relatedInstances; + } + return new List(); + } + + private void CoupledClassToGraphRelatedInstance(List relatedInstances, CoupledClassStrength cc, RelationType relationType) + { + var index = relatedInstances.FindIndex(i => i.CodeSnippetId.Equals(cc.CoupledClass.FullName)); + if (index != -1) + { + try + { + relatedInstances[index].CouplingTypeAndStrength.Add(cc.CouplingType, cc.CouplingStrength); + } + catch (Exception e) + { + relatedInstances[index].CouplingTypeAndStrength[cc.CouplingType] += cc.CouplingStrength; + } + } + else + { + var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt.Add(cc.CouplingType, cc.CouplingStrength); + relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, couplingTypeAndSt)); + } + } + private List BuildClasses() { var cadetClasses = _cadetProject.Classes; diff --git a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs index a11d7c8c..8be106a7 100644 --- a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs @@ -129,6 +129,7 @@ private void ProcessInitialDataSetProject(string basePath, DataSetProject initia { var project = CreateDataSetProject(basePath, initialProject.Name, initialProject.Url, codeSmells, smellFilters, projectBuildSettings); initialProject.CandidateInstances = project.CandidateInstances; + initialProject.GraphInstances = project.GraphInstances; initialProject.Processed(); _projectRepository.Update(initialProject); } diff --git a/DataSetExplorer/Core/DataSets/InstanceService.cs b/DataSetExplorer/Core/DataSets/InstanceService.cs index 03629508..0ae1dea5 100644 --- a/DataSetExplorer/Core/DataSets/InstanceService.cs +++ b/DataSetExplorer/Core/DataSets/InstanceService.cs @@ -11,15 +11,13 @@ namespace DataSetExplorer.Core.DataSets public class InstanceService : IInstanceService { private readonly IInstanceRepository _instanceRepository; - private readonly IProjectRepository _projectRepository; private readonly IDataSetCreationService _dataSetCreationService; private readonly IAnnotationRepository _annotationRepository; public InstanceService(IInstanceRepository instanceRepository, IDataSetCreationService dataSetCreationService, - IAnnotationRepository annotationRepository, IProjectRepository projectRepository) + IAnnotationRepository annotationRepository) { _instanceRepository = instanceRepository; - _projectRepository = projectRepository; _dataSetCreationService = dataSetCreationService; _annotationRepository = annotationRepository; } diff --git a/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs b/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs index 65d7e846..0188c53e 100644 --- a/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs +++ b/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs @@ -9,6 +9,7 @@ public class DataSetProject public string Name { get; private set; } public string Url { get; private set; } public HashSet CandidateInstances { get; internal set; } + public List GraphInstances { get; internal set; } public ProjectState State { get; private set; } internal DataSetProject(string name, string url) diff --git a/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs index 45dca1b8..7f0574dc 100644 --- a/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs @@ -20,6 +20,7 @@ public ProjectDatabaseRepository(IServiceScopeFactory serviceScopeFactory) public DataSetProject Get(int id) { return _dbContext.DataSetProjects + .Include(p => p.GraphInstances).ThenInclude(i => i.RelatedInstances) .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances) .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.RelatedInstances) .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.Annotations) diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index ff5ddbfe..4cec4b18 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -22,6 +22,8 @@ public class DataSetExplorerContext : DbContext public DbSet HeuristicDefinitions { get; set; } public DbSet SeverityDefinitions { get; set; } public DbSet SmellCandidateInstances { get; set; } + public DbSet GraphInstances { get; set; } + public DbSet GraphRelatedInstances { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { } @@ -40,6 +42,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) m => JsonConvert.SerializeObject(m), m => JsonConvert.DeserializeObject>(m)); + modelBuilder.Entity() + .Property(i => i.CouplingTypeAndStrength) + .HasConversion( + m => JsonConvert.SerializeObject(m), + m => JsonConvert.DeserializeObject>(m)); + modelBuilder.Entity().HasOne().WithMany(d => d.SupportedCodeSmells) .OnDelete(DeleteBehavior.Cascade); @@ -55,6 +63,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasOne().WithMany(p => p.CandidateInstances) .OnDelete(DeleteBehavior.Cascade); + modelBuilder.Entity().HasOne().WithMany(p => p.GraphInstances) + .OnDelete(DeleteBehavior.Cascade); + modelBuilder.Entity().HasOne().WithMany(c => c.Instances) .OnDelete(DeleteBehavior.Cascade); @@ -67,6 +78,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasOne().WithMany(i => i.RelatedInstances) .OnDelete(DeleteBehavior.Cascade); + modelBuilder.Entity().HasOne().WithMany(i => i.RelatedInstances) + .OnDelete(DeleteBehavior.Cascade); + modelBuilder .Entity() .Property(i => i.RelationType) From ab4a3dca1fe05f3bb36bf030ae2890bb461c0059 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Sun, 3 Jul 2022 18:21:18 +0200 Subject: [PATCH 22/46] feat[DE]: Independent graph load --- .../Core/DataSets/IProjectService.cs | 10 ++++++++ .../Core/DataSets/ProjectService.cs | 23 +++++++++++++++++++ .../DataSets/Repository/IProjectRepository.cs | 1 + .../Repository/ProjectDatabaseRepository.cs | 8 ++++++- DataSetExplorer/Startup.cs | 1 + .../Controllers/Dataset/ProjectController.cs | 19 ++++++++++----- 6 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 DataSetExplorer/Core/DataSets/IProjectService.cs create mode 100644 DataSetExplorer/Core/DataSets/ProjectService.cs diff --git a/DataSetExplorer/Core/DataSets/IProjectService.cs b/DataSetExplorer/Core/DataSets/IProjectService.cs new file mode 100644 index 00000000..9f153ae9 --- /dev/null +++ b/DataSetExplorer/Core/DataSets/IProjectService.cs @@ -0,0 +1,10 @@ +using DataSetExplorer.Core.DataSets.Model; +using FluentResults; + +namespace DataSetExplorer.Core.DataSets +{ + public interface IProjectService + { + Result GetProjectWithGraphInstances(int id); + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/ProjectService.cs b/DataSetExplorer/Core/DataSets/ProjectService.cs new file mode 100644 index 00000000..5950afd5 --- /dev/null +++ b/DataSetExplorer/Core/DataSets/ProjectService.cs @@ -0,0 +1,23 @@ +using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Core.DataSets.Repository; +using FluentResults; + +namespace DataSetExplorer.Core.DataSets +{ + public class ProjectService : IProjectService + { + private readonly IProjectRepository _projectRepository; + + public ProjectService(IProjectRepository projectRepository) + { + _projectRepository = projectRepository; + } + + public Result GetProjectWithGraphInstances(int id) + { + var project = _projectRepository.GetProjectWithGraphInstances(id); + if (project == default) return Result.Fail($"Project with id: {id} does not exist."); + return Result.Ok(project); + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs index 586e51a1..cac2eba8 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs @@ -9,5 +9,6 @@ public interface IProjectRepository IEnumerable GetAll(IEnumerable projectIds); DataSetProject Update(DataSetProject dataSetProject); DataSetProject Delete(int id); + DataSetProject GetProjectWithGraphInstances(int id); } } diff --git a/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs index 7f0574dc..cc0937d3 100644 --- a/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs @@ -20,7 +20,6 @@ public ProjectDatabaseRepository(IServiceScopeFactory serviceScopeFactory) public DataSetProject Get(int id) { return _dbContext.DataSetProjects - .Include(p => p.GraphInstances).ThenInclude(i => i.RelatedInstances) .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances) .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.RelatedInstances) .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.Annotations) @@ -53,5 +52,12 @@ public DataSetProject Delete(int id) _dbContext.SaveChanges(); return deletedProject; } + + public DataSetProject GetProjectWithGraphInstances(int id) + { + return _dbContext.DataSetProjects + .Include(p => p.GraphInstances).ThenInclude(i => i.RelatedInstances) + .FirstOrDefault(p => p.Id == id); + } } } diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index 110569fc..a9030988 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -36,6 +36,7 @@ public void ConfigureServices(IServiceCollection services) opt.UseNpgsql(CreateConnectionStringFromEnvironment())); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs index 171b8ace..50a5f100 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs @@ -5,11 +5,6 @@ using DataSetExplorer.UI.Controllers.Dataset.DTOs; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; namespace DataSetExplorer.UI.Controllers.Dataset { @@ -21,11 +16,14 @@ public class ProjectController : ControllerBase private readonly IMapper _mapper; private readonly IDataSetCreationService _dataSetCreationService; + private readonly IProjectService _projectService; - public ProjectController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration) + public ProjectController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration, + IProjectService projectService) { _mapper = mapper; _dataSetCreationService = creationService; + _projectService = projectService; _gitClonePath = configuration.GetValue("Workspace:GitClonePath"); } @@ -62,5 +60,14 @@ public IActionResult GetCommunities([FromBody] Graph Graph) { return Ok(_dataSetCreationService.ExportCommunities(Graph).Value); } + + [HttpGet] + [Route("{id}/graph")] + public IActionResult GetProjectWithGraphInstances([FromRoute] int id) + { + var result = _projectService.GetProjectWithGraphInstances(id); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } } } From 769acba12a0952f66c1d7befd4ad9ffe1c11d0a2 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 21 Jul 2022 16:49:30 +0200 Subject: [PATCH 23/46] Add RelationType to GraphRelatedInstance --- .../Core/CommunityDetection/Model/GraphRelatedInstance.cs | 4 +++- .../Infrastructure/Database/DataSetExplorerContext.cs | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs b/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs index 96f0e5b3..7f651801 100644 --- a/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs +++ b/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs @@ -5,12 +5,14 @@ public class GraphRelatedInstance { public int Id { get; private set; } public string CodeSnippetId { get; private set; } + public RelationType RelationType { get; private set; } public Dictionary CouplingTypeAndStrength { get; private set; } - public GraphRelatedInstance(string codeSnippetId, Dictionary couplingTypeAndStrength) + public GraphRelatedInstance(string codeSnippetId, RelationType relationType, Dictionary couplingTypeAndStrength) { CodeSnippetId = codeSnippetId; CouplingTypeAndStrength = couplingTypeAndStrength; + RelationType = relationType; } private GraphRelatedInstance() diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index 4cec4b18..9e80e5d0 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -86,6 +86,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(i => i.RelationType) .HasConversion(new EnumToStringConverter()); + modelBuilder + .Entity() + .Property(i => i.RelationType) + .HasConversion(new EnumToStringConverter()); + modelBuilder.Entity().HasOne().WithMany(d => d.Heuristics) .OnDelete(DeleteBehavior.Cascade); From 4d3651e47577ee8ac7465a2cb20cff588a47026c Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 21 Jul 2022 16:51:17 +0200 Subject: [PATCH 24/46] Get graph instance with related instances --- .../GraphInstanceService.cs | 26 +++++++++++++++++++ .../IGraphInstanceService.cs | 10 +++++++ .../Repository/GraphInstanceRepository.cs | 26 +++++++++++++++++++ .../Repository/IGraphInstanceRepository.cs | 9 +++++++ .../Controllers/Dataset/ProjectController.cs | 13 +++++++++- 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs create mode 100644 DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs create mode 100644 DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs create mode 100644 DataSetExplorer/Core/CommunityDetection/Repository/IGraphInstanceRepository.cs diff --git a/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs b/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs new file mode 100644 index 00000000..ad6adc49 --- /dev/null +++ b/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs @@ -0,0 +1,26 @@ +using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Core.DataSets.Repository; +using FluentResults; + +namespace DataSetExplorer.Core.DataSets +{ + public class GraphInstanceService : IGraphInstanceService + { + private readonly IGraphInstanceRepository _graphInstanceRepository; + private readonly IInstanceRepository _instanceRepository; + + public GraphInstanceService(IGraphInstanceRepository graphInstanceRepository, IInstanceRepository instanceRepository) + { + _graphInstanceRepository = graphInstanceRepository; + _instanceRepository = instanceRepository; + } + + public Result GetGraphInstanceWithRelatedInstances(int projectId, int instanceId) + { + var instance = _instanceRepository.Get(instanceId); + var graphInstance = _graphInstanceRepository.GetGraphInstanceWithRelatedInstances(projectId, instance.CodeSnippetId); + if (graphInstance == default) return Result.Fail($"Project with id: {projectId} or instance with id: {instanceId} does not exist."); + return Result.Ok(graphInstance); + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs b/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs new file mode 100644 index 00000000..4821657c --- /dev/null +++ b/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs @@ -0,0 +1,10 @@ +using DataSetExplorer.Core.DataSets.Model; +using FluentResults; + +namespace DataSetExplorer.Core.DataSets +{ + public interface IGraphInstanceService + { + Result GetGraphInstanceWithRelatedInstances(int projectId, int instanceId); + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs b/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs new file mode 100644 index 00000000..064b655d --- /dev/null +++ b/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs @@ -0,0 +1,26 @@ +using System.Linq; +using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Infrastructure.Database; +using Microsoft.EntityFrameworkCore; + +namespace DataSetExplorer.Core.DataSets.Repository +{ + public class GraphInstanceRepository : IGraphInstanceRepository + { + private readonly DataSetExplorerContext _dbContext; + + public GraphInstanceRepository(DataSetExplorerContext dbContext) + { + _dbContext = dbContext; + } + + public GraphInstance GetGraphInstanceWithRelatedInstances(int projectId, string codeSnippetId) + { + var graphInstances = _dbContext.DataSetProjects + .Include(p => p.GraphInstances).ThenInclude(i => i.RelatedInstances) + .FirstOrDefault(p => p.Id == projectId).GraphInstances; + + return graphInstances.Find(i => i.CodeSnippetId == codeSnippetId); + } + } +} diff --git a/DataSetExplorer/Core/CommunityDetection/Repository/IGraphInstanceRepository.cs b/DataSetExplorer/Core/CommunityDetection/Repository/IGraphInstanceRepository.cs new file mode 100644 index 00000000..0d345a72 --- /dev/null +++ b/DataSetExplorer/Core/CommunityDetection/Repository/IGraphInstanceRepository.cs @@ -0,0 +1,9 @@ +using DataSetExplorer.Core.DataSets.Model; + +namespace DataSetExplorer.Core.DataSets.Repository +{ + public interface IGraphInstanceRepository + { + GraphInstance GetGraphInstanceWithRelatedInstances(int projectId, string codeSnippetId); + } +} diff --git a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs index 50a5f100..2563528c 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs @@ -17,13 +17,15 @@ public class ProjectController : ControllerBase private readonly IMapper _mapper; private readonly IDataSetCreationService _dataSetCreationService; private readonly IProjectService _projectService; + private readonly IGraphInstanceService _graphInstanceService; public ProjectController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration, - IProjectService projectService) + IProjectService projectService, IGraphInstanceService graphInstanceService) { _mapper = mapper; _dataSetCreationService = creationService; _projectService = projectService; + _graphInstanceService = graphInstanceService; _gitClonePath = configuration.GetValue("Workspace:GitClonePath"); } @@ -69,5 +71,14 @@ public IActionResult GetProjectWithGraphInstances([FromRoute] int id) if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } + + [HttpGet] + [Route("{projectId}/instances/{instanceId}/graph")] + public IActionResult GetGraphNeighboursInstances([FromRoute] int projectId, [FromRoute] int instanceId) + { + var result = _graphInstanceService.GetGraphInstanceWithRelatedInstances(projectId, instanceId); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } } } From 2b8cb4fbdcacaa6d293f43bdcfb103549cbf1178 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 21 Jul 2022 16:52:18 +0200 Subject: [PATCH 25/46] refactor[DE]: Renaming --- .../DataSets/CaDETToDataSetProjectBuilder.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index 65b80e5a..de00054f 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -99,6 +99,7 @@ internal DataSetProject Build() private List CaDETToGraphClasses(List cadetClasses) { + CreateCouplingMap(cadetClasses); return cadetClasses.Select(c => new GraphInstance( c.FullName, GetCodeUrl(c.FullName), FindGraphClassRelatedInstances(c))).ToList(); } @@ -107,10 +108,10 @@ private List FindGraphClassRelatedInstances(CaDETClass c) { var relatedInstances = new List(); if (c.Parent != null) - { - var couplingTypeAndSt = new Dictionary(); - couplingTypeAndSt.Add(CouplingType.Parent, 1); - relatedInstances.Add(new GraphRelatedInstance(c.Parent.FullName, couplingTypeAndSt)); + { + var couplingTypeAndStrength = new Dictionary(); + couplingTypeAndStrength.Add(CouplingType.Parent, 1); + relatedInstances.Add(new GraphRelatedInstance(c.Parent.FullName, RelationType.Parent, couplingTypeAndStrength)); } relatedInstances.AddRange(FindReferencedGraphInstances(c)); relatedInstances.AddRange(FindGraphInstancesThatReference(c)); @@ -142,7 +143,7 @@ private void CoupledClassToGraphRelatedInstance(List relat { var couplingTypeAndSt = new Dictionary(); couplingTypeAndSt.Add(cc.CouplingType, cc.CouplingStrength); - relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, couplingTypeAndSt)); + relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, RelationType.Referenced, couplingTypeAndSt)); } } @@ -174,9 +175,9 @@ private void CoupledClassToGraphRelatedInstance(List relat } else { - var couplingTypeAndSt = new Dictionary(); - couplingTypeAndSt.Add(cc.CouplingType, cc.CouplingStrength); - relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, couplingTypeAndSt)); + var couplingTypeAndStrength = new Dictionary(); + couplingTypeAndStrength.Add(cc.CouplingType, cc.CouplingStrength); + relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, RelationType.References, couplingTypeAndStrength)); } } @@ -195,7 +196,6 @@ private int DetermineNumberOfInstances(int totalNumber) private List CaDETToDataSetProjectClasses(List cadetClasses) { - CreateCouplingMap(cadetClasses); return cadetClasses.Select(c => new Instance( c.FullName, GetCodeUrl(c.FullName), _projectAndCommitUrl, SnippetType.Class, _cadetProject.GetMetricsForCodeSnippet(c.FullName), FindClassRelatedInstances(c) From 66ffa097119309a5cc2bb085c7c29024d4eb743d Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Mon, 1 Aug 2022 16:03:11 +0200 Subject: [PATCH 26/46] feat[DE]: Add link to GraphRelatedInstance --- .../Core/CommunityDetection/GraphInstanceService.cs | 7 +++++++ .../Core/CommunityDetection/IGraphInstanceService.cs | 1 + .../CommunityDetection/Model/GraphRelatedInstance.cs | 5 ++++- .../Core/DataSets/CaDETToDataSetProjectBuilder.cs | 6 +++--- DataSetExplorer/Startup.cs | 3 +++ .../UI/Controllers/Dataset/InstanceController.cs | 2 +- .../UI/Controllers/Dataset/ProjectController.cs | 9 +++++++++ 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs b/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs index ad6adc49..126f93dc 100644 --- a/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs +++ b/DataSetExplorer/Core/CommunityDetection/GraphInstanceService.cs @@ -22,5 +22,12 @@ public Result GetGraphInstanceWithRelatedInstances(int projectId, if (graphInstance == default) return Result.Fail($"Project with id: {projectId} or instance with id: {instanceId} does not exist."); return Result.Ok(graphInstance); } + + public Result GetGraphInstanceWithRelatedInstances(int projectId, string instanceCodeSnippetId) + { + var graphInstance = _graphInstanceRepository.GetGraphInstanceWithRelatedInstances(projectId, instanceCodeSnippetId); + if (graphInstance == default) return Result.Fail($"Project with id: {projectId} or instance with codeSnippetId: {instanceCodeSnippetId} does not exist."); + return Result.Ok(graphInstance); + } } } \ No newline at end of file diff --git a/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs b/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs index 4821657c..09f6b537 100644 --- a/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs +++ b/DataSetExplorer/Core/CommunityDetection/IGraphInstanceService.cs @@ -6,5 +6,6 @@ namespace DataSetExplorer.Core.DataSets public interface IGraphInstanceService { Result GetGraphInstanceWithRelatedInstances(int projectId, int instanceId); + Result GetGraphInstanceWithRelatedInstances(int projectId, string instanceCodeSnippetId); } } \ No newline at end of file diff --git a/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs b/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs index 7f651801..2f71264a 100644 --- a/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs +++ b/DataSetExplorer/Core/CommunityDetection/Model/GraphRelatedInstance.cs @@ -7,12 +7,15 @@ public class GraphRelatedInstance public string CodeSnippetId { get; private set; } public RelationType RelationType { get; private set; } public Dictionary CouplingTypeAndStrength { get; private set; } + public string Link { get; private set; } - public GraphRelatedInstance(string codeSnippetId, RelationType relationType, Dictionary couplingTypeAndStrength) + public GraphRelatedInstance(string codeSnippetId, RelationType relationType, Dictionary couplingTypeAndStrength, + string link) { CodeSnippetId = codeSnippetId; CouplingTypeAndStrength = couplingTypeAndStrength; RelationType = relationType; + Link = link; } private GraphRelatedInstance() diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index de00054f..5d658a80 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -111,7 +111,7 @@ private List FindGraphClassRelatedInstances(CaDETClass c) { var couplingTypeAndStrength = new Dictionary(); couplingTypeAndStrength.Add(CouplingType.Parent, 1); - relatedInstances.Add(new GraphRelatedInstance(c.Parent.FullName, RelationType.Parent, couplingTypeAndStrength)); + relatedInstances.Add(new GraphRelatedInstance(c.Parent.FullName, RelationType.Parent, couplingTypeAndStrength, GetCodeUrl(c.Parent.FullName))); } relatedInstances.AddRange(FindReferencedGraphInstances(c)); relatedInstances.AddRange(FindGraphInstancesThatReference(c)); @@ -143,7 +143,7 @@ private void CoupledClassToGraphRelatedInstance(List relat { var couplingTypeAndSt = new Dictionary(); couplingTypeAndSt.Add(cc.CouplingType, cc.CouplingStrength); - relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, RelationType.Referenced, couplingTypeAndSt)); + relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, RelationType.Referenced, couplingTypeAndSt, GetCodeUrl(cc.CoupledClass.FullName))); } } @@ -177,7 +177,7 @@ private void CoupledClassToGraphRelatedInstance(List relat { var couplingTypeAndStrength = new Dictionary(); couplingTypeAndStrength.Add(cc.CouplingType, cc.CouplingStrength); - relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, RelationType.References, couplingTypeAndStrength)); + relatedInstances.Add(new GraphRelatedInstance(cc.CoupledClass.FullName, RelationType.References, couplingTypeAndStrength, GetCodeUrl(cc.CoupledClass.FullName))); } } diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index a9030988..ad995f4a 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -53,6 +53,9 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) diff --git a/DataSetExplorer/UI/Controllers/Dataset/InstanceController.cs b/DataSetExplorer/UI/Controllers/Dataset/InstanceController.cs index 74d75cf4..f61c0c18 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/InstanceController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/InstanceController.cs @@ -35,7 +35,7 @@ public IActionResult GetInstanceWithAnnotations([FromRoute] int id) } [HttpGet] - [Route("{id}/cohesion-graph")] + [Route("{id}/class-cohesion-graph")] public IActionResult GetCohesionGraphForInstance([FromRoute] int id) { var result = _instanceService.GetInstanceWithAnnotations(id); diff --git a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs index 2563528c..629c04e3 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs @@ -80,5 +80,14 @@ public IActionResult GetGraphNeighboursInstances([FromRoute] int projectId, [Fro if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } + + [HttpGet] + [Route("{projectId}/instances/{instanceCodeSnippetId}/graph-extended")] + public IActionResult GetGraphNeighboursInstances([FromRoute] int projectId, [FromRoute] string instanceCodeSnippetId) + { + var result = _graphInstanceService.GetGraphInstanceWithRelatedInstances(projectId, instanceCodeSnippetId); + if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); + return Ok(result.Value); + } } } From 5d28af3b7e9ee6536a5a3002be7c15a698e9a340 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Mon, 22 Aug 2022 11:31:04 +0200 Subject: [PATCH 27/46] fix[DE]: Fix dataset export - get heuristics from schema --- .../DataSetExportationService.cs | 24 ++++++++++- ...r.cs => DraftDataSetExportationService.cs} | 40 +++++++++++-------- .../IDataSetExportationService.cs | 2 + .../IDraftDataSetExportationService.cs | 9 +++++ .../Core/DataSets/DataSetCreationService.cs | 7 ---- .../Core/DataSets/IDataSetCreationService.cs | 1 - DataSetExplorer/Program.cs | 2 +- DataSetExplorer/Startup.cs | 6 ++- .../Controllers/Dataset/DataSetController.cs | 8 ++-- 9 files changed, 69 insertions(+), 30 deletions(-) rename DataSetExplorer/Core/DataSetSerializer/{DraftDataSetExporter.cs => DraftDataSetExportationService.cs} (66%) create mode 100644 DataSetExplorer/Core/DataSetSerializer/IDraftDataSetExportationService.cs diff --git a/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs index c293d8aa..d50d49c0 100644 --- a/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs @@ -2,6 +2,9 @@ using System.IO; using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets; +using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Core.DataSets.Repository; +using DataSetExplorer.UI.Controllers.Dataset.DTOs; using FluentResults; namespace DataSetExplorer.Core.DataSetSerializer @@ -9,10 +12,29 @@ namespace DataSetExplorer.Core.DataSetSerializer class DataSetExportationService : IDataSetExportationService { private readonly FullDataSetFactory _fullDataSetFactory; + private readonly IDraftDataSetExportationService _draftDataSetExportationService; + private readonly IDataSetRepository _dataSetRepository; - public DataSetExportationService(FullDataSetFactory fullDataSetFactory) + public DataSetExportationService(FullDataSetFactory fullDataSetFactory, IDraftDataSetExportationService draftDataSetExportationService, + IDataSetRepository dataSetRepository) { _fullDataSetFactory = fullDataSetFactory; + _dataSetRepository = dataSetRepository; + _draftDataSetExportationService = draftDataSetExportationService; + } + + public Result ExportDraft(DraftDataSetExportDTO dataSetDTO) + { + var dataSet = GetDataSetForExport(dataSetDTO.Id).Value; + var exportPath = _draftDataSetExportationService.Export(dataSetDTO.ExportPath, dataSetDTO.AnnotatorId, dataSet); + return Result.Ok(exportPath); + } + + private Result GetDataSetForExport(int id) + { + var dataSet = _dataSetRepository.GetDataSetForExport(id); + if (dataSet == default) return Result.Fail($"DataSet with id: {id} does not exist."); + return Result.Ok(dataSet); } public Result Export(IDictionary projects, List annotators, string outputPath) diff --git a/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExporter.cs b/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs similarity index 66% rename from DataSetExplorer/Core/DataSetSerializer/DraftDataSetExporter.cs rename to DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs index e19fc289..892b43d6 100644 --- a/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs @@ -2,28 +2,29 @@ using System.IO; using System.Linq; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.Core.AnnotationSchema.Repository; using DataSetExplorer.Core.DataSets.Model; -using DataSetExplorer.Core.DataSetSerializer.ViewModel; using OfficeOpenXml; namespace DataSetExplorer.Core.DataSetSerializer { - class DraftDataSetExporter + public class DraftDataSetExportationService : IDraftDataSetExportationService { private readonly string _templatePath = "./Core/DataSetSerializer/Template/New_Dataset_Template.xlsx"; private string _exportPath; private ExcelPackage _excelFile; private ExcelWorksheet _sheet; - private readonly ColumnHeuristicsModel _requiredSmells = new(); + private readonly IAnnotationSchemaRepository _annotationSchemaRepository; - public DraftDataSetExporter(string exportPath) + public DraftDataSetExportationService(IAnnotationSchemaRepository annotationSchemaRepository) { - _exportPath = exportPath; + _annotationSchemaRepository = annotationSchemaRepository; } - public string Export(int annotatorId, DataSet dataSet) + public string Export(string exportPath, int annotatorId, DataSet dataSet) { - _exportPath += dataSet.Name + "/"; + _exportPath = exportPath + dataSet.Name + "/"; ExcelPackage.LicenseContext = LicenseContext.NonCommercial; foreach (var project in dataSet.Projects) { @@ -64,18 +65,19 @@ private void PopulateBasicInfo(int annotatorId, DataSetProject project, SmellCan _sheet.Cells[2, 3].Value = annotatorId; } - private List PopulateSmellHeuristics(SmellCandidateInstances candidate) + private List PopulateSmellHeuristics(SmellCandidateInstances candidate) { - var smellHeuristics = _requiredSmells.GetHeuristicsByCodeSmellName(candidate.CodeSmell.Name); + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinitionByName(candidate.CodeSmell.Name); + var smellHeuristics = _annotationSchemaRepository.GetCodeSmellDefinition(codeSmellDefinition.Id).Heuristics.ToList(); for (var i = 0; i < smellHeuristics.Count; i++) { - _sheet.Cells[2, 4 + (2 * i)].Value = smellHeuristics[i]; + _sheet.Cells[2, 4 + (2 * i)].Value = smellHeuristics[i].Name; } _sheet.Cells[3, 4 + (smellHeuristics.Count * 2)].Value = "Note"; return smellHeuristics; } - private void PopulateAnnotatedInstances(SmellCandidateInstances candidate, List smellHeuristics) + private void PopulateAnnotatedInstances(SmellCandidateInstances candidate, List smellHeuristics) { var row = 4; foreach (var instance in candidate.Instances) @@ -88,29 +90,35 @@ private void PopulateAnnotatedInstances(SmellCandidateInstances candidate, List< } } - private void PopulateAnnotations(List smellHeuristics, int row, Instance instance) + private void PopulateAnnotations(List smellHeuristics, int row, Instance instance) { foreach (var annotation in instance.Annotations) { _sheet.Cells[row, 3].Value = annotation.Severity; foreach (var applicableHeuristic in annotation.ApplicableHeuristics) { - var index = smellHeuristics.FindIndex(h => h.Equals(applicableHeuristic.Description)); + var index = smellHeuristics.FindIndex(h => h.Name.Equals(applicableHeuristic.Description)); + _sheet.Cells[3, 4 + (2 * index)].Value = "Applicable?"; _sheet.Cells[row, 4 + (2 * index)].Value = "Yes"; + _sheet.Cells[3, 4 + (2 * index) + 1].Value = "Reasoning"; + _sheet.Cells[row, 4 + (2 * index) + 1].Value = applicableHeuristic.ReasonForApplicability; + } PopulateNotApplicableAnnotations(smellHeuristics, row, annotation); _sheet.Cells[row, 4 + (smellHeuristics.Count * 2)].Value = annotation.Note; } } - private void PopulateNotApplicableAnnotations(List smellHeuristics, int row, Annotation annotation) + private void PopulateNotApplicableAnnotations(List smellHeuristics, int row, Annotation annotation) { var notApplicableHeuristics = - smellHeuristics.Except(annotation.ApplicableHeuristics.ConvertAll(h => h.Description)); + smellHeuristics.ConvertAll(h => h.Name).Except(annotation.ApplicableHeuristics.ConvertAll(h => h.Description)); foreach (var heuristic in notApplicableHeuristics) { - var index = smellHeuristics.FindIndex(h => h.Equals(heuristic)); + var index = smellHeuristics.FindIndex(h => h.Name.Equals(heuristic)); _sheet.Cells[row, 4 + (2 * index)].Value = "No"; + _sheet.Cells[3, 4 + (2 * index)].Value = "Applicable?"; + _sheet.Cells[3, 4 + (2 * index) + 1].Value = "Reasoning"; } } diff --git a/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs index ed649a2c..5e197d7e 100644 --- a/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.UI.Controllers.Dataset.DTOs; using FluentResults; namespace DataSetExplorer.Core.DataSetSerializer @@ -7,5 +8,6 @@ namespace DataSetExplorer.Core.DataSetSerializer public interface IDataSetExportationService { public Result Export(IDictionary projects, List annotators, string outputPath); + public Result ExportDraft(DraftDataSetExportDTO dataSetDTO); } } diff --git a/DataSetExplorer/Core/DataSetSerializer/IDraftDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/IDraftDataSetExportationService.cs new file mode 100644 index 00000000..3eb4d3c7 --- /dev/null +++ b/DataSetExplorer/Core/DataSetSerializer/IDraftDataSetExportationService.cs @@ -0,0 +1,9 @@ +using DataSetExplorer.Core.DataSets.Model; + +namespace DataSetExplorer.Core.DataSetSerializer +{ + public interface IDraftDataSetExportationService + { + public string Export(string exportPath, int annotatorId, DataSet dataSet); + } +} diff --git a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs index 8be106a7..e3e9cf69 100644 --- a/DataSetExplorer/Core/DataSets/DataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/DataSetCreationService.cs @@ -80,13 +80,6 @@ public Result GetDataSet(int id) return Result.Ok(dataSet); } - public Result GetDataSetForExport(int id) - { - var dataSet = _dataSetRepository.GetDataSetForExport(id); - if (dataSet == default) return Result.Fail($"DataSet with id: {id} does not exist."); - return Result.Ok(dataSet); - } - public Result> GetAllDataSets() { var dataSets = _dataSetRepository.GetAll(); diff --git a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs index c6d7f04e..a4c391fd 100644 --- a/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs +++ b/DataSetExplorer/Core/DataSets/IDataSetCreationService.cs @@ -16,7 +16,6 @@ public interface IDataSetCreationService Result CreateEmptyDataSet(string dataSetName, List codeSmells); Result AddProjectToDataSet(int dataSetId, string basePath, DataSetProject project, List smellFilters, ProjectBuildSettingsDTO projectBuildSettings); Result GetDataSet(int id); - Result GetDataSetForExport(int id); Result> GetAllDataSets(); Result> GetDataSetsByCodeSmell(string codeSmellName); Result GetDataSetProject(int id); diff --git a/DataSetExplorer/Program.cs b/DataSetExplorer/Program.cs index fbceba2a..a43d6eb3 100644 --- a/DataSetExplorer/Program.cs +++ b/DataSetExplorer/Program.cs @@ -24,7 +24,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) => private static void CreateConsoleUI() { new MainMenu( - new DataSetExportationService(new FullDataSetFactory()), + new DataSetExportationService(new FullDataSetFactory(), null, null), new DataSetCreationService(new GitCodeRepository(), null, null, null)) .Run(); } diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index ad995f4a..c41367ec 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -12,6 +12,7 @@ using DataSetExplorer.Core.DataSets.Repository; using DataSetExplorer.Infrastructure.Database; using DataSetExplorer.Infrastructure.RepositoryAdapters; +using DataSetExplorer.Core.DataSetSerializer; namespace DataSetExplorer { @@ -46,7 +47,7 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); - + services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -56,6 +57,9 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) diff --git a/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs b/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs index e6d46654..e2122db6 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs @@ -18,11 +18,14 @@ public class DataSetController : ControllerBase private readonly IMapper _mapper; private readonly IDataSetCreationService _dataSetCreationService; + private readonly IDataSetExportationService _dataSetExportationService; - public DataSetController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration) + public DataSetController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration, + IDataSetExportationService exportationService) { _mapper = mapper; _dataSetCreationService = creationService; + _dataSetExportationService = exportationService; _gitClonePath = configuration.GetValue("Workspace:GitClonePath"); } @@ -39,8 +42,7 @@ public IActionResult UpdateDataSet([FromBody] DatasetDTO datasetDto) [Route("export")] public IActionResult ExportDataSet([FromBody] DraftDataSetExportDTO dataSetDTO) { - var dataSet = _dataSetCreationService.GetDataSetForExport(dataSetDTO.Id).Value; - var exportPath = new DraftDataSetExporter(dataSetDTO.ExportPath).Export(dataSetDTO.AnnotatorId, dataSet); + var exportPath = _dataSetExportationService.ExportDraft(dataSetDTO); return Ok(new FluentResults.Result().WithSuccess("Successfully exported to " + exportPath)); } From 33cf2f51e9a4977366e9b99263bb67c07f5b9810 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Tue, 23 Aug 2022 12:54:23 +0200 Subject: [PATCH 28/46] feat[DE]: Add relation type: class to which the method belongs --- .../Core/DataSets/CaDETToDataSetProjectBuilder.cs | 7 ++++++- DataSetExplorer/Core/DataSets/Model/CouplingType.cs | 3 ++- DataSetExplorer/Core/DataSets/Model/RelationType.cs | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index 5d658a80..4f1d7a35 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -351,10 +351,15 @@ private List FindMethodRelatedInstances(CaDETMember m) private IEnumerable FindReferencedInstances(CaDETMember referencingMember) { var relatedInstances = new List(); + + var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt.Add(CouplingType.BelongsTo, 1); + relatedInstances.Add(new RelatedInstance(referencingMember.Parent.FullName, GetCodeUrl(referencingMember.Parent.FullName), RelationType.BelongsTo, couplingTypeAndSt)); + var classParent = referencingMember.Parent.Parent; if (classParent != null) { - var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt = new Dictionary(); couplingTypeAndSt.Add(CouplingType.Parent, 1); relatedInstances.Add(new RelatedInstance(classParent.FullName, GetCodeUrl(classParent.FullName), RelationType.Parent, couplingTypeAndSt)); } diff --git a/DataSetExplorer/Core/DataSets/Model/CouplingType.cs b/DataSetExplorer/Core/DataSets/Model/CouplingType.cs index 7ad49859..5b8479ce 100644 --- a/DataSetExplorer/Core/DataSets/Model/CouplingType.cs +++ b/DataSetExplorer/Core/DataSets/Model/CouplingType.cs @@ -9,6 +9,7 @@ public enum CouplingType Variable, Parent, AccessedAccessor, - AccessedField + AccessedField, + BelongsTo } } diff --git a/DataSetExplorer/Core/DataSets/Model/RelationType.cs b/DataSetExplorer/Core/DataSets/Model/RelationType.cs index 2dfdefc4..60941a27 100644 --- a/DataSetExplorer/Core/DataSets/Model/RelationType.cs +++ b/DataSetExplorer/Core/DataSets/Model/RelationType.cs @@ -4,6 +4,7 @@ public enum RelationType { Referenced, References, - Parent + Parent, + BelongsTo } } \ No newline at end of file From b6623c5eb562b6fc1b313ef5fa3acbbc072a0895 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 24 Aug 2022 10:59:06 +0200 Subject: [PATCH 29/46] feat[DE]: Add subclass in related instances --- CodeModel/CaDETModel/CodeItems/CaDETClass.cs | 1 + .../CodeParsers/CSharp/CSharpCodeParser.cs | 14 ++++++++++++ .../DataSets/CaDETToDataSetProjectBuilder.cs | 22 +++++++++++++++++++ .../Core/DataSets/Model/CouplingType.cs | 3 ++- .../Core/DataSets/Model/RelationType.cs | 3 ++- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CodeModel/CaDETModel/CodeItems/CaDETClass.cs b/CodeModel/CaDETModel/CodeItems/CaDETClass.cs index b2911f3c..43f9fcc2 100644 --- a/CodeModel/CaDETModel/CodeItems/CaDETClass.cs +++ b/CodeModel/CaDETModel/CodeItems/CaDETClass.cs @@ -27,6 +27,7 @@ public string ContainerName public List Members { get; internal set; } public List Fields { get; internal set; } public Dictionary Metrics { get; set; } + public List Subclasses { get; set; } public CaDETClass(string name) { diff --git a/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs b/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs index c5247bcd..06e736e1 100644 --- a/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs +++ b/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs @@ -196,6 +196,7 @@ private List ConnectCaDETGraph(List classes) foreach (var c in classes) { c.Parent = LinkParent(classes, c.Parent); + c.Subclasses = LinkSubclasses(classes, c); var outerClass = LinkOuterClass(classes, c.ContainerName); if (outerClass != null) { @@ -218,6 +219,19 @@ private static CaDETClass LinkParent(List classes, CaDETClass parent if (parent.Name.Equals("object")) return null; return classes.FirstOrDefault(c => c.FullName.Equals(parent.Name)); } + + private List LinkSubclasses(List classes, CaDETClass c) + { + var subclasses = new List(); + foreach(var subclass in classes) + { + if (subclass.Parent == null) continue; + if (subclass.Parent.FullName != null && subclass.Parent.FullName.Equals(c.FullName)) subclasses.Add(subclass); + else if (subclass.Parent.Name != null && subclass.Parent.Name.Equals(c.FullName)) subclasses.Add(subclass); + } + return subclasses; + } + private static CaDETClass LinkOuterClass(List classes, string containerName) { return classes.FirstOrDefault(c => c.FullName.Equals(containerName)); diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index 4f1d7a35..552dcee3 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -113,11 +113,22 @@ private List FindGraphClassRelatedInstances(CaDETClass c) couplingTypeAndStrength.Add(CouplingType.Parent, 1); relatedInstances.Add(new GraphRelatedInstance(c.Parent.FullName, RelationType.Parent, couplingTypeAndStrength, GetCodeUrl(c.Parent.FullName))); } + AddSubclassesToGraphRelatedInstances(c.Subclasses, relatedInstances); relatedInstances.AddRange(FindReferencedGraphInstances(c)); relatedInstances.AddRange(FindGraphInstancesThatReference(c)); return relatedInstances; } + private void AddSubclassesToGraphRelatedInstances(List subclasses, List relatedInstances) + { + foreach (var subclass in subclasses) + { + var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt.Add(CouplingType.Subclass, 1); + relatedInstances.Add(new GraphRelatedInstance(subclass.FullName, RelationType.Subclass, couplingTypeAndSt, GetCodeUrl(subclass.FullName))); + } + } + private List FindReferencedGraphInstances(CaDETClass referencingClass) { var relatedInstances = new List(); @@ -261,11 +272,22 @@ private List FindClassRelatedInstances(CaDETClass c) couplingTypeAndSt.Add(CouplingType.Parent, 1); relatedInstances.Add(new RelatedInstance(c.Parent.FullName, GetCodeUrl(c.Parent.FullName), RelationType.Parent, couplingTypeAndSt)); } + AddSubclassesToRelatedInstances(c.Subclasses, relatedInstances); relatedInstances.AddRange(FindReferencedInstances(c)); relatedInstances.AddRange(FindInstancesThatReference(c)); return relatedInstances; } + private void AddSubclassesToRelatedInstances(List subclasses, List relatedInstances) + { + foreach (var subclass in subclasses) + { + var couplingTypeAndSt = new Dictionary(); + couplingTypeAndSt.Add(CouplingType.Subclass, 1); + relatedInstances.Add(new RelatedInstance(subclass.FullName, GetCodeUrl(subclass.FullName), RelationType.Subclass, couplingTypeAndSt)); + } + } + private List FindReferencedInstances(CaDETClass referencingClass) { var relatedInstances = new List(); diff --git a/DataSetExplorer/Core/DataSets/Model/CouplingType.cs b/DataSetExplorer/Core/DataSets/Model/CouplingType.cs index 5b8479ce..ef2ff360 100644 --- a/DataSetExplorer/Core/DataSets/Model/CouplingType.cs +++ b/DataSetExplorer/Core/DataSets/Model/CouplingType.cs @@ -10,6 +10,7 @@ public enum CouplingType Parent, AccessedAccessor, AccessedField, - BelongsTo + BelongsTo, + Subclass } } diff --git a/DataSetExplorer/Core/DataSets/Model/RelationType.cs b/DataSetExplorer/Core/DataSets/Model/RelationType.cs index 60941a27..4a5a1e43 100644 --- a/DataSetExplorer/Core/DataSets/Model/RelationType.cs +++ b/DataSetExplorer/Core/DataSets/Model/RelationType.cs @@ -5,6 +5,7 @@ public enum RelationType Referenced, References, Parent, - BelongsTo + BelongsTo, + Subclass } } \ No newline at end of file From e1409b0ffcfab4229b00d9dde7ce4dadbbce2fb0 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Fri, 26 Aug 2022 14:00:34 +0200 Subject: [PATCH 30/46] fix[DE]: Fix string comparison --- .../CommunityDetection/Repository/GraphInstanceRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs b/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs index 064b655d..dc3f8d80 100644 --- a/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs +++ b/DataSetExplorer/Core/CommunityDetection/Repository/GraphInstanceRepository.cs @@ -20,7 +20,7 @@ public GraphInstance GetGraphInstanceWithRelatedInstances(int projectId, string .Include(p => p.GraphInstances).ThenInclude(i => i.RelatedInstances) .FirstOrDefault(p => p.Id == projectId).GraphInstances; - return graphInstances.Find(i => i.CodeSnippetId == codeSnippetId); + return graphInstances.Find(i => i.CodeSnippetId.Equals(codeSnippetId)); } } } From 7087b9f29301a4cd45d06016d0408dd77c910692 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 31 Aug 2022 12:19:03 +0200 Subject: [PATCH 31/46] feat[DE]: Add annotator registration --- .../Core/Annotations/Model/Annotator.cs | 11 ++++- DataSetExplorer/Core/Auth/AuthService.cs | 32 ++++++++++++++ DataSetExplorer/Core/Auth/IAuthService.cs | 12 ++++++ .../Core/Auth/Repository/AuthRepository.cs | 42 ++++++++++++++++++ .../Core/Auth/Repository/IAuthRepository.cs | 11 +++++ .../Database/DataSetExplorerContext.cs | 3 ++ DataSetExplorer/Startup.cs | 4 ++ DataSetExplorer/UI/ConsoleApp/DataSetIO.cs | 2 +- .../UI/Controllers/Auth/AuthController.cs | 43 +++++++++++++++++++ .../UI/Controllers/Auth/DTOs/AnnotatorDTO.cs | 10 +++++ .../UI/Controllers/Auth/Mapper/AuthProfile.cs | 14 ++++++ DataSetExplorerTests/Unit/ImporterTests.cs | 6 +-- 12 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 DataSetExplorer/Core/Auth/AuthService.cs create mode 100644 DataSetExplorer/Core/Auth/IAuthService.cs create mode 100644 DataSetExplorer/Core/Auth/Repository/AuthRepository.cs create mode 100644 DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs create mode 100644 DataSetExplorer/UI/Controllers/Auth/AuthController.cs create mode 100644 DataSetExplorer/UI/Controllers/Auth/DTOs/AnnotatorDTO.cs create mode 100644 DataSetExplorer/UI/Controllers/Auth/Mapper/AuthProfile.cs diff --git a/DataSetExplorer/Core/Annotations/Model/Annotator.cs b/DataSetExplorer/Core/Annotations/Model/Annotator.cs index f474fa42..11ceb262 100644 --- a/DataSetExplorer/Core/Annotations/Model/Annotator.cs +++ b/DataSetExplorer/Core/Annotations/Model/Annotator.cs @@ -6,18 +6,24 @@ public class Annotator { public int Id { get; private set; } public string Name { get; private set; } + public string Email { get; private set; } public int YearsOfExperience { get; private set; } public int Ranking { get; private set; } + public Annotator() { + + } + public Annotator(int id) { Id = id; } - public Annotator(int id, string name, int yearsOfExperience, int ranking) + public Annotator(int id, string name, string email, int yearsOfExperience, int ranking) { Id = id; Name = name; + Email = email; YearsOfExperience = yearsOfExperience; Ranking = ranking; } @@ -32,13 +38,14 @@ public bool Equals(Annotator other) return other != null && Id == other.Id && Name == other.Name && + Email == other.Email && YearsOfExperience == other.YearsOfExperience && Ranking == other.Ranking; } public override int GetHashCode() { - return HashCode.Combine(Id, Name, YearsOfExperience, Ranking); + return HashCode.Combine(Id, Name, Email, YearsOfExperience, Ranking); } } } \ No newline at end of file diff --git a/DataSetExplorer/Core/Auth/AuthService.cs b/DataSetExplorer/Core/Auth/AuthService.cs new file mode 100644 index 00000000..6a3e0b61 --- /dev/null +++ b/DataSetExplorer/Core/Auth/AuthService.cs @@ -0,0 +1,32 @@ +using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.Auth.Repository; +using FluentResults; + +namespace DataSetExplorer.Core.Auth +{ + public class AuthService : IAuthService + { + private readonly IAuthRepository _authRepository; + + public AuthService(IAuthRepository authRepository) + { + _authRepository = authRepository; + } + + public Result RegisterAnnotator(Annotator annotator) + { + _authRepository.RegisterAnnotator(annotator); + return Result.Ok(annotator); + } + + public Result GetAnnotatorByEmail(string email) + { + return Result.Ok(_authRepository.GetAnnotatorByEmail(email)); + } + + public Result GetAnnotatorById(int id) + { + return Result.Ok(_authRepository.GetAnnotatorById(id)); + } + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/Auth/IAuthService.cs b/DataSetExplorer/Core/Auth/IAuthService.cs new file mode 100644 index 00000000..f3bdda12 --- /dev/null +++ b/DataSetExplorer/Core/Auth/IAuthService.cs @@ -0,0 +1,12 @@ +using DataSetExplorer.Core.Annotations.Model; +using FluentResults; + +namespace DataSetExplorer.Core.Auth +{ + public interface IAuthService + { + Result RegisterAnnotator(Annotator annotatorDTO); + Result GetAnnotatorByEmail(string email); + Result GetAnnotatorById(int id); + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs b/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs new file mode 100644 index 00000000..7827cda2 --- /dev/null +++ b/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs @@ -0,0 +1,42 @@ +using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Infrastructure.Database; +using Microsoft.EntityFrameworkCore; +using System.Linq; + +namespace DataSetExplorer.Core.Auth.Repository +{ + public class AuthRepository : IAuthRepository + { + private readonly DataSetExplorerContext _dbContext; + + public AuthRepository(DataSetExplorerContext dbContext) + { + _dbContext = dbContext; + } + + public void RegisterAnnotator(Annotator annotator) + { + _dbContext.Update(annotator); + try + { + _dbContext.SaveChanges(); + } + catch (DbUpdateException e) + { + return; + } + } + + public Annotator GetAnnotatorByEmail(string email) + { + return _dbContext.Annotators + .FirstOrDefault(a => a.Email == email); + } + + public Annotator GetAnnotatorById(int id) + { + return _dbContext.Annotators + .FirstOrDefault(a => a.Id == id); + } + } +} diff --git a/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs b/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs new file mode 100644 index 00000000..db18594b --- /dev/null +++ b/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs @@ -0,0 +1,11 @@ +using DataSetExplorer.Core.Annotations.Model; + +namespace DataSetExplorer.Core.Auth.Repository +{ + public interface IAuthRepository + { + void RegisterAnnotator(Annotator annotator); + Annotator GetAnnotatorByEmail(string email); + Annotator GetAnnotatorById(int id); + } +} diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index 9e80e5d0..c9c3d0a4 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -110,6 +110,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(codeSmell => { codeSmell.HasIndex(c => c.Name).IsUnique(); }); + modelBuilder.Entity(annotator => { + annotator.HasIndex(a => a.Email).IsUnique(); + }); } } } diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index c41367ec..3cb133ed 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -13,6 +13,8 @@ using DataSetExplorer.Infrastructure.Database; using DataSetExplorer.Infrastructure.RepositoryAdapters; using DataSetExplorer.Core.DataSetSerializer; +using DataSetExplorer.Core.Auth; +using DataSetExplorer.Core.Auth.Repository; namespace DataSetExplorer { @@ -60,6 +62,8 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) diff --git a/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs b/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs index 1478a44e..065157c7 100644 --- a/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs +++ b/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs @@ -29,7 +29,7 @@ internal static List GetAnnotators() foreach (string line in lines) { string[] columns = line.Split(','); - annotators.Add(new Annotator(int.Parse(columns[0]), columns[1], int.Parse(columns[2]), int.Parse(columns[3]))); + annotators.Add(new Annotator(int.Parse(columns[0]), columns[1], columns[2], int.Parse(columns[3]), int.Parse(columns[4]))); } return annotators; } diff --git a/DataSetExplorer/UI/Controllers/Auth/AuthController.cs b/DataSetExplorer/UI/Controllers/Auth/AuthController.cs new file mode 100644 index 00000000..a52e4205 --- /dev/null +++ b/DataSetExplorer/UI/Controllers/Auth/AuthController.cs @@ -0,0 +1,43 @@ +using AutoMapper; +using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.Auth; +using DataSetExplorer.UI.Controllers.Auth.DTOs; +using Microsoft.AspNetCore.Mvc; + +namespace DataSetExplorer.UI.Controllers.Auth +{ + [Route("api/auth/")] + [ApiController] + public class AuthController : ControllerBase + { + private readonly IMapper _mapper; + private readonly IAuthService _authService; + + public AuthController(IMapper mapper, IAuthService authService) + { + _mapper = mapper; + _authService = authService; + } + + [HttpPost] + public IActionResult RegisterAnnotator([FromBody] AnnotatorDTO annotatorDTO) + { + var annotator = _authService.RegisterAnnotator(_mapper.Map(annotatorDTO)); + return Ok(annotator); + } + + [HttpGet] + [Route("email/{email}")] + public IActionResult GetAnnotatorByEmail([FromRoute] string email) + { + return Ok(_authService.GetAnnotatorByEmail(email).Value); + } + + [HttpGet] + [Route("id/{id}")] + public IActionResult GetAnnotatorById([FromRoute] int id) + { + return Ok(_authService.GetAnnotatorById(id).Value); + } + } +} diff --git a/DataSetExplorer/UI/Controllers/Auth/DTOs/AnnotatorDTO.cs b/DataSetExplorer/UI/Controllers/Auth/DTOs/AnnotatorDTO.cs new file mode 100644 index 00000000..3a945220 --- /dev/null +++ b/DataSetExplorer/UI/Controllers/Auth/DTOs/AnnotatorDTO.cs @@ -0,0 +1,10 @@ +namespace DataSetExplorer.UI.Controllers.Auth.DTOs +{ + public class AnnotatorDTO + { + public string Name { get; set; } + public string Email { get; set; } + public int YearsOfExperience { get; set; } + public int Ranking { get; set; } + } +} diff --git a/DataSetExplorer/UI/Controllers/Auth/Mapper/AuthProfile.cs b/DataSetExplorer/UI/Controllers/Auth/Mapper/AuthProfile.cs new file mode 100644 index 00000000..cb59747c --- /dev/null +++ b/DataSetExplorer/UI/Controllers/Auth/Mapper/AuthProfile.cs @@ -0,0 +1,14 @@ +using AutoMapper; +using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.UI.Controllers.Auth.DTOs; + +namespace DataSetExplorer.UI.Controllers.Auth.Mapper +{ + public class AuthProfile : Profile + { + public AuthProfile() + { + CreateMap(); + } + } +} diff --git a/DataSetExplorerTests/Unit/ImporterTests.cs b/DataSetExplorerTests/Unit/ImporterTests.cs index a12ef4fa..b44396da 100644 --- a/DataSetExplorerTests/Unit/ImporterTests.cs +++ b/DataSetExplorerTests/Unit/ImporterTests.cs @@ -38,9 +38,9 @@ public void Imports_data_set_instances_and_annotations() var annotators = new List() { - new Annotator(1, "Nikola Luburic", 6, 1), - new Annotator(2, "Simona Prokic", 2, 2), - new Annotator(3, "Katarina-Glorija Grujic", 2, 3) + new Annotator(1, "Nikola Luburic", "nikola.luburic@uns.ac.rs", 6, 1), + new Annotator(2, "Simona Prokic", "simona.prokic@uns.ac.rs", 2, 2), + new Annotator(3, "Katarina-Glorija Grujic", "katarina.glorija@uns.ac.rs", 2, 3) }; JoinInstancesAndAnnotators(distinctClasses.ToList(), annotators); From cad2a0018a8a78f58d89c2e12a86be149baa0c2b Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 31 Aug 2022 15:04:09 +0200 Subject: [PATCH 32/46] refactor[DE]: Delete unused methods --- .../AnnotationSchemaDatabaseRepository.cs | 48 ------------------- .../Repository/IAnnotationSchemaRepository.cs | 8 ---- 2 files changed, 56 deletions(-) diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs index 7452d6a6..f9ec1cf6 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/AnnotationSchemaDatabaseRepository.cs @@ -48,53 +48,5 @@ public CodeSmellDefinition DeleteCodeSmellDefinition(int id) _dbContext.SaveChanges(); return deletedCodeSmell; } - - public HeuristicDefinition GetHeuristic(int id) - { - return _dbContext.HeuristicDefinitions - .FirstOrDefault(h => h.Id == id); - } - - public IEnumerable GetAllHeuristics() - { - return _dbContext.HeuristicDefinitions; - } - - public void SaveHeuristic(HeuristicDefinition heuristic) - { - _dbContext.Update(heuristic); - _dbContext.SaveChanges(); - } - - public HeuristicDefinition DeleteHeuristic(int id) - { - var deletedHeuristic = _dbContext.HeuristicDefinitions.Remove(_dbContext.HeuristicDefinitions.Find(id)).Entity; - _dbContext.SaveChanges(); - return deletedHeuristic; - } - - public SeverityDefinition GetSeverity(int id) - { - return _dbContext.SeverityDefinitions - .FirstOrDefault(s => s.Id == id); - } - - public IEnumerable GetAllSeverities() - { - return _dbContext.SeverityDefinitions; - } - - public void SaveSeverity(SeverityDefinition severity) - { - _dbContext.Update(severity); - _dbContext.SaveChanges(); - } - - public SeverityDefinition DeleteSeverity(int id) - { - var deletedSeverity = _dbContext.SeverityDefinitions.Remove(_dbContext.SeverityDefinitions.Find(id)).Entity; - _dbContext.SaveChanges(); - return deletedSeverity; - } } } diff --git a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs index 72aa8e06..32d0568b 100644 --- a/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs +++ b/DataSetExplorer/Core/AnnotationSchema/Repository/IAnnotationSchemaRepository.cs @@ -10,13 +10,5 @@ public interface IAnnotationSchemaRepository IEnumerable GetAllCodeSmellDefinitions(); void SaveCodeSmellDefinition(CodeSmellDefinition codeSmellDefinition); CodeSmellDefinition DeleteCodeSmellDefinition(int id); - HeuristicDefinition GetHeuristic(int id); - IEnumerable GetAllHeuristics(); - void SaveHeuristic(HeuristicDefinition heuristic); - HeuristicDefinition DeleteHeuristic(int id); - SeverityDefinition GetSeverity(int id); - IEnumerable GetAllSeverities(); - void SaveSeverity(SeverityDefinition severity); - SeverityDefinition DeleteSeverity(int id); } } From 4960d5f242c08bd04ef9850bcce55d28230d099c Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 31 Aug 2022 15:07:07 +0200 Subject: [PATCH 33/46] feat[DE]: Add annotator update methods --- DataSetExplorer/Core/Annotations/Model/Annotator.cs | 6 ++---- DataSetExplorer/Core/Auth/AuthService.cs | 5 ++--- DataSetExplorer/Core/Auth/IAuthService.cs | 2 +- .../Core/Auth/Repository/AuthRepository.cs | 5 +++-- .../Core/Auth/Repository/IAuthRepository.cs | 2 +- .../DraftDataSetExportationService.cs | 3 +-- DataSetExplorer/UI/Controllers/Auth/AuthController.cs | 11 ++++++++++- 7 files changed, 20 insertions(+), 14 deletions(-) diff --git a/DataSetExplorer/Core/Annotations/Model/Annotator.cs b/DataSetExplorer/Core/Annotations/Model/Annotator.cs index 11ceb262..27c612d2 100644 --- a/DataSetExplorer/Core/Annotations/Model/Annotator.cs +++ b/DataSetExplorer/Core/Annotations/Model/Annotator.cs @@ -4,15 +4,13 @@ namespace DataSetExplorer.Core.Annotations.Model { public class Annotator { - public int Id { get; private set; } + public int Id { get; set; } public string Name { get; private set; } public string Email { get; private set; } public int YearsOfExperience { get; private set; } public int Ranking { get; private set; } - public Annotator() { - - } + public Annotator() {} public Annotator(int id) { diff --git a/DataSetExplorer/Core/Auth/AuthService.cs b/DataSetExplorer/Core/Auth/AuthService.cs index 6a3e0b61..01f80cd9 100644 --- a/DataSetExplorer/Core/Auth/AuthService.cs +++ b/DataSetExplorer/Core/Auth/AuthService.cs @@ -13,10 +13,9 @@ public AuthService(IAuthRepository authRepository) _authRepository = authRepository; } - public Result RegisterAnnotator(Annotator annotator) + public Result Save(Annotator annotator) { - _authRepository.RegisterAnnotator(annotator); - return Result.Ok(annotator); + return Result.Ok(_authRepository.Save(annotator)); } public Result GetAnnotatorByEmail(string email) diff --git a/DataSetExplorer/Core/Auth/IAuthService.cs b/DataSetExplorer/Core/Auth/IAuthService.cs index f3bdda12..a3e68884 100644 --- a/DataSetExplorer/Core/Auth/IAuthService.cs +++ b/DataSetExplorer/Core/Auth/IAuthService.cs @@ -5,7 +5,7 @@ namespace DataSetExplorer.Core.Auth { public interface IAuthService { - Result RegisterAnnotator(Annotator annotatorDTO); + Result Save(Annotator annotatorDTO); Result GetAnnotatorByEmail(string email); Result GetAnnotatorById(int id); } diff --git a/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs b/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs index 7827cda2..c44dc65b 100644 --- a/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs +++ b/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs @@ -14,16 +14,17 @@ public AuthRepository(DataSetExplorerContext dbContext) _dbContext = dbContext; } - public void RegisterAnnotator(Annotator annotator) + public Annotator Save(Annotator annotator) { _dbContext.Update(annotator); try { _dbContext.SaveChanges(); + return annotator; } catch (DbUpdateException e) { - return; + return null; } } diff --git a/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs b/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs index db18594b..0ddc3687 100644 --- a/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs +++ b/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs @@ -4,7 +4,7 @@ namespace DataSetExplorer.Core.Auth.Repository { public interface IAuthRepository { - void RegisterAnnotator(Annotator annotator); + Annotator Save(Annotator annotator); Annotator GetAnnotatorByEmail(string email); Annotator GetAnnotatorById(int id); } diff --git a/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs index 892b43d6..0a921737 100644 --- a/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs @@ -101,8 +101,7 @@ private void PopulateAnnotations(List smellHeuristics, int _sheet.Cells[3, 4 + (2 * index)].Value = "Applicable?"; _sheet.Cells[row, 4 + (2 * index)].Value = "Yes"; _sheet.Cells[3, 4 + (2 * index) + 1].Value = "Reasoning"; - _sheet.Cells[row, 4 + (2 * index) + 1].Value = applicableHeuristic.ReasonForApplicability; - + _sheet.Cells[row, 4 + (2 * index) + 1].Value = applicableHeuristic.ReasonForApplicability; } PopulateNotApplicableAnnotations(smellHeuristics, row, annotation); _sheet.Cells[row, 4 + (smellHeuristics.Count * 2)].Value = annotation.Note; diff --git a/DataSetExplorer/UI/Controllers/Auth/AuthController.cs b/DataSetExplorer/UI/Controllers/Auth/AuthController.cs index a52e4205..97bbdf18 100644 --- a/DataSetExplorer/UI/Controllers/Auth/AuthController.cs +++ b/DataSetExplorer/UI/Controllers/Auth/AuthController.cs @@ -22,7 +22,7 @@ public AuthController(IMapper mapper, IAuthService authService) [HttpPost] public IActionResult RegisterAnnotator([FromBody] AnnotatorDTO annotatorDTO) { - var annotator = _authService.RegisterAnnotator(_mapper.Map(annotatorDTO)); + var annotator = _authService.Save(_mapper.Map(annotatorDTO)); return Ok(annotator); } @@ -39,5 +39,14 @@ public IActionResult GetAnnotatorById([FromRoute] int id) { return Ok(_authService.GetAnnotatorById(id).Value); } + + [HttpPut] + [Route("{id}")] + public IActionResult UpdateAnnotator([FromRoute] int id, [FromBody] AnnotatorDTO annotatorDTO) + { + var annotator = _mapper.Map(annotatorDTO); + annotator.Id = id; + return Ok(_authService.Save(annotator).Value); + } } } From 04b8adab467c15a2d5e1068c332cf7df12fb8ffb Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Tue, 6 Sep 2022 16:22:46 +0200 Subject: [PATCH 34/46] fix[DE]: Fix dataset export --- .../DraftDataSetExportationService.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs index 0a921737..0eafe024 100644 --- a/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/DraftDataSetExportationService.cs @@ -51,7 +51,7 @@ private void PopulateSheets(int annotatorId, DataSetProject project) _sheet = _excelFile.Workbook.Worksheets[i]; PopulateBasicInfo(annotatorId, project, candidate); var smellHeuristics = PopulateSmellHeuristics(candidate); - PopulateAnnotatedInstances(candidate, smellHeuristics); + PopulateAnnotatedInstances(candidate, smellHeuristics, annotatorId); Serialize(project.Name + annotatorId); i++; } @@ -77,7 +77,8 @@ private List PopulateSmellHeuristics(SmellCandidateInstance return smellHeuristics; } - private void PopulateAnnotatedInstances(SmellCandidateInstances candidate, List smellHeuristics) + private void PopulateAnnotatedInstances(SmellCandidateInstances candidate, List smellHeuristics, + int annotatorId) { var row = 4; foreach (var instance in candidate.Instances) @@ -85,15 +86,17 @@ private void PopulateAnnotatedInstances(SmellCandidateInstances candidate, List< if (instance.Annotations.Count == 0) continue; _sheet.Cells[row, 1].Value = instance.CodeSnippetId; _sheet.Cells[row, 2].Value = instance.Link; - PopulateAnnotations(smellHeuristics, row, instance); + PopulateAnnotations(smellHeuristics, row, instance, annotatorId); row++; } } - private void PopulateAnnotations(List smellHeuristics, int row, Instance instance) + private void PopulateAnnotations(List smellHeuristics, int row, Instance instance, + int annotatorId) { foreach (var annotation in instance.Annotations) { + if (annotation.Annotator.Id != annotatorId) continue; _sheet.Cells[row, 3].Value = annotation.Severity; foreach (var applicableHeuristic in annotation.ApplicableHeuristics) { From 58038b2a1620d6eb95479a37eac258a5592567c2 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Wed, 7 Sep 2022 13:31:33 +0200 Subject: [PATCH 35/46] feat[DE]: Export complete dataset --- .../Core/Annotations/Model/Annotator.cs | 8 ++++ DataSetExplorer/Core/Auth/AuthService.cs | 6 +++ DataSetExplorer/Core/Auth/IAuthService.cs | 2 + .../Core/Auth/Repository/AuthRepository.cs | 6 +++ .../Core/Auth/Repository/IAuthRepository.cs | 2 + ...s => CompleteDataSetExportationService.cs} | 44 +++++++++++++------ .../DataSetExportationService.cs | 22 +++++++--- .../Core/DataSetSerializer/ExcelImporter.cs | 20 +++++++++ .../ICompleteDataSetExportationService.cs | 10 +++++ .../IDataSetExportationService.cs | 3 +- .../Core/DataSets/FullDataSetFactory.cs | 36 ++++++++++++++- .../Core/DataSets/IProjectService.cs | 2 + .../Core/DataSets/Model/DataSetProject.cs | 7 ++- .../Core/DataSets/ProjectService.cs | 6 +++ .../DataSets/Repository/IProjectRepository.cs | 1 + .../Repository/ProjectDatabaseRepository.cs | 11 +++++ DataSetExplorer/Program.cs | 2 +- DataSetExplorer/Startup.cs | 1 + DataSetExplorer/UI/ConsoleApp/DataSetIO.cs | 4 +- DataSetExplorer/UI/ConsoleApp/MainMenu.cs | 4 +- .../Dataset/DTOs/CompleteDataSetExportDTO.cs | 8 ++++ .../Controllers/Dataset/DataSetController.cs | 12 ++++- 22 files changed, 189 insertions(+), 28 deletions(-) rename DataSetExplorer/Core/DataSetSerializer/{CompleteDataSetExporter.cs => CompleteDataSetExportationService.cs} (83%) create mode 100644 DataSetExplorer/Core/DataSetSerializer/ICompleteDataSetExportationService.cs create mode 100644 DataSetExplorer/UI/Controllers/Dataset/DTOs/CompleteDataSetExportDTO.cs diff --git a/DataSetExplorer/Core/Annotations/Model/Annotator.cs b/DataSetExplorer/Core/Annotations/Model/Annotator.cs index 27c612d2..65847a17 100644 --- a/DataSetExplorer/Core/Annotations/Model/Annotator.cs +++ b/DataSetExplorer/Core/Annotations/Model/Annotator.cs @@ -26,6 +26,14 @@ public Annotator(int id, string name, string email, int yearsOfExperience, int r Ranking = ranking; } + public Annotator(int id, string name, int yearsOfExperience, int ranking) + { + Id = id; + Name = name; + YearsOfExperience = yearsOfExperience; + Ranking = ranking; + } + public override bool Equals(object obj) { return Equals(obj as Annotator); diff --git a/DataSetExplorer/Core/Auth/AuthService.cs b/DataSetExplorer/Core/Auth/AuthService.cs index 01f80cd9..83c91d0a 100644 --- a/DataSetExplorer/Core/Auth/AuthService.cs +++ b/DataSetExplorer/Core/Auth/AuthService.cs @@ -1,6 +1,7 @@ using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.Auth.Repository; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.Auth { @@ -27,5 +28,10 @@ public Result GetAnnotatorById(int id) { return Result.Ok(_authRepository.GetAnnotatorById(id)); } + + public Result> GetAll() + { + return Result.Ok(_authRepository.GetAll()); + } } } \ No newline at end of file diff --git a/DataSetExplorer/Core/Auth/IAuthService.cs b/DataSetExplorer/Core/Auth/IAuthService.cs index a3e68884..f49adbdf 100644 --- a/DataSetExplorer/Core/Auth/IAuthService.cs +++ b/DataSetExplorer/Core/Auth/IAuthService.cs @@ -1,5 +1,6 @@ using DataSetExplorer.Core.Annotations.Model; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.Auth { @@ -8,5 +9,6 @@ public interface IAuthService Result Save(Annotator annotatorDTO); Result GetAnnotatorByEmail(string email); Result GetAnnotatorById(int id); + Result> GetAll(); } } \ No newline at end of file diff --git a/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs b/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs index c44dc65b..5888c176 100644 --- a/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs +++ b/DataSetExplorer/Core/Auth/Repository/AuthRepository.cs @@ -1,6 +1,7 @@ using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Infrastructure.Database; using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; using System.Linq; namespace DataSetExplorer.Core.Auth.Repository @@ -39,5 +40,10 @@ public Annotator GetAnnotatorById(int id) return _dbContext.Annotators .FirstOrDefault(a => a.Id == id); } + + public List GetAll() + { + return _dbContext.Annotators.ToList(); + } } } diff --git a/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs b/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs index 0ddc3687..5c449654 100644 --- a/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs +++ b/DataSetExplorer/Core/Auth/Repository/IAuthRepository.cs @@ -1,4 +1,5 @@ using DataSetExplorer.Core.Annotations.Model; +using System.Collections.Generic; namespace DataSetExplorer.Core.Auth.Repository { @@ -7,5 +8,6 @@ public interface IAuthRepository Annotator Save(Annotator annotator); Annotator GetAnnotatorByEmail(string email); Annotator GetAnnotatorById(int id); + List GetAll(); } } diff --git a/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExporter.cs b/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs similarity index 83% rename from DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExporter.cs rename to DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs index ff1c0e9e..caf53ccb 100644 --- a/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs @@ -3,29 +3,31 @@ using System.Linq; using CodeModel.CaDETModel.CodeItems; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.Core.AnnotationSchema.Repository; using DataSetExplorer.Core.DataSets.Model; -using DataSetExplorer.Core.DataSetSerializer.ViewModel; using OfficeOpenXml; namespace DataSetExplorer.Core.DataSetSerializer { - class CompleteDataSetExporter + class CompleteDataSetExportationService: ICompleteDataSetExportationService { private readonly string _dataSetWithAnnotationsTemplatePath = "./Core/DataSetSerializer/Template/Complete_Dataset_With_Annotations_Template.xlsx"; private readonly string _dataSetWithHeuristicsTemplatePath = "./Core/DataSetSerializer/Template/Complete_Dataset_With_Heuristics_Template.xlsx"; private readonly string _dataSetWithMetricsTemplatePath = "./Core/DataSetSerializer/Template/Complete_Dataset_With_Metrics_Template.xlsx"; - private readonly string _exportPath; + private string _exportPath; private ExcelPackage _excelFile; private ExcelWorksheet _sheet; - private readonly ColumnHeuristicsModel _requiredSmells = new ColumnHeuristicsModel(); + private readonly IAnnotationSchemaRepository _annotationSchemaRepository; - public CompleteDataSetExporter(string exportPath) + public CompleteDataSetExportationService(IAnnotationSchemaRepository annotationSchemaRepository) { - _exportPath = exportPath; + _annotationSchemaRepository = annotationSchemaRepository; } - public void Export(List dataSetInstances, string smell, string fileName) + public void Export(string outputPath, List dataSetInstances, string smell, string fileName) { + _exportPath = outputPath; ExportDataSetWithAnnotations(dataSetInstances, fileName); ExportDataSetWithMetrics(dataSetInstances, fileName); ExportDataSetWithHeuristics(dataSetInstances, smell, fileName); @@ -160,7 +162,8 @@ private void PopulateHeuristicsTemplate(List instances, string smell) private void PopulateHeuristicsHeader(List instances, string smell, List annotators) { - var smellHeuristics = _requiredSmells.GetHeuristicsByCodeSmellName(smell); + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinitionByName(smell); + var smellHeuristics = _annotationSchemaRepository.GetCodeSmellDefinition(codeSmellDefinition.Id).Heuristics.ToList(); var numOfHeuristics = smellHeuristics.Count(); _sheet.Cells[1, 2, 1, 1 + (numOfHeuristics * annotators.Count)].Merge = true; @@ -173,7 +176,8 @@ private void PopulateHeuristicsHeader(List instances, string smell, Li private void PopulateHeuristics(List annotations, int row, List annotators, string smell) { - var smellHeuristics = _requiredSmells.GetHeuristicsByCodeSmellName(smell); + var codeSmellDefinition = _annotationSchemaRepository.GetCodeSmellDefinitionByName(smell); + var smellHeuristics = _annotationSchemaRepository.GetCodeSmellDefinition(codeSmellDefinition.Id).Heuristics.ToList(); var numOfHeuristics = smellHeuristics.Count(); for (int i = 0; i < annotations.Count(); i++) { @@ -188,28 +192,40 @@ private void PopulateHeuristics(List annotations, int row, List smellHeuristics, List applicableHeuristics, int row, int annotationNum) + private void PopulateHeuristicValues(List smellHeuristics, List applicableHeuristics, int row, int annotationNum) { var numOfHeuristics = smellHeuristics.Count(); applicableHeuristics = GetCodeSmellHeuristicsForExport(smellHeuristics, applicableHeuristics); - for (var i = 0; i < applicableHeuristics.Count(); i++) + for (var i = 0; i < smellHeuristics.Count(); i++) { - _sheet.Cells[4, 2 + (numOfHeuristics * annotationNum) + i].Value = applicableHeuristics[i].Description; + _sheet.Cells[4, 2 + (numOfHeuristics * annotationNum) + i].Value = smellHeuristics[i].Name; _sheet.Cells[3, 2 + (numOfHeuristics * annotationNum), 3, 1 + (numOfHeuristics * annotationNum) + numOfHeuristics].Merge = true; _sheet.Cells[3, 2 + (numOfHeuristics * annotationNum)].Value = "Heuristics"; + } + + if (applicableHeuristics.Count == 0) + { + for (var i = 0; i < smellHeuristics.Count(); i++) + { + _sheet.Cells[row, 2 + (numOfHeuristics * annotationNum) + i].Value = "FALSE"; + } + } + + for (var i = 0; i < applicableHeuristics.Count(); i++) + { _sheet.Cells[row, 2 + (numOfHeuristics * annotationNum) + i].Value = applicableHeuristics[i].IsApplicable; } } - private List GetCodeSmellHeuristicsForExport(List heuristics, List applicableHeuristics) + private List GetCodeSmellHeuristicsForExport(List heuristics, List applicableHeuristics) { var heuristicsForExport = new List(); foreach (var heuristic in heuristics) { foreach (var applicableHeur in applicableHeuristics) { - if (heuristic.Equals(applicableHeur.Description)) { + if (heuristic.Name.Equals(applicableHeur.Description)) { heuristicsForExport.Add(applicableHeur); break; } diff --git a/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs index d50d49c0..b4a65f48 100644 --- a/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/DataSetExportationService.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.Auth; using DataSetExplorer.Core.DataSets; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Core.DataSets.Repository; @@ -13,14 +14,19 @@ class DataSetExportationService : IDataSetExportationService { private readonly FullDataSetFactory _fullDataSetFactory; private readonly IDraftDataSetExportationService _draftDataSetExportationService; + private readonly ICompleteDataSetExportationService _completeDataSetExportationService; private readonly IDataSetRepository _dataSetRepository; + private readonly IAuthService _authService; public DataSetExportationService(FullDataSetFactory fullDataSetFactory, IDraftDataSetExportationService draftDataSetExportationService, - IDataSetRepository dataSetRepository) + IDataSetRepository dataSetRepository, ICompleteDataSetExportationService completeDataSetExportationService, + IAuthService authService) { _fullDataSetFactory = fullDataSetFactory; _dataSetRepository = dataSetRepository; _draftDataSetExportationService = draftDataSetExportationService; + _completeDataSetExportationService = completeDataSetExportationService; + _authService = authService; } public Result ExportDraft(DraftDataSetExportDTO dataSetDTO) @@ -30,6 +36,12 @@ public Result ExportDraft(DraftDataSetExportDTO dataSetDTO) return Result.Ok(exportPath); } + public Result ExportComplete(int datasetId, CompleteDataSetExportDTO dataSetDTO) + { + var annotationsFilesPaths = File.ReadAllLines(dataSetDTO.AnnotationsPath); + return this.Export(datasetId, annotationsFilesPaths, dataSetDTO.ExportPath); + } + private Result GetDataSetForExport(int id) { var dataSet = _dataSetRepository.GetDataSetForExport(id); @@ -37,15 +49,15 @@ private Result GetDataSetForExport(int id) return Result.Ok(dataSet); } - public Result Export(IDictionary projects, List annotators, string outputPath) + public Result Export(int datasetId, string[] annotationsFilesPaths, string outputPath) { + List annotators = _authService.GetAll().Value; try { - var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projects, annotators, annotatorId: null); - var exporter = new CompleteDataSetExporter(outputPath); + var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(datasetId, annotators, annotationsFilesPaths); foreach (var codeSmellGroup in instancesGroupedBySmells) { - exporter.Export(codeSmellGroup.Instances, codeSmellGroup.CodeSmell.Name, "DataSet_" + codeSmellGroup.CodeSmell.Name); + _completeDataSetExportationService.Export(outputPath, codeSmellGroup.Instances, codeSmellGroup.CodeSmell.Name, "DataSet_" + codeSmellGroup.CodeSmell.Name); } return Result.Ok("Data set exported: " + outputPath); } catch (IOException e) diff --git a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs index a4ef769b..9dcf55c4 100644 --- a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs @@ -27,6 +27,11 @@ public ExcelImporter(string sourceFolder, IAnnotationRepository annotationReposi _annotationRepository = annotationRepository; } + public ExcelImporter(IAnnotationRepository annotationRepository) + { + _annotationRepository = annotationRepository; + } + /// /// This logic is highly dependent on the appropriate excel file structure. /// It examines excel documents in the sourceFolder directory and its subdirectories. @@ -66,6 +71,21 @@ private static List GetWorksheets(IEnumerable docu return sheets; } + internal DataSetProject ImportAnnotationsFile(string annotationsFilePath) + { + var project = new DataSetProject(); + + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + var sheets = new ExcelPackage(new FileInfo(annotationsFilePath)).Workbook.Worksheets; + foreach (var excelWorksheet in sheets) + { + project.AddCandidateInstance(new SmellCandidateInstances(_annotationRepository.GetCodeSmell(excelWorksheet.Name), ExtractInstances(excelWorksheet))); + project.Url = excelWorksheet.Cells["A2"].Text; + } + + return project; + } + private List ExtractInstances(ExcelWorksheet sheet) { var instances = new List(); diff --git a/DataSetExplorer/Core/DataSetSerializer/ICompleteDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/ICompleteDataSetExportationService.cs new file mode 100644 index 00000000..6c9f959c --- /dev/null +++ b/DataSetExplorer/Core/DataSetSerializer/ICompleteDataSetExportationService.cs @@ -0,0 +1,10 @@ +using DataSetExplorer.Core.DataSets.Model; +using System.Collections.Generic; + +namespace DataSetExplorer.Core.DataSetSerializer +{ + public interface ICompleteDataSetExportationService + { + public void Export(string exportPath, List dataSetInstances, string smell, string fileName); + } +} diff --git a/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs index 5e197d7e..df10de89 100644 --- a/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs @@ -7,7 +7,8 @@ namespace DataSetExplorer.Core.DataSetSerializer { public interface IDataSetExportationService { - public Result Export(IDictionary projects, List annotators, string outputPath); + public Result Export(int datasetId, string[] annotationsFilesPaths, string outputPath); public Result ExportDraft(DraftDataSetExportDTO dataSetDTO); + public Result ExportComplete(int datasetId, CompleteDataSetExportDTO dataSetDTO); } } diff --git a/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs b/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs index 2c4b5f95..5e905196 100644 --- a/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs +++ b/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs @@ -13,11 +13,14 @@ public class FullDataSetFactory { private readonly IInstanceRepository _instanceRepository; private readonly IAnnotationRepository _annotationRepository; + private readonly IProjectService _projectService; - public FullDataSetFactory(IInstanceRepository instanceRepository, IAnnotationRepository annotationRepository) + public FullDataSetFactory(IInstanceRepository instanceRepository, IAnnotationRepository annotationRepository, + IProjectService projectService) { _instanceRepository = instanceRepository; _annotationRepository = annotationRepository; + _projectService = projectService; } public FullDataSetFactory() { } @@ -40,6 +43,37 @@ public List GetAnnotatedInstancesGroupedBySmells(IDicti return allAnnotatedInstances; } + public List GetAnnotatedInstancesGroupedBySmells(int datasetId, List annotators, string[] annotationsFilesPaths) + { + var allAnnotatedInstances = new List(); + var projects = _projectService.GetAllByDatasetId(datasetId).Value; + + foreach (var project in projects) + { + AddInstancesToCandidates(allAnnotatedInstances, project.CandidateInstances.ToList()); + var importer = new ExcelImporter(_annotationRepository); + foreach (var annotationsFilePath in annotationsFilesPaths) + { + var importedProject = importer.ImportAnnotationsFile(annotationsFilePath); + if (importedProject.Url.Equals(project.Url)) JoinAnnotations(project, importedProject); + } + } + return allAnnotatedInstances; + } + + private void JoinAnnotations(DataSetProject project, DataSetProject importedProject) + { + foreach(var candidate in project.CandidateInstances) + { + var importedCandidate = importedProject.CandidateInstances.First(c => c.CodeSmell.Name.Equals(candidate.CodeSmell.Name)); + foreach (var importedInstance in importedCandidate.Instances) + { + var instance = candidate.Instances.Find(x => x.Link.Equals(importedInstance.Link)); + importedInstance.Annotations.ToList().ForEach(a => instance.AddAnnotation(a)); + } + } + } + private static void AddInstancesToCandidates(List allAnnotatedInstances, List annotatedInstances) { foreach (var annotated in annotatedInstances) diff --git a/DataSetExplorer/Core/DataSets/IProjectService.cs b/DataSetExplorer/Core/DataSets/IProjectService.cs index 9f153ae9..cdb3db86 100644 --- a/DataSetExplorer/Core/DataSets/IProjectService.cs +++ b/DataSetExplorer/Core/DataSets/IProjectService.cs @@ -1,10 +1,12 @@ using DataSetExplorer.Core.DataSets.Model; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.DataSets { public interface IProjectService { Result GetProjectWithGraphInstances(int id); + Result> GetAllByDatasetId(int datasetId); } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs b/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs index 0188c53e..75afd372 100644 --- a/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs +++ b/DataSetExplorer/Core/DataSets/Model/DataSetProject.cs @@ -7,7 +7,7 @@ public class DataSetProject { public int Id { get; private set; } public string Name { get; private set; } - public string Url { get; private set; } + public string Url { get; set; } public HashSet CandidateInstances { get; internal set; } public List GraphInstances { get; internal set; } public ProjectState State { get; private set; } @@ -22,6 +22,11 @@ internal DataSetProject(string name, string url) public DataSetProject(string name) : this(name, null) { } + public DataSetProject() + { + CandidateInstances = new HashSet(); + } + internal void AddCandidateInstance(SmellCandidateInstances newCandidate) { if (CandidateInstances.TryGetValue(newCandidate, out var existingCandidate)) diff --git a/DataSetExplorer/Core/DataSets/ProjectService.cs b/DataSetExplorer/Core/DataSets/ProjectService.cs index 5950afd5..704a8c54 100644 --- a/DataSetExplorer/Core/DataSets/ProjectService.cs +++ b/DataSetExplorer/Core/DataSets/ProjectService.cs @@ -1,6 +1,7 @@ using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Core.DataSets.Repository; using FluentResults; +using System.Collections.Generic; namespace DataSetExplorer.Core.DataSets { @@ -19,5 +20,10 @@ public Result GetProjectWithGraphInstances(int id) if (project == default) return Result.Fail($"Project with id: {id} does not exist."); return Result.Ok(project); } + + public Result> GetAllByDatasetId(int datasetId) + { + return Result.Ok(_projectRepository.GetAllByDatasetId(datasetId)); + } } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs index cac2eba8..439a9521 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IProjectRepository.cs @@ -10,5 +10,6 @@ public interface IProjectRepository DataSetProject Update(DataSetProject dataSetProject); DataSetProject Delete(int id); DataSetProject GetProjectWithGraphInstances(int id); + List GetAllByDatasetId(int datasetId); } } diff --git a/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs index cc0937d3..9b569faa 100644 --- a/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/ProjectDatabaseRepository.cs @@ -59,5 +59,16 @@ public DataSetProject GetProjectWithGraphInstances(int id) .Include(p => p.GraphInstances).ThenInclude(i => i.RelatedInstances) .FirstOrDefault(p => p.Id == id); } + + public List GetAllByDatasetId(int datasetId) + { + return _dbContext.DataSets + .Include(d => d.Projects).ThenInclude(p => p.CandidateInstances).ThenInclude(c => c.Instances) + .Include(d => d.Projects).ThenInclude(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.Annotations).ThenInclude(a => a.Annotator) + .Include(d => d.Projects).ThenInclude(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.Annotations).ThenInclude(a => a.ApplicableHeuristics) + .Include(d => d.Projects).ThenInclude(p => p.CandidateInstances).ThenInclude(c => c.Instances).ThenInclude(i => i.Annotations).ThenInclude(a => a.InstanceSmell) + .Include(d => d.Projects).ThenInclude(p => p.CandidateInstances).ThenInclude(c => c.CodeSmell) + .FirstOrDefault(d => d.Id == datasetId).Projects.ToList(); + } } } diff --git a/DataSetExplorer/Program.cs b/DataSetExplorer/Program.cs index a43d6eb3..5b1cc334 100644 --- a/DataSetExplorer/Program.cs +++ b/DataSetExplorer/Program.cs @@ -24,7 +24,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) => private static void CreateConsoleUI() { new MainMenu( - new DataSetExportationService(new FullDataSetFactory(), null, null), + new DataSetExportationService(new FullDataSetFactory(), null, null, null, null), new DataSetCreationService(new GitCodeRepository(), null, null, null)) .Run(); } diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index 3cb133ed..98225549 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -62,6 +62,7 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); } diff --git a/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs b/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs index 065157c7..c04040df 100644 --- a/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs +++ b/DataSetExplorer/UI/ConsoleApp/DataSetIO.cs @@ -29,7 +29,9 @@ internal static List GetAnnotators() foreach (string line in lines) { string[] columns = line.Split(','); - annotators.Add(new Annotator(int.Parse(columns[0]), columns[1], columns[2], int.Parse(columns[3]), int.Parse(columns[4]))); + if (columns.Length == 4) annotators.Add(new Annotator(int.Parse(columns[0]), columns[1], int.Parse(columns[2]), int.Parse(columns[3]))); + else annotators.Add(new Annotator(int.Parse(columns[0]), columns[1], columns[2], int.Parse(columns[3]), int.Parse(columns[4]))); + } return annotators; } diff --git a/DataSetExplorer/UI/ConsoleApp/MainMenu.cs b/DataSetExplorer/UI/ConsoleApp/MainMenu.cs index 3f32722a..701f4232 100644 --- a/DataSetExplorer/UI/ConsoleApp/MainMenu.cs +++ b/DataSetExplorer/UI/ConsoleApp/MainMenu.cs @@ -67,11 +67,11 @@ private void CreateDataSet() private void ExportDataSet() { - var projects = DataSetIO.GetProjects("local repo folder and annotations folder"); + /*var projects = DataSetIO.GetProjects("local repo folder and annotations folder"); var annotators = DataSetIO.GetAnnotators(); string outputPath = ConsoleIO.GetAnswerOnQuestion("Enter output folder path: "); Result result = _dataSetExportationService.Export(projects, annotators, outputPath); - Console.Write(result.ToString()); + Console.Write(result);*/ } private static void WriteMenuWithOptions() diff --git a/DataSetExplorer/UI/Controllers/Dataset/DTOs/CompleteDataSetExportDTO.cs b/DataSetExplorer/UI/Controllers/Dataset/DTOs/CompleteDataSetExportDTO.cs new file mode 100644 index 00000000..f6ffbf08 --- /dev/null +++ b/DataSetExplorer/UI/Controllers/Dataset/DTOs/CompleteDataSetExportDTO.cs @@ -0,0 +1,8 @@ +namespace DataSetExplorer.UI.Controllers.Dataset.DTOs +{ + public class CompleteDataSetExportDTO + { + public string AnnotationsPath { get; set; } + public string ExportPath { get; set; } + } +} diff --git a/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs b/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs index e2122db6..3e969117 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs @@ -39,13 +39,21 @@ public IActionResult UpdateDataSet([FromBody] DatasetDTO datasetDto) } [HttpPost] - [Route("export")] - public IActionResult ExportDataSet([FromBody] DraftDataSetExportDTO dataSetDTO) + [Route("export-draft")] + public IActionResult ExportDraftDataSet([FromBody] DraftDataSetExportDTO dataSetDTO) { var exportPath = _dataSetExportationService.ExportDraft(dataSetDTO); return Ok(new FluentResults.Result().WithSuccess("Successfully exported to " + exportPath)); } + [HttpPost] + [Route("{id}/export-complete")] + public IActionResult ExportCompleteDataSet([FromRoute] int id, [FromBody] CompleteDataSetExportDTO dataSetDTO) + { + var exportPath = _dataSetExportationService.ExportComplete(id, dataSetDTO); + return Ok(new FluentResults.Result().WithSuccess("Successfully exported to " + exportPath)); + } + [HttpPost] [Route("{name}")] public IActionResult CreateDataSet([FromBody] List codeSmells, [FromRoute] string name) From 40488290dfa61507f4da8a25dddb03d649eef5a2 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 23 Feb 2023 17:20:06 +0100 Subject: [PATCH 36/46] feat[DE]: Add clean code analysis export - clean names --- .../CleanCodeAnalysisService.cs | 105 ++++++++++++++++++ .../ICleanCodeAnalysisService.cs | 11 ++ .../CleanCodeAnalysis/Model/Identifier.cs | 27 +++++ .../CompleteDataSetExportationService.cs | 5 +- .../Core/DataSetSerializer/ExcelImporter.cs | 7 ++ .../IDataSetExportationService.cs | 4 +- .../Clean_Names_Analysis_Template.xlsx | Bin 0 -> 8849 bytes .../DataSets/CaDETToDataSetProjectBuilder.cs | 18 ++- .../Core/DataSets/FullDataSetFactory.cs | 7 +- .../Core/DataSets/IInstanceService.cs | 2 + .../Core/DataSets/InstanceService.cs | 14 +++ .../Core/DataSets/Model/Instance.cs | 21 +++- .../Repository/IInstanceRepository.cs | 2 + .../Repository/InstanceDatabaseRepository.cs | 31 ++++++ .../Database/DataSetExplorerContext.cs | 10 ++ DataSetExplorer/Startup.cs | 4 +- .../Dataset/DTOs/CleanCodeAnalysisDTO.cs | 8 ++ .../Controllers/Dataset/DataSetController.cs | 13 ++- .../Controllers/Dataset/ProjectController.cs | 13 ++- 19 files changed, 290 insertions(+), 12 deletions(-) create mode 100644 DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs create mode 100644 DataSetExplorer/Core/CleanCodeAnalysis/ICleanCodeAnalysisService.cs create mode 100644 DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs create mode 100644 DataSetExplorer/Core/DataSetSerializer/Template/Clean_Names_Analysis_Template.xlsx create mode 100644 DataSetExplorer/UI/Controllers/Dataset/DTOs/CleanCodeAnalysisDTO.cs diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs new file mode 100644 index 00000000..65d4e53b --- /dev/null +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -0,0 +1,105 @@ +using DataSetExplorer.Core.DataSets; +using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.UI.Controllers.Dataset.DTOs; +using FluentResults; +using OfficeOpenXml; +using System.Collections.Generic; +using System.IO; + +namespace DataSetExplorer.Core.CleanCodeAnalysis +{ + public class CleanCodeAnalysisService : ICleanCodeAnalysisService + { + private readonly string _cleanNamesAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Names_Analysis_Template.xlsx"; + private readonly string _cleanFunctionsAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Functions_Analysis_Template.xlsx"; + private readonly string _cleanClassesAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Classes_Template.xlsx"; + private string _exportPath; + private ExcelPackage _excelFile; + private ExcelWorksheet _sheet; + private readonly IInstanceService _instanceService; + + public CleanCodeAnalysisService(IInstanceService instanceService) + { + _instanceService = instanceService; + } + + public Result ExportDatasetAnalysis(int datasetId, CleanCodeAnalysisDTO analysisOptions) + { + _exportPath = analysisOptions.ExportPath; + foreach (var option in analysisOptions.CleanCodeOptions) + { + if (option.Equals("Clean names")) + ExportCleanNamesAnalysis(_instanceService.GetAllByDatasetId(datasetId).Value); + if (option.Equals("Clean functions")) + ExportCleanFunctionsAnalysis(); + if (option.Equals("Clean classes")) + ExportCleanClassesAnalysis(); + } + return Result.Ok(analysisOptions.ExportPath); + } + + public Result ExportProjectAnalysis(int projectId, CleanCodeAnalysisDTO analysisOptions) + { + _exportPath = analysisOptions.ExportPath; + foreach (var option in analysisOptions.CleanCodeOptions) + { + if (option.Equals("Clean names")) + ExportCleanNamesAnalysis(_instanceService.GetAllByProjectId(projectId).Value); + if (option.Equals("Clean functions")) + ExportCleanFunctionsAnalysis(); + if (option.Equals("Clean classes")) + ExportCleanClassesAnalysis(); + } + return Result.Ok(analysisOptions.ExportPath); + } + + private void ExportCleanNamesAnalysis(Dictionary> instances) + { + if (instances == default) return; + + foreach (var projectName in instances.Keys) + { + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + _excelFile = new ExcelPackage(new FileInfo(_cleanNamesAnalysisTemplatePath)); + _sheet = _excelFile.Workbook.Worksheets[0]; + PopulateCleanNamesTemplate(instances[projectName]); + Serialize(projectName + "_CleanNames"); + } + } + + private void PopulateCleanNamesTemplate(List instances) + { + var identifierCount = 0; + for (var i = 0; i < instances.Count; i++) + { + var row = 3 + i + identifierCount; + _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; + _sheet.Cells[row, 2].Value = instances[i].Link; + + instances[i].Identifiers.Sort((x, y) => x.Type.CompareTo(y.Type)); + for (var j = 0; j < instances[i].Identifiers.Count; j++) + { + _sheet.Cells[row + j, 3].Value = instances[i].Identifiers[j].Name; + _sheet.Cells[row + j, 4].Value = instances[i].Identifiers[j].Type.ToString(); + } + identifierCount += instances[i].Identifiers.Count; + } + } + + private void ExportCleanFunctionsAnalysis() + { + // TODO + } + + private void ExportCleanClassesAnalysis() + { + // TODO + } + + private void Serialize(string fileName) + { + var filePath = _exportPath + fileName + ".xlsx"; + _excelFile.SaveAs(new FileInfo(filePath)); + } + } +} diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/ICleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/ICleanCodeAnalysisService.cs new file mode 100644 index 00000000..b217380e --- /dev/null +++ b/DataSetExplorer/Core/CleanCodeAnalysis/ICleanCodeAnalysisService.cs @@ -0,0 +1,11 @@ +using DataSetExplorer.UI.Controllers.Dataset.DTOs; +using FluentResults; + +namespace DataSetExplorer.Core.CleanCodeAnalysis +{ + public interface ICleanCodeAnalysisService + { + public Result ExportDatasetAnalysis(int datasetId, CleanCodeAnalysisDTO analysisOptions); + public Result ExportProjectAnalysis(int projectId, CleanCodeAnalysisDTO analysisOptions); + } +} diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs b/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs new file mode 100644 index 00000000..eb12e68f --- /dev/null +++ b/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs @@ -0,0 +1,27 @@ +namespace DataSetExplorer.Core.CleanCodeAnalysis.Model +{ + public class Identifier + { + public int Id { get; private set; } + public string Name { get; private set; } + public IdentifierType Type { get; private set; } + + public Identifier(string name, IdentifierType type) + { + Name = name; + Type = type; + } + + private Identifier() { } + + } + + public enum IdentifierType + { + Class, + Field, + Member, + Variable, + Parameter + } +} \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs index caf53ccb..852f8b4c 100644 --- a/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/CompleteDataSetExportationService.cs @@ -50,8 +50,11 @@ private void PopulateAnnotationsTemplate(List instances) var row = 3 + i; _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; _sheet.Cells[row, 2].Value = instances[i].Link; - _sheet.Cells[row, 3].Value = + if (instances[i].Annotations.Count > 0) + { + _sheet.Cells[row, 3].Value = instances[i].Annotations.First().InstanceSmell.Name; + } _sheet.Cells[row, 4].Value = instances[i].ProjectLink; PopulateAnnotations(instances[i], row); } diff --git a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs index 9dcf55c4..b2bf75bb 100644 --- a/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs +++ b/DataSetExplorer/Core/DataSetSerializer/ExcelImporter.cs @@ -86,6 +86,13 @@ internal DataSetProject ImportAnnotationsFile(string annotationsFilePath) return project; } + internal string GetProjectUrl(string annotationsFilePath) + { + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + var sheets = new ExcelPackage(new FileInfo(annotationsFilePath)).Workbook.Worksheets; + return sheets[0].Cells["A2"].Text; + } + private List ExtractInstances(ExcelWorksheet sheet) { var instances = new List(); diff --git a/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs b/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs index df10de89..cc69e3d1 100644 --- a/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs +++ b/DataSetExplorer/Core/DataSetSerializer/IDataSetExportationService.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using DataSetExplorer.Core.Annotations.Model; -using DataSetExplorer.UI.Controllers.Dataset.DTOs; +using DataSetExplorer.UI.Controllers.Dataset.DTOs; using FluentResults; namespace DataSetExplorer.Core.DataSetSerializer diff --git a/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Names_Analysis_Template.xlsx b/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Names_Analysis_Template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2dd54591aed4a84b1595c4dd5d337049033f4447 GIT binary patch literal 8849 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 literal 0 HcmV?d00001 diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index 552dcee3..65e02f99 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -6,6 +6,7 @@ using CodeModel.CaDETModel.CodeItems; using DataSetExplorer.Core.Annotations.Model; using DataSetExplorer.Core.DataSets.Model; +using DataSetExplorer.Core.CleanCodeAnalysis.Model; namespace DataSetExplorer.Core.DataSets { @@ -27,6 +28,7 @@ internal class CaDETToDataSetProjectBuilder private readonly List _codeSmells; private readonly InstanceFilter _instanceFilter; private readonly Dictionary> _classCouplings = new Dictionary>(); + private readonly List _cleanClassNaming = new List(); internal CaDETToDataSetProjectBuilder(InstanceFilter instanceFilter, string projectAndCommitUrl, string projectName, string projectPath, List ignoredFolders, LanguageEnum language, bool includeClasses, bool includeMembers, List codeSmells) { @@ -209,10 +211,21 @@ private List CaDETToDataSetProjectClasses(List cadetClasse { return cadetClasses.Select(c => new Instance( c.FullName, GetCodeUrl(c.FullName), _projectAndCommitUrl, SnippetType.Class, - _cadetProject.GetMetricsForCodeSnippet(c.FullName), FindClassRelatedInstances(c) + _cadetProject.GetMetricsForCodeSnippet(c.FullName), FindClassRelatedInstances(c), FindAllIdentifiers(c) )).ToList(); } + private List FindAllIdentifiers(CaDETClass cadetClass) + { + var identifiers = new List(); + identifiers.Add(new Identifier(cadetClass.Name, IdentifierType.Class)); + cadetClass.Fields.ForEach(field => identifiers.Add(new Identifier(field.Name, IdentifierType.Field))); + cadetClass.Members.ForEach(member => identifiers.Add(new Identifier(member.Name, IdentifierType.Member))); + cadetClass.Members.ForEach(member => member.Variables.ForEach(variable => identifiers.Add(new Identifier(variable.Name, IdentifierType.Variable)))); + cadetClass.Members.ForEach(member => member.Params.ForEach(param => identifiers.Add(new Identifier(param.Name, IdentifierType.Parameter)))); + return identifiers; + } + private void CreateCouplingMap(List cadetClasses) { foreach (var instance in cadetClasses) @@ -359,7 +372,8 @@ private List BuildMembers() private List CaDETToDataSetFunction(List cadetMembers) { return cadetMembers.Select(m => new Instance( - m.Signature(), GetCodeUrl(m.Signature()), _projectAndCommitUrl, SnippetType.Function, _cadetProject.GetMetricsForCodeSnippet(m.Signature()), FindMethodRelatedInstances(m) + m.Signature(), GetCodeUrl(m.Signature()), _projectAndCommitUrl, SnippetType.Function, + _cadetProject.GetMetricsForCodeSnippet(m.Signature()), FindMethodRelatedInstances(m) )).ToList(); } diff --git a/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs b/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs index 5e905196..4caa02a8 100644 --- a/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs +++ b/DataSetExplorer/Core/DataSets/FullDataSetFactory.cs @@ -54,8 +54,11 @@ public List GetAnnotatedInstancesGroupedBySmells(int da var importer = new ExcelImporter(_annotationRepository); foreach (var annotationsFilePath in annotationsFilesPaths) { - var importedProject = importer.ImportAnnotationsFile(annotationsFilePath); - if (importedProject.Url.Equals(project.Url)) JoinAnnotations(project, importedProject); + if (project.Url.Equals(importer.GetProjectUrl(annotationsFilePath))) + { + var importedProject = importer.ImportAnnotationsFile(annotationsFilePath); + if (importedProject.Url.Equals(project.Url)) JoinAnnotations(project, importedProject); + } } } return allAnnotatedInstances; diff --git a/DataSetExplorer/Core/DataSets/IInstanceService.cs b/DataSetExplorer/Core/DataSets/IInstanceService.cs index 59a104a5..ddd877ca 100644 --- a/DataSetExplorer/Core/DataSets/IInstanceService.cs +++ b/DataSetExplorer/Core/DataSets/IInstanceService.cs @@ -8,6 +8,8 @@ namespace DataSetExplorer.Core.DataSets { public interface IInstanceService { + Result>> GetAllByDatasetId(int datasetId); + Result>> GetAllByProjectId(int projectId); Result GetInstanceWithRelatedInstances(int id); Result GetInstanceWithAnnotations(int id); Result> GetInstancesForSmell(string codeSmellName); diff --git a/DataSetExplorer/Core/DataSets/InstanceService.cs b/DataSetExplorer/Core/DataSets/InstanceService.cs index 0ae1dea5..23051b4d 100644 --- a/DataSetExplorer/Core/DataSets/InstanceService.cs +++ b/DataSetExplorer/Core/DataSets/InstanceService.cs @@ -22,6 +22,20 @@ public InstanceService(IInstanceRepository instanceRepository, IDataSetCreationS _annotationRepository = annotationRepository; } + public Result>> GetAllByDatasetId(int datasetId) + { + var instances = _instanceRepository.GetAllByDatasetId(datasetId); + if (instances == default) return Result.Fail($"Dataset with id: {datasetId} does not exist."); + return Result.Ok(instances); + } + + public Result>> GetAllByProjectId(int projectId) + { + var instances = _instanceRepository.GetAllByProjectId(projectId); + if (instances == default) return Result.Fail($"Project with id: {projectId} does not exist."); + return Result.Ok(instances); + } + public Result GetInstanceWithRelatedInstances(int id) { var instance = _instanceRepository.GetInstanceWithRelatedInstances(id); diff --git a/DataSetExplorer/Core/DataSets/Model/Instance.cs b/DataSetExplorer/Core/DataSets/Model/Instance.cs index de8a0c27..ddeee7fb 100644 --- a/DataSetExplorer/Core/DataSets/Model/Instance.cs +++ b/DataSetExplorer/Core/DataSets/Model/Instance.cs @@ -3,6 +3,7 @@ using System.Linq; using CodeModel.CaDETModel.CodeItems; using DataSetExplorer.Core.Annotations.Model; +using DataSetExplorer.Core.CleanCodeAnalysis.Model; namespace DataSetExplorer.Core.DataSets.Model { @@ -16,20 +17,37 @@ public class Instance public ISet Annotations { get; private set; } public Dictionary MetricFeatures { get; internal set; } // TODO: Expand and replace with the IFeature if a new feature type is introduced public List RelatedInstances { get; private set; } + public List Identifiers { get; private set; } - internal Instance(string codeSnippetId, string link, string projectLink, SnippetType type, Dictionary metricFeatures, List relatedInstances) + internal Instance(string codeSnippetId, string link, string projectLink, SnippetType type, Dictionary metricFeatures, List relatedInstances, List identifiers) { CodeSnippetId = codeSnippetId; Link = link; ProjectLink = projectLink; Type = type; RelatedInstances = relatedInstances; + Identifiers = identifiers; Annotations = new HashSet(); SetMetricFeatures(metricFeatures); Validate(); } + internal Instance(string codeSnippetId, string link, string projectLink, SnippetType type, Dictionary metricFeatures, List relatedInstances) + { + CodeSnippetId = codeSnippetId; + Link = link; + ProjectLink = projectLink; + Type = type; + RelatedInstances = relatedInstances; + + Annotations = new HashSet(); + SetMetricFeatures(metricFeatures); + Validate(); + } + private Instance() { } @@ -121,6 +139,7 @@ private bool HasMajoritySeverityVote( private string GetAnnotationFromMostExperiencedAnnotator() { + if (Annotations.Count == 0) return "0"; return Annotations.OrderBy(a => a.Annotator.Ranking).First().Severity; } diff --git a/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs index bf9ae4ed..644f096d 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs @@ -8,6 +8,8 @@ namespace DataSetExplorer.Core.DataSets.Repository public interface IInstanceRepository { Instance Get(int id); + Dictionary> GetAllByDatasetId(int datasetId); + Dictionary> GetAllByProjectId(int projectId); InstanceDTO GetInstanceWithRelatedInstances(int id); IEnumerable GetInstancesAnnotatedByAnnotator(int projectId, int? annotatorId); IEnumerable GetAnnotatedInstances(int projectId); diff --git a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs index 5653d2f1..7fe397dd 100644 --- a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs @@ -22,6 +22,37 @@ public Instance Get(int id) return _dbContext.Instances.Include(i => i.Annotations).FirstOrDefault(i => i.Id == id); } + public Dictionary> GetAllByDatasetId(int datasetId) + { + var instances = new Dictionary>(); + var dataset = _dbContext.DataSets + .Include(d => d.Projects) + .ThenInclude(p => p.CandidateInstances) + .ThenInclude(c => c.Instances) + .ThenInclude(i => i.Identifiers) + .FirstOrDefault(d => d.Id == datasetId); + if (dataset == default) return null; + + foreach(var project in dataset.Projects) + instances.Add(project.Name, project.CandidateInstances.SelectMany(c => c.Instances).ToList()); + + return instances; + } + + public Dictionary> GetAllByProjectId(int projectId) + { + var instances = new Dictionary>(); + var project = _dbContext.DataSetProjects + .Include(p => p.CandidateInstances) + .ThenInclude(c => c.Instances) + .ThenInclude(i => i.Identifiers) + .FirstOrDefault(p => p.Id == projectId); + if (project == default) return null; + + instances.Add(project.Name, project.CandidateInstances.SelectMany(c => c.Instances).ToList()); + return instances; + } + public InstanceDTO GetInstanceWithRelatedInstances(int id) { return new InstanceDTO(_dbContext.Instances diff --git a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs index c9c3d0a4..8809dce2 100644 --- a/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs +++ b/DataSetExplorer/Infrastructure/Database/DataSetExplorerContext.cs @@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Newtonsoft.Json; using DataSetExplorer.Core.AnnotationSchema.Model; +using DataSetExplorer.Core.CleanCodeAnalysis.Model; namespace DataSetExplorer.Infrastructure.Database { @@ -24,6 +25,7 @@ public class DataSetExplorerContext : DbContext public DbSet SmellCandidateInstances { get; set; } public DbSet GraphInstances { get; set; } public DbSet GraphRelatedInstances { get; set; } + public DbSet Identifiers { get; set; } public DataSetExplorerContext(DbContextOptions options) : base(options) { } @@ -78,6 +80,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasOne().WithMany(i => i.RelatedInstances) .OnDelete(DeleteBehavior.Cascade); + modelBuilder.Entity().HasOne().WithMany(i => i.Identifiers) + .OnDelete(DeleteBehavior.Cascade); + modelBuilder.Entity().HasOne().WithMany(i => i.RelatedInstances) .OnDelete(DeleteBehavior.Cascade); @@ -102,6 +107,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(c => c.SnippetType) .HasConversion(); + modelBuilder + .Entity() + .Property(i => i.Type) + .HasConversion(); + modelBuilder .Entity() .Property(c => c.SnippetType) diff --git a/DataSetExplorer/Startup.cs b/DataSetExplorer/Startup.cs index 98225549..cf1a0f6e 100644 --- a/DataSetExplorer/Startup.cs +++ b/DataSetExplorer/Startup.cs @@ -15,6 +15,7 @@ using DataSetExplorer.Core.DataSetSerializer; using DataSetExplorer.Core.Auth; using DataSetExplorer.Core.Auth.Repository; +using DataSetExplorer.Core.CleanCodeAnalysis; namespace DataSetExplorer { @@ -54,7 +55,8 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - + + services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/DataSetExplorer/UI/Controllers/Dataset/DTOs/CleanCodeAnalysisDTO.cs b/DataSetExplorer/UI/Controllers/Dataset/DTOs/CleanCodeAnalysisDTO.cs new file mode 100644 index 00000000..457b4025 --- /dev/null +++ b/DataSetExplorer/UI/Controllers/Dataset/DTOs/CleanCodeAnalysisDTO.cs @@ -0,0 +1,8 @@ +namespace DataSetExplorer.UI.Controllers.Dataset.DTOs +{ + public class CleanCodeAnalysisDTO + { + public string ExportPath { get; set; } + public string[] CleanCodeOptions { get; set; } + } +} diff --git a/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs b/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs index 3e969117..fbf136e8 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/DataSetController.cs @@ -4,6 +4,7 @@ using DataSetExplorer.Core.DataSets; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.Core.DataSetSerializer; +using DataSetExplorer.Core.CleanCodeAnalysis; using DataSetExplorer.UI.Controllers.Dataset.DTOs; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; @@ -19,13 +20,15 @@ public class DataSetController : ControllerBase private readonly IMapper _mapper; private readonly IDataSetCreationService _dataSetCreationService; private readonly IDataSetExportationService _dataSetExportationService; + private readonly ICleanCodeAnalysisService _cleanCodeAnalysisService; public DataSetController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration, - IDataSetExportationService exportationService) + IDataSetExportationService exportationService, ICleanCodeAnalysisService cleanCodeAnalysisService) { _mapper = mapper; _dataSetCreationService = creationService; _dataSetExportationService = exportationService; + _cleanCodeAnalysisService = cleanCodeAnalysisService; _gitClonePath = configuration.GetValue("Workspace:GitClonePath"); } @@ -54,6 +57,14 @@ public IActionResult ExportCompleteDataSet([FromRoute] int id, [FromBody] Comple return Ok(new FluentResults.Result().WithSuccess("Successfully exported to " + exportPath)); } + [HttpPost] + [Route("{id}/export-clean-code-analysis")] + public IActionResult ExportCleanCodeAnalysis([FromRoute] int id, [FromBody] CleanCodeAnalysisDTO dataSetDTO) + { + var exportPath = _cleanCodeAnalysisService.ExportDatasetAnalysis(id, dataSetDTO).Value; + return Ok(new FluentResults.Result().WithSuccess("Successfully exported to " + exportPath)); + } + [HttpPost] [Route("{name}")] public IActionResult CreateDataSet([FromBody] List codeSmells, [FromRoute] string name) diff --git a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs index 629c04e3..57c34ee1 100644 --- a/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs +++ b/DataSetExplorer/UI/Controllers/Dataset/ProjectController.cs @@ -1,6 +1,7 @@ using AutoMapper; using DataSetExplorer.Core.CommunityDetection.Model; using DataSetExplorer.Core.DataSets; +using DataSetExplorer.Core.CleanCodeAnalysis; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.UI.Controllers.Dataset.DTOs; using Microsoft.AspNetCore.Mvc; @@ -18,14 +19,16 @@ public class ProjectController : ControllerBase private readonly IDataSetCreationService _dataSetCreationService; private readonly IProjectService _projectService; private readonly IGraphInstanceService _graphInstanceService; + private readonly ICleanCodeAnalysisService _cleanCodeAnalysisService; public ProjectController(IMapper mapper, IDataSetCreationService creationService, IConfiguration configuration, - IProjectService projectService, IGraphInstanceService graphInstanceService) + IProjectService projectService, IGraphInstanceService graphInstanceService, ICleanCodeAnalysisService cleanCodeAnalysisService) { _mapper = mapper; _dataSetCreationService = creationService; _projectService = projectService; _graphInstanceService = graphInstanceService; + _cleanCodeAnalysisService = cleanCodeAnalysisService; _gitClonePath = configuration.GetValue("Workspace:GitClonePath"); } @@ -89,5 +92,13 @@ public IActionResult GetGraphNeighboursInstances([FromRoute] int projectId, [Fro if (result.IsFailed) return BadRequest(new { message = result.Reasons[0].Message }); return Ok(result.Value); } + + [HttpPost] + [Route("{id}/export-clean-code-analysis")] + public IActionResult ExportCleanCodeAnalysis([FromRoute] int id, [FromBody] CleanCodeAnalysisDTO analysisExportOptions) + { + var exportPath = _cleanCodeAnalysisService.ExportProjectAnalysis(id, analysisExportOptions).Value; + return Ok(new FluentResults.Result().WithSuccess("Successfully exported to " + exportPath)); + } } } From 1d27d504c8ce46633fbed2ba603ed25f93d2258a Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Thu, 23 Feb 2023 18:18:53 +0100 Subject: [PATCH 37/46] feat[DE]: Add clean code analysis export - clean functions/classes --- .../CleanCodeAnalysisService.cs | 93 +++++++++++++++--- .../Clean_Classes_Analysis_Template.xlsx | Bin 0 -> 8783 bytes .../Clean_Functions_Analysis_Template.xlsx | Bin 0 -> 8785 bytes .../Core/DataSets/IInstanceService.cs | 6 +- .../Core/DataSets/InstanceService.cs | 22 ++++- .../Repository/IInstanceRepository.cs | 6 +- .../Repository/InstanceDatabaseRepository.cs | 30 +++++- 7 files changed, 135 insertions(+), 22 deletions(-) create mode 100644 DataSetExplorer/Core/DataSetSerializer/Template/Clean_Classes_Analysis_Template.xlsx create mode 100644 DataSetExplorer/Core/DataSetSerializer/Template/Clean_Functions_Analysis_Template.xlsx diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index 65d4e53b..68c6f322 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -1,4 +1,5 @@ -using DataSetExplorer.Core.DataSets; +using CodeModel.CaDETModel.CodeItems; +using DataSetExplorer.Core.DataSets; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.UI.Controllers.Dataset.DTOs; using FluentResults; @@ -12,7 +13,7 @@ public class CleanCodeAnalysisService : ICleanCodeAnalysisService { private readonly string _cleanNamesAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Names_Analysis_Template.xlsx"; private readonly string _cleanFunctionsAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Functions_Analysis_Template.xlsx"; - private readonly string _cleanClassesAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Classes_Template.xlsx"; + private readonly string _cleanClassesAnalysisTemplatePath = "./Core/DataSetSerializer/Template/Clean_Classes_Analysis_Template.xlsx"; private string _exportPath; private ExcelPackage _excelFile; private ExcelWorksheet _sheet; @@ -29,11 +30,11 @@ public Result ExportDatasetAnalysis(int datasetId, CleanCodeAnalysisDTO foreach (var option in analysisOptions.CleanCodeOptions) { if (option.Equals("Clean names")) - ExportCleanNamesAnalysis(_instanceService.GetAllByDatasetId(datasetId).Value); + ExportCleanNamesAnalysis(_instanceService.GetInstancesWithIdentifiersByDatasetId(datasetId).Value); if (option.Equals("Clean functions")) - ExportCleanFunctionsAnalysis(); + ExportCleanFunctionsAnalysis(_instanceService.GetInstancesByDatasetId(datasetId).Value); if (option.Equals("Clean classes")) - ExportCleanClassesAnalysis(); + ExportCleanClassesAnalysis(_instanceService.GetInstancesByDatasetId(datasetId).Value); } return Result.Ok(analysisOptions.ExportPath); } @@ -44,11 +45,11 @@ public Result ExportProjectAnalysis(int projectId, CleanCodeAnalysisDTO foreach (var option in analysisOptions.CleanCodeOptions) { if (option.Equals("Clean names")) - ExportCleanNamesAnalysis(_instanceService.GetAllByProjectId(projectId).Value); + ExportCleanNamesAnalysis(_instanceService.GetInstancesWithIdentifiersByProjectId(projectId).Value); if (option.Equals("Clean functions")) - ExportCleanFunctionsAnalysis(); + ExportCleanFunctionsAnalysis(_instanceService.GetInstancesByProjectId(projectId).Value); if (option.Equals("Clean classes")) - ExportCleanClassesAnalysis(); + ExportCleanClassesAnalysis(_instanceService.GetInstancesByProjectId(projectId).Value); } return Result.Ok(analysisOptions.ExportPath); } @@ -70,6 +71,7 @@ private void ExportCleanNamesAnalysis(Dictionary> instanc private void PopulateCleanNamesTemplate(List instances) { var identifierCount = 0; + instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); for (var i = 0; i < instances.Count; i++) { var row = 3 + i + identifierCount; @@ -86,14 +88,81 @@ private void PopulateCleanNamesTemplate(List instances) } } - private void ExportCleanFunctionsAnalysis() + private void ExportCleanFunctionsAnalysis(Dictionary> instances) { - // TODO + if (instances == default) return; + + foreach (var projectName in instances.Keys) + { + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + _excelFile = new ExcelPackage(new FileInfo(_cleanFunctionsAnalysisTemplatePath)); + _sheet = _excelFile.Workbook.Worksheets[0]; + PopulateCleanFunctionsTemplate(instances[projectName]); + Serialize(projectName + "_CleanFunctions"); + } + } + + private void PopulateCleanFunctionsTemplate(List instances) + { + instances.RemoveAll(i => i.Type.Equals(SnippetType.Class)); + for (var i = 0; i < instances.Count; i++) + { + var row = 3 + i; + _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; + _sheet.Cells[row, 2].Value = instances[i].Link; + + _sheet.Cells[2, 3].Value = CaDETMetric.MLOC; + _sheet.Cells[row, 3].Value = instances[i].MetricFeatures[CaDETMetric.MLOC]; + + _sheet.Cells[2, 4].Value = CaDETMetric.CYCLO_SWITCH; + _sheet.Cells[row, 4].Value = instances[i].MetricFeatures[CaDETMetric.CYCLO_SWITCH]; + + _sheet.Cells[2, 5].Value = CaDETMetric.MMNB; + _sheet.Cells[row, 5].Value = instances[i].MetricFeatures[CaDETMetric.MMNB]; + } } - private void ExportCleanClassesAnalysis() + private void ExportCleanClassesAnalysis(Dictionary> instances) { - // TODO + if (instances == default) return; + + foreach (var projectName in instances.Keys) + { + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + _excelFile = new ExcelPackage(new FileInfo(_cleanClassesAnalysisTemplatePath)); + _sheet = _excelFile.Workbook.Worksheets[0]; + PopulateCleanClassesTemplate(instances[projectName]); + Serialize(projectName + "_CleanClasses"); + } + } + + private void PopulateCleanClassesTemplate(List instances) + { + instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); + for (var i = 0; i < instances.Count; i++) + { + var row = 3 + i; + _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; + _sheet.Cells[row, 2].Value = instances[i].Link; + + _sheet.Cells[2, 3].Value = CaDETMetric.CLOC; + _sheet.Cells[row, 3].Value = instances[i].MetricFeatures[CaDETMetric.CLOC]; + + _sheet.Cells[2, 4].Value = CaDETMetric.WMC; + _sheet.Cells[row, 4].Value = instances[i].MetricFeatures[CaDETMetric.WMC]; + + _sheet.Cells[2, 5].Value = CaDETMetric.NAD; + _sheet.Cells[row, 5].Value = instances[i].MetricFeatures[CaDETMetric.NAD]; + + _sheet.Cells[2, 6].Value = CaDETMetric.NMD; + _sheet.Cells[row, 6].Value = instances[i].MetricFeatures[CaDETMetric.NMD]; + + _sheet.Cells[2, 7].Value = CaDETMetric.CBO; + _sheet.Cells[row, 7].Value = instances[i].MetricFeatures[CaDETMetric.CBO]; + + _sheet.Cells[2, 8].Value = CaDETMetric.DIT; + _sheet.Cells[row, 8].Value = instances[i].MetricFeatures[CaDETMetric.DIT]; + } } private void Serialize(string fileName) diff --git a/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Classes_Analysis_Template.xlsx b/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Classes_Analysis_Template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a088371370b241916b012c88e6d0bab60d8a5c3a GIT binary patch literal 8783 zcmeHsbyQSq+y2lD-Q7yp5YnAPgEWYA$Iu}mA>AP;B?8hQD2>DbN`oLJNDd$=-3Z^P z=lnc}bAI3Y{(s*+YxZ7y?R{TsKhJZ=bzhIB3KB9A02P1^008I#(t@EQE(ibsG711d z2tY?PmW8-@TDy3f>iD@@dzf(fIy=$jBO|ip0TAKu|M&P0o`DLTK9^1qUaS75q+FX` z^vlSyGIXkDD&xEBXwQ684DQyilCxX|GTUhB)}TWfwVXzbnGVIsDrcAsWu#zETo;BK zcg--1<15|w#lM4J$cGkI=*7QHioKUdhP}Is`l$|0wQ-E>xnyzyyrSV_b@eC~0$&ENZ~GMcmB$a-7-6nO1RW*u-0 z;V3*L4H;Rd%jHSh_iKHE?h%1!KL?m^-oZbj@~A{y2ksx~36k!SUZ&wBj0*`RX3qdJ ze9TFct3-~mkVCMxW!>$jPvWS~%V%-sa`L5V7t{A~D6iphc5{OS(EMAN*6D)o9Kn50 z75)?x9;T-5)=nPWTtCkL4bT7JnEcDoD^k=nxBs>`vA8Bw4y-rZD z(ihyi_=3BXbM4GjcsdkeNQ#eJgRc5#=fvVSd+AS>`72@xh(zzy`&33`T)26mu`#)) zE4WoGb>n+a98a7)S5)?6@or6ID{m}$snWM_N8!`HTn*j`mp%oM@D)`AiTLvnqYr9^ z^A=}S2oo~eJCzaD4T5=_sUumBr_zfyuqC5}Rkz2U6Zd*p*nX}G=yjq$KBv&twiC9m zw#aoCVem7xa_Tsg%W5b59>A%d-Fu&bpWuvlM6ri4@A$D%E&u*Nj$gMRu&caxuP-!~ zwqzb&vHlq(!@Sw$Iq(3XLInVD;WOjw#O(udceH>&9DmfYLLDv03L68HZ3`eE_gN&z4C%3VA_2`}_{o&5GC zs3b|3nD$Lt;|Dc*B!%?_*II`6reUgKQKQ_~#RL(uJHbynsL5DkH_EcL zvtIW1B5N!&TJo=Y8wP(c;o)Q+A46%#@S?92P!`fhDBM(Z7SNw=I){oANF@dcJ#e9f#eB~vp}&~6kHqyin7YC1HtYC75!W?~pL;$WK0s;R~C z@YaZS4&EPIslJTS>RUr?>if=P7iVHg`yJ`uJUK)nE#naG!Od`QrU0NLz&-g_#{a87 z|C#*};N%P*5C7Rm#eFrEZa6u?yp9C`MenO+on@lu3p!e$WNS7t zm{j3Lf<*Z34)u7S-osf&B0Pq&m&6btKO%J66-9vz9S$L(TkKTQgesyC5^Qg7mG5BU zWO@)bNu>00IM-~(@$Q?C}MesWegS>bhJU&wQ!?WK&?Mm>)6YcHF(AtIu zx=dD^)te^S*%QF7;==wN4`x#XJ1pVOMm5rL;up_kK0&A73T!p6W zo_IinCtYN(BJE?=6pz*X=PkOsOP(^9{jBY?2OI-OyEZF*JrfJ?mHub)Gl|Jzp+W`# z6oCK$8T^eulAnj2wY8@Q_s#RlHi2}P7h|TiQd>}y za0^|sS4HWwaqKiJwDbo<^X*wKwT83A!Ldm%YZwiMr_@ur4~SW8EazmxMC$}%gs&Xa zqn)v<*@Dwl-|$m2$3#aQVG(*@L{>RM&8z&1^W4Ov5&Eb$8`wu@Le%!P*NOPHs>ESN zb>JGj`;8`ajLFNXv(^RJ#^6DJ70eF>l~71TdjLA&6*mJbG`_ysn}?UVbuDAVlqmxU zLo3QSe<3Fu+uc#Hhb?yB8j>ofh*q@?PH#_k3ZOe&FPPfq(|BWR1>YRhaCFDqA8#Gg%{aE?ko=wke8?&gs87I zN#f%K5LVZWkN)EZl^C6c7L@U8(}@$86Zi(?YO zIgiqZ9N#CRVtOgz-sv(k7>RsJsLX~4tr$7ec;kXuqDN(BVNfjI5H>eG?DUHLbX|~niOCC z($~f@caE=!qbG2{wMcKG_#W-Q2!2l!;T^on+@Yxw6>(B>Xz)?r(*g;JU?*4=w(q+T ztsi{0j4f4*w70yVocb~8my`bV)a>Lrj7|_%xaq4SgvmN%dq_l~ z`Pxk?OW!4VB_ZH~()}e7%YgECDHgSY{OQjuR=6BolZb^^7;VTl$`9)oW^42%>OJZA zta>Et!h~PsM~&vJDU zGUi>c=zj#IZm1^AAHPX=X|bWKy4f~F(G()~<9_%$+=jCjbIA*M@I9CL=V$*sRU|`| zyQQ!qOc_@Y>gPBa($&qSN&WZonG-Fu?9ptQ-`dA~n-wi55{r8HZWXuhMWUqIh}+(# z@QkaOu#qmU;xi4I;l;Kx2z%q~L?m^++Ad9oRNhxPRDX<@S@;n?Q`o2t=t^R-Q*WV^ z$m)0X46(-SYv>^@+il3R%X~xAMCDE~+_M6tk}p@@w&Ty=py&mm4W!+mr*DIC^%Q7r z(O1UJnwk{wB-I@&vn5*e(YY)7dvw*T(E2yhvM``LTWm4)O=l9xTtN3+qKSv|mY|vv zgV*OWJ02@z*v5mf_ml%$V)*u#|4OH9sIu?8fS0FeoFCG_&y3<}XYFjw{qy`YnGEXp zxy-_|F6p`?db41?#XwEGko0o*`b+tcX8DmgIZmKF@b261fswMDg^YqjsNKx=S3&`A z_prSJE;K>A2^h~a0#?z`EEfvI*kIYk>^G;chccRWmE?U@4f;0v9~X{Eil1L?Jmb(+ zz}$pB;>xgEwN=&~7zHbsF&*SputeUZ+$WNQmV*^*=uQ_K%nG{peFfOS!-0vZh+kaz zl%F1HP&8y<1$Z#l(OX!Q=Zr}Rv;p~LVvZb!p7*lF0DeoikZLG(%K=`{|J@jZ4w-JV~$ENuX)28guGLsPQ$k_;A+Y;qmlwA|34U zOqWKH?V;=PnPL(&GVmtr^LruJJ#^kPLtM$69McM092#lzfpaxnYGm`qhg0h$DQVkV zpZ0K2CLp4UkmR%nJ6i>z4>Bx}0N7S?t6#JeiPgZ!t$s}Io&1z<3azGT`shVLu2iJL zkBd!2da7+nSt3jtwQj&EV)?#fDcLoZkF1Wex;w1<4t$XmD$r?~PIPq1#U>fuTubR1 zKM=mUNG*5DO2$YbS;Q%=Fex4@R|ZBB4wc}0_6QbT*PlK7uttRzBGJpVn^H0?fnzL6 zq)dLaT_PZZXmrYgz#0RVm3keB19are=(Y;(*0Kx;MOHXr;vhldSepsdE-Q+0W(zhl zCKghs8I_?`kGFfo%MkaWSzSRgYjbn?o&Bp*#?;T$pa@|tA1VEf@U><^G3p%qx|@<( z*-i(+j3*Nj;uLurvkCN zt?b_HK?HU+dn_M;aUP{+I{7Ah}YVcH+Y)-D1X|*WsxPHlRAJ; z8kQD@EW+x#uqEyLbQ9rnv-I+)WOCFX|MQTlqVCZ+70IVl$^(*emne~nI8Ru-inmdN zT`dlUm#gx-pd;h)<{>JFOgGbrI-4oIj2X&@=oPAiCo7dX_+ig|H&!COT1?8(Uj@fc8RXQz>rMCafUAHv^-r6J=WOzKYz?DDj zU-9hW>E~qa@q-q0>l#C{Kt#WqqZ|rwZwh)zCKLE+z5RVr``0*R78BFGLev|zH*J<& zKwXIOC5Wa&qQ3p`T$Hr)u!v|qVIz~B+;0^#c<8>!4I2k2nWeYlZL>j!rZ^ z*x?y0vRVKQTICZ*j*RyvVQ=`EgAzFBn}O06pDquOy=jc`9%urklzqrfZ&vmdUE9_$ zSgEO-y7P_d4QgTGg}142DI2@PSvsZ*4kw9%b@My6!ZA*oy7J3kczdDQ;iD%qZt7=Ak49k*5sU{e!E9bP!-l={eq1 zJ%7*&Zgmz_U*Pk!HMUp~(Q{%qvQGI6^T;VRj%%{YE*hwM@IiZ5K9l6Kq|XdekVdLV zu0m~DHQO$+SZPh2zAyn8!w3D`Wy4cI)h_R*Gu;g^`kS@up@Dgbv@q#|9 z7ysHJD>=A%{hrjUIBCQHGZETgh4A~2Xf@{74xJOqdxMh(Zo*Y1@uFcp2lEmQQVOh) z@(MM`*u@njq0%3(b2?(i=2*)FycDpG;5;x{iD>g;V&jbIU7$tC3C}_pT06#_M3xrr{JbXWT?6dcRNIVoW_t2-N4MClfB!!K}vh`ujOy5 zyiTGK9wwXcKhYoIVrTAdZKdt$Ztr6IGin|rNIP_a@Z?X!zeo>CB+p8*%BPUxgv&HL zxC6{JoU|MZ?LNF}4J4L9_dK76bqVfhWKRf^;6!tXxlm|=11S*WNfII(jxkwCG{RmG zz6>|DvYXq4f?~^zEihBTK@*vmz=E%8{ouOn`_T{C(zQIe*3okD7>6%P?Q^}3LZpuE z>1(P{>NJJ8r{|{0afYL2(Jpw6vPVhVnz^t`Bv@DC^5=bS4$+i>;tO?ErgOCLas0D& z5OwBNfx@52z~|x4uaW-fGyiBEel?!I8;GB6=aWQeOecs){uJq2*4ICEG8{`*Tackq z_bZac#SH3fM$#$KcmKCk)*Y*>t|O}gS(jp^lr}iY9OKQ1;VYJ;cGY|SGo0up+A@*U)s>@rk_?D3Yr?heekbb+>i%4l04zt1J~^oNAKVxUxX`1KiD6vZuAXwza3{kJY|?&%o7NSnMIDFiIr@=tOD3m%NQ3x@Wv(yktDjc-Il-r8xNVsL(-gKyT;F z&CEUKhda7^J9_tG*k9a10Uz?o1)t-q4oc;m2vt(PaXo!h_>(q=H>a zVv9{n2xL(Y@%7Lm6oH@k_6^z44lpwjkxj|CkPcuhWV!TG%7Zo_J`nO{gl~w9OfWrS zFC|I=J%|Ev90vg{FQg61g};*C3?JRUOu(7WWb+;P^6$X^_;A6&3Sz104srG1wuHD_ z|FH@5U!4Iybxz51DqSF=_X{XDktwGF_Uy7UvmyPtROneO{+N9xq)rmxe3KjhPcD<^ z`((pS?f&1C>cq;p&H-Ovjo$0$3nlpY1-*2ZLL8#M!KoZzW>h_FS27Bq;mq19k1_6# z4`a6FXrzNOCl`vZ)+d+2kOsvF? z@nJbn1q_KhJ1tvG!HZ-fnt5S8e(5j>1Wi?rc;So8{;~gHS9PgEz5QJy6tG zYAeh*xHfN*QIn40Wt2Bcn+=eLxGVQob+#i6)vkR-yZ7Q>Jqu`=pc(-8s_$?q3-7O< zW$xyCUv|f&Q|eM@Fn0QSKFq0j2GjL8JEyd4Bq9+mxsj zM0W4P#%77O`sV41z)2YyQd#<<)CX30P8=o%#LM=6{+?XCcL|kYmccSk2=Bus#550y zD8VZLzIt?nsLYb*O40QZbx`1IBuLq_$%sZZcJlIm!^VV@K(|At^`U`Aq zSx|cnRc`Ka7VMnu`87F{8I%tc?GIBd8*if7YIhrGdB3e$d`iVl{E4%pjakt+hh5lZ zqLTtw->HHfhM#stQz8m7vGaftI82OHps4UzuS*EkTPC+sJi#f(t5h0Bwy01S;1ArP zEG#s&c+^D^tf@qT)zwDj*i$Du@#$g5`?hL6GAZAh#755*1lsZ@r6aU`Pt`AcSnrUA z^I@0aQwz^T+8~=Ya8}#pG`!^&2fJOlT{G*89HvfBW{;Rn; d)nCm2$kduDC~zMH0I=XcCb%0D{$P`U{{j5pv6cV; literal 0 HcmV?d00001 diff --git a/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Functions_Analysis_Template.xlsx b/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Functions_Analysis_Template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e4be65cb12b48275752b1c152ea5ab3d02ea386b GIT binary patch literal 8785 zcmeHscQ{;Y*Zwf0Oms%?g6Kwx5}jbw5S@tLyBRehNVMoBIuS"&;YL?_WAdKjWa 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 literal 0 HcmV?d00001 diff --git a/DataSetExplorer/Core/DataSets/IInstanceService.cs b/DataSetExplorer/Core/DataSets/IInstanceService.cs index ddd877ca..2fdc2b91 100644 --- a/DataSetExplorer/Core/DataSets/IInstanceService.cs +++ b/DataSetExplorer/Core/DataSets/IInstanceService.cs @@ -8,8 +8,10 @@ namespace DataSetExplorer.Core.DataSets { public interface IInstanceService { - Result>> GetAllByDatasetId(int datasetId); - Result>> GetAllByProjectId(int projectId); + Result>> GetInstancesWithIdentifiersByDatasetId(int datasetId); + Result>> GetInstancesWithIdentifiersByProjectId(int projectId); + Result>> GetInstancesByDatasetId(int datasetId); + Result>> GetInstancesByProjectId(int projectId); Result GetInstanceWithRelatedInstances(int id); Result GetInstanceWithAnnotations(int id); Result> GetInstancesForSmell(string codeSmellName); diff --git a/DataSetExplorer/Core/DataSets/InstanceService.cs b/DataSetExplorer/Core/DataSets/InstanceService.cs index 23051b4d..75dcac67 100644 --- a/DataSetExplorer/Core/DataSets/InstanceService.cs +++ b/DataSetExplorer/Core/DataSets/InstanceService.cs @@ -22,16 +22,30 @@ public InstanceService(IInstanceRepository instanceRepository, IDataSetCreationS _annotationRepository = annotationRepository; } - public Result>> GetAllByDatasetId(int datasetId) + public Result>> GetInstancesWithIdentifiersByDatasetId(int datasetId) { - var instances = _instanceRepository.GetAllByDatasetId(datasetId); + var instances = _instanceRepository.GetInstancesWithIdentifiersByDatasetId(datasetId); if (instances == default) return Result.Fail($"Dataset with id: {datasetId} does not exist."); return Result.Ok(instances); } - public Result>> GetAllByProjectId(int projectId) + public Result>> GetInstancesWithIdentifiersByProjectId(int projectId) { - var instances = _instanceRepository.GetAllByProjectId(projectId); + var instances = _instanceRepository.GetInstancesWithIdentifiersByProjectId(projectId); + if (instances == default) return Result.Fail($"Project with id: {projectId} does not exist."); + return Result.Ok(instances); + } + + public Result>> GetInstancesByDatasetId(int datasetId) + { + var instances = _instanceRepository.GetInstancesByDatasetId(datasetId); + if (instances == default) return Result.Fail($"Dataset with id: {datasetId} does not exist."); + return Result.Ok(instances); + } + + public Result>> GetInstancesByProjectId(int projectId) + { + var instances = _instanceRepository.GetInstancesByProjectId(projectId); if (instances == default) return Result.Fail($"Project with id: {projectId} does not exist."); return Result.Ok(instances); } diff --git a/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs b/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs index 644f096d..a26d5626 100644 --- a/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/IInstanceRepository.cs @@ -8,8 +8,10 @@ namespace DataSetExplorer.Core.DataSets.Repository public interface IInstanceRepository { Instance Get(int id); - Dictionary> GetAllByDatasetId(int datasetId); - Dictionary> GetAllByProjectId(int projectId); + Dictionary> GetInstancesWithIdentifiersByDatasetId(int datasetId); + Dictionary> GetInstancesWithIdentifiersByProjectId(int projectId); + Dictionary> GetInstancesByDatasetId(int datasetId); + Dictionary> GetInstancesByProjectId(int projectId); InstanceDTO GetInstanceWithRelatedInstances(int id); IEnumerable GetInstancesAnnotatedByAnnotator(int projectId, int? annotatorId); IEnumerable GetAnnotatedInstances(int projectId); diff --git a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs index 7fe397dd..8ddc7b9c 100644 --- a/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs +++ b/DataSetExplorer/Core/DataSets/Repository/InstanceDatabaseRepository.cs @@ -22,7 +22,7 @@ public Instance Get(int id) return _dbContext.Instances.Include(i => i.Annotations).FirstOrDefault(i => i.Id == id); } - public Dictionary> GetAllByDatasetId(int datasetId) + public Dictionary> GetInstancesWithIdentifiersByDatasetId(int datasetId) { var instances = new Dictionary>(); var dataset = _dbContext.DataSets @@ -39,7 +39,7 @@ public Dictionary> GetAllByDatasetId(int datasetId) return instances; } - public Dictionary> GetAllByProjectId(int projectId) + public Dictionary> GetInstancesWithIdentifiersByProjectId(int projectId) { var instances = new Dictionary>(); var project = _dbContext.DataSetProjects @@ -53,6 +53,32 @@ public Dictionary> GetAllByProjectId(int projectId) return instances; } + public Dictionary> GetInstancesByDatasetId(int datasetId) + { + var instances = new Dictionary>(); + var dataset = _dbContext.DataSets + .Include(d => d.Projects).ThenInclude(p => p.CandidateInstances).ThenInclude(c => c.Instances) + .FirstOrDefault(d => d.Id == datasetId); + if (dataset == default) return null; + + foreach (var project in dataset.Projects) + instances.Add(project.Name, project.CandidateInstances.SelectMany(c => c.Instances).ToList()); + + return instances; + } + + public Dictionary> GetInstancesByProjectId(int projectId) + { + var instances = new Dictionary>(); + var project = _dbContext.DataSetProjects + .Include(p => p.CandidateInstances).ThenInclude(c => c.Instances) + .FirstOrDefault(p => p.Id == projectId); + if (project == default) return null; + + instances.Add(project.Name, project.CandidateInstances.SelectMany(c => c.Instances).ToList()); + return instances; + } + public InstanceDTO GetInstanceWithRelatedInstances(int id) { return new InstanceDTO(_dbContext.Instances From 35773708331165e19c1bdba0d10c1c971bdf5f74 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Sat, 25 Feb 2023 20:56:24 +0100 Subject: [PATCH 38/46] feat[DE]: Add conditional formatting --- .../CleanCodeAnalysisService.cs | 77 ++++++++++++------ .../Clean_Classes_Analysis_Template.xlsx | Bin 8783 -> 8826 bytes .../Clean_Functions_Analysis_Template.xlsx | Bin 8785 -> 8827 bytes 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index 68c6f322..abfa813a 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -5,6 +5,7 @@ using FluentResults; using OfficeOpenXml; using System.Collections.Generic; +using System.Drawing; using System.IO; namespace DataSetExplorer.Core.CleanCodeAnalysis @@ -107,18 +108,20 @@ private void PopulateCleanFunctionsTemplate(List instances) instances.RemoveAll(i => i.Type.Equals(SnippetType.Class)); for (var i = 0; i < instances.Count; i++) { - var row = 3 + i; - _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; - _sheet.Cells[row, 2].Value = instances[i].Link; + var row = 5 + i; + PopulateInstanceInfo(row, instances[i]); - _sheet.Cells[2, 3].Value = CaDETMetric.MLOC; - _sheet.Cells[row, 3].Value = instances[i].MetricFeatures[CaDETMetric.MLOC]; + PopulateMetrics(row, 3, CaDETMetric.MLOC, 15, 25, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 3, instances.Count + 4, 3), _sheet.Cells[3, 3].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 3, instances.Count + 4, 3), _sheet.Cells[2, 3].Value, Color.Yellow); - _sheet.Cells[2, 4].Value = CaDETMetric.CYCLO_SWITCH; - _sheet.Cells[row, 4].Value = instances[i].MetricFeatures[CaDETMetric.CYCLO_SWITCH]; + PopulateMetrics(row, 4, CaDETMetric.CYCLO_SWITCH, 6, 12, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 4, instances.Count + 4, 4), _sheet.Cells[3, 4].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 4, instances.Count + 4, 4), _sheet.Cells[2, 4].Value, Color.Yellow); - _sheet.Cells[2, 5].Value = CaDETMetric.MMNB; - _sheet.Cells[row, 5].Value = instances[i].MetricFeatures[CaDETMetric.MMNB]; + PopulateMetrics(row, 5, CaDETMetric.MMNB, 4, 6, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 5, instances.Count + 4, 5), _sheet.Cells[3, 5].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 5, instances.Count + 4, 5), _sheet.Cells[2, 5].Value, Color.Yellow); } } @@ -141,30 +144,56 @@ private void PopulateCleanClassesTemplate(List instances) instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); for (var i = 0; i < instances.Count; i++) { - var row = 3 + i; - _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; - _sheet.Cells[row, 2].Value = instances[i].Link; + var row = 5 + i; + PopulateInstanceInfo(row, instances[i]); - _sheet.Cells[2, 3].Value = CaDETMetric.CLOC; - _sheet.Cells[row, 3].Value = instances[i].MetricFeatures[CaDETMetric.CLOC]; + PopulateMetrics(row, 3, CaDETMetric.CLOC, 80, 150, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 3, instances.Count + 4, 3), _sheet.Cells[3, 3].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 3, instances.Count + 4, 3), _sheet.Cells[2, 3].Value, Color.Yellow); - _sheet.Cells[2, 4].Value = CaDETMetric.WMC; - _sheet.Cells[row, 4].Value = instances[i].MetricFeatures[CaDETMetric.WMC]; + PopulateMetrics(row, 4, CaDETMetric.WMC, 15, 25, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 4, instances.Count + 4, 4), _sheet.Cells[3, 4].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 4, instances.Count + 4, 4), _sheet.Cells[2, 4].Value, Color.Yellow); - _sheet.Cells[2, 5].Value = CaDETMetric.NAD; - _sheet.Cells[row, 5].Value = instances[i].MetricFeatures[CaDETMetric.NAD]; + PopulateMetrics(row, 5, CaDETMetric.NAD, 10, 15, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 5, instances.Count + 4, 5), _sheet.Cells[3, 5].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 5, instances.Count + 4, 5), _sheet.Cells[2, 5].Value, Color.Yellow); - _sheet.Cells[2, 6].Value = CaDETMetric.NMD; - _sheet.Cells[row, 6].Value = instances[i].MetricFeatures[CaDETMetric.NMD]; + PopulateMetrics(row, 6, CaDETMetric.NMD, 12, 16, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 6, instances.Count + 4, 6), _sheet.Cells[3, 6].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 6, instances.Count + 4, 6), _sheet.Cells[2, 6].Value, Color.Yellow); - _sheet.Cells[2, 7].Value = CaDETMetric.CBO; - _sheet.Cells[row, 7].Value = instances[i].MetricFeatures[CaDETMetric.CBO]; + PopulateMetrics(row, 7, CaDETMetric.CBO, 8, 12, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 7, instances.Count + 4, 7), _sheet.Cells[3, 7].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 7, instances.Count + 4, 7), _sheet.Cells[2, 7].Value, Color.Yellow); - _sheet.Cells[2, 8].Value = CaDETMetric.DIT; - _sheet.Cells[row, 8].Value = instances[i].MetricFeatures[CaDETMetric.DIT]; + PopulateMetrics(row, 8, CaDETMetric.DIT, 3, 5, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 8, instances.Count + 4, 8), _sheet.Cells[3, 8].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 8, instances.Count + 4, 8), _sheet.Cells[2, 8].Value, Color.Yellow); } } + private void PopulateInstanceInfo(int row, Instance instance) + { + _sheet.Cells[row, 1].Value = instance.CodeSnippetId; + _sheet.Cells[row, 2].Value = instance.Link; + } + + private void PopulateMetrics(int row, int column, CaDETMetric metric, int suspiciousValue, int criticalValue, Instance instance) + { + _sheet.Cells[2, column].Value = suspiciousValue; + _sheet.Cells[3, column].Value = criticalValue; + _sheet.Cells[4, column].Value = metric; + _sheet.Cells[row, column].Value = instance.MetricFeatures[metric]; + } + + private void SetConditionalFormatting(ExcelAddress excelAddress, object formula, Color color) + { + var cf = _sheet.ConditionalFormatting.AddGreaterThan(excelAddress); + cf.Formula = formula.ToString(); + cf.Style.Fill.BackgroundColor.Color = color; + } + private void Serialize(string fileName) { var filePath = _exportPath + fileName + ".xlsx"; diff --git a/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Classes_Analysis_Template.xlsx b/DataSetExplorer/Core/DataSetSerializer/Template/Clean_Classes_Analysis_Template.xlsx index a088371370b241916b012c88e6d0bab60d8a5c3a..c9d9e282129b88fbee5b0c2fd8b219b19c719b0f 100644 GIT binary patch delta 2469 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 delta 2391 zcmV-d38?n_MA1aB+6DyZ3_(ki-Uc0i-%r~x5PqMu|H1NmNSu}wB2v^}XqC39S{b}l zLayUB7LJ`c4lP6c?>i?=q4b48l-RK^`TX78cXx5Q%_Vx^rW9Hwn4AO{am92h)H=bx zudlo_j7m#YN~Kmj!H>Mem;J9_E;icSFSWi$0HDeQXVw<6@0Tp&IW13g!4+74R@&s$ z!qTk$vM`*cWyZP9r5^@CEt8%Vv17f(O7U-9mD9RQsXYYZ_ zskyHTkLkPsh^3IiKGvWZl^-mAY2ajtW5MlR?!|SdI2NBr_l&VtJX>k!TTWE>7HAN z`xh%A`As8TM2q4l&0VG>Mv|6xk_yYy1ovR6H~e73RK>6o60Bhqgc0`pdpXYxEFkv- zX}M9<@{v{+q_(5}Sy|QCqfCQ{(J%g|5{5(VfP}yu7%7YCvYb(yp~}dA1drndV>IP< zQGmu>F)hZ_(mA)2Z6UScW-)@X-JEkHs1$!;`<0^VkRbcPrYuhGaQUN9yuR%z3%y0 z;GGY<18+E(1YtNC3fMZEuB2^(Mg{37|(l9xgYv@m8cZ1Ce#YQ>dk8?;98E3>cFR z>A3`e>dM~^I+EiE<%RJ zmSpW*J4+JF*Pxh&gj%1cHWUJ=E)vc2^bB8ESV4QX)Sl$+#1baEr%EveeFL<@du4a_Fj!{s~Rc z5JGuvp7YPcJxNb`O?{R>LIVDIpP-jDCi^^>>u}$&Ru$B&lkQT>@1k;R%&CZrf)?o{ zJ0;`po!)$czIgOBKEn;(Sya7uV&DAW&#K)OSdKRi3lSp$f9l{`VgYfDl<=<(yfJLs zm#z;up)pO*^8@QBWI*>gEMvf--3&r$oab4ZQ!ljF^H(I+J0Q`H$Rf_@^gjWM0fu&j z7sp3yoHheA zrU~O%3LWrG;72AD9H^6If=p5n4G(6R2LapVAQ7G=Dxm)4SI{t%=}eB^^|F?3yJj1% z|Lj=>P&gHNFJ7;OW-YV};dKe}{hlY2K@S&y-7O-PPGLb8d+?$sk7Ju@2WKa&Da#HY>F@2HWxpkq9 z5#Ij=R(=P|l>Z2p>_`t*MjvMg4FRaSPRZV0E%ITDw3c)e! zDvGwb_&$*?338qk)n49XFtMmuulYjlbL7$uTg>Cd8_VlF5o!CAkqH&EM-cx83fHT( zKDYn?0O|mfP!}41T#i9%!!Qs<_l4X+%s!FZKq*C%7Y>C&x@vL&VNYyPYout#rM-O> zLI`yE-s8hJ?N6N5Hx>?wEIe)+P)L0m0*w}qhqv_$C>BqHpA(^lUu0cKFJs#{_U zlSqEmn)?Z(=S|8;wVYCkUMiMRb1vuyo)9I@`l)H2b@YKVK=o-Mv9JZTP&hBx-Pjop z&WPIw`Z8La(HFkDE)A$YDddcz-gp1=2TBP&-?gq^-5&sxp#v1NJs1N51zOpvq$9IM z8YcmNOT;h~h4+I0p=95t4;(bK9Z;E-1Hx1kcOkjc2{sRsXs7?)v{UQ&ScY@%ch5a3 z*GJh!A7Gu(szOyb$xkJGDDcQ@MyIG>jk(d zkd!0LROsNnAs9P$07+dE94d%=Z6)>LX%mI*@4%#-Ii>J}2{+Ag&)J-v#KnDdVlno8pY+8PBjnHU z%l2V6of-=@cEteIV?P~rejBRX3*fgyy%SO^TH?P-$=Q^R$k`o*b>tN8OL{Ku?wbu8 zs`E52;xv!*qRCdIxFJ{RYl(jY>S@i-52`{ zK>-GnZ6Qzr2$Q}cIvZNqs-z Date: Sat, 25 Mar 2023 10:23:58 +0100 Subject: [PATCH 39/46] Remove contructors from clean names analysis --- .../CleanCodeAnalysisService.cs | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index abfa813a..73bcea0a 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -1,4 +1,5 @@ using CodeModel.CaDETModel.CodeItems; +using DataSetExplorer.Core.CleanCodeAnalysis.Model; using DataSetExplorer.Core.DataSets; using DataSetExplorer.Core.DataSets.Model; using DataSetExplorer.UI.Controllers.Dataset.DTOs; @@ -64,15 +65,40 @@ private void ExportCleanNamesAnalysis(Dictionary> instanc ExcelPackage.LicenseContext = LicenseContext.NonCommercial; _excelFile = new ExcelPackage(new FileInfo(_cleanNamesAnalysisTemplatePath)); _sheet = _excelFile.Workbook.Worksheets[0]; + FilterInstances(instances[projectName]); PopulateCleanNamesTemplate(instances[projectName]); Serialize(projectName + "_CleanNames"); } } + private void FilterInstances(List instances) + { + RemoveFunctions(instances); + RemoveConstructors(instances); + } + + private void RemoveFunctions(List instances) + { + instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); + } + + private void RemoveConstructors(List instances) + { + foreach(var instance in instances) + { + var classIdentifier = instance.Identifiers.Find(i => i.Type.Equals(IdentifierType.Class)); + instance.Identifiers.RemoveAll(i => IsConstructor(i, classIdentifier)); + } + } + + private static bool IsConstructor(Identifier i, Identifier classIdentifier) + { + return i.Name.Equals(classIdentifier.Name) && i.Type.Equals(IdentifierType.Member); + } + private void PopulateCleanNamesTemplate(List instances) { var identifierCount = 0; - instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); for (var i = 0; i < instances.Count; i++) { var row = 3 + i + identifierCount; From 663d4fe9fca54fb152d6ff3adec7dd0505a94539 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Sat, 25 Mar 2023 16:18:23 +0100 Subject: [PATCH 40/46] Replace members with properties and methods (for clean names analysis) --- .../CleanCodeAnalysisService.cs | 16 +--------------- .../Core/CleanCodeAnalysis/Model/Identifier.cs | 5 +++-- .../DataSets/CaDETToDataSetProjectBuilder.cs | 9 ++++++++- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index 73bcea0a..30875477 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -74,7 +74,7 @@ private void ExportCleanNamesAnalysis(Dictionary> instanc private void FilterInstances(List instances) { RemoveFunctions(instances); - RemoveConstructors(instances); + } private void RemoveFunctions(List instances) @@ -82,20 +82,6 @@ private void RemoveFunctions(List instances) instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); } - private void RemoveConstructors(List instances) - { - foreach(var instance in instances) - { - var classIdentifier = instance.Identifiers.Find(i => i.Type.Equals(IdentifierType.Class)); - instance.Identifiers.RemoveAll(i => IsConstructor(i, classIdentifier)); - } - } - - private static bool IsConstructor(Identifier i, Identifier classIdentifier) - { - return i.Name.Equals(classIdentifier.Name) && i.Type.Equals(IdentifierType.Member); - } - private void PopulateCleanNamesTemplate(List instances) { var identifierCount = 0; diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs b/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs index eb12e68f..3ff252bf 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/Model/Identifier.cs @@ -20,8 +20,9 @@ public enum IdentifierType { Class, Field, - Member, Variable, - Parameter + Parameter, + Property, + Method } } \ No newline at end of file diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index 65e02f99..d9adb023 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -218,11 +218,18 @@ private List CaDETToDataSetProjectClasses(List cadetClasse private List FindAllIdentifiers(CaDETClass cadetClass) { var identifiers = new List(); + identifiers.Add(new Identifier(cadetClass.Name, IdentifierType.Class)); cadetClass.Fields.ForEach(field => identifiers.Add(new Identifier(field.Name, IdentifierType.Field))); - cadetClass.Members.ForEach(member => identifiers.Add(new Identifier(member.Name, IdentifierType.Member))); cadetClass.Members.ForEach(member => member.Variables.ForEach(variable => identifiers.Add(new Identifier(variable.Name, IdentifierType.Variable)))); cadetClass.Members.ForEach(member => member.Params.ForEach(param => identifiers.Add(new Identifier(param.Name, IdentifierType.Parameter)))); + + var properties = cadetClass.Members.FindAll(member => member.Type.Equals(CaDETMemberType.Property)); + properties.ForEach(property => identifiers.Add(new Identifier(property.Name, IdentifierType.Property))); + + var methods = cadetClass.Members.FindAll(member => member.Type.Equals(CaDETMemberType.Method)); + methods.ForEach(method => identifiers.Add(new Identifier(method.Name, IdentifierType.Method))); + return identifiers; } From ed164d26a6cf070e13b323a5eafc61a717c83092 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Sat, 25 Mar 2023 17:42:37 +0100 Subject: [PATCH 41/46] Group same identifiers and count occurrence (for clean names analysis) --- .../CleanCodeAnalysisService.cs | 76 +++++++++++++++---- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index 30875477..f9d8c10f 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; namespace DataSetExplorer.Core.CleanCodeAnalysis { @@ -56,25 +57,48 @@ public Result ExportProjectAnalysis(int projectId, CleanCodeAnalysisDTO return Result.Ok(analysisOptions.ExportPath); } - private void ExportCleanNamesAnalysis(Dictionary> instances) + private void ExportCleanNamesAnalysis(Dictionary> projectsAndInstances) { - if (instances == default) return; + if (projectsAndInstances == default) return; - foreach (var projectName in instances.Keys) + foreach (var projectAndInstances in projectsAndInstances) { ExcelPackage.LicenseContext = LicenseContext.NonCommercial; _excelFile = new ExcelPackage(new FileInfo(_cleanNamesAnalysisTemplatePath)); _sheet = _excelFile.Workbook.Worksheets[0]; - FilterInstances(instances[projectName]); - PopulateCleanNamesTemplate(instances[projectName]); - Serialize(projectName + "_CleanNames"); + + FilterInstances(projectAndInstances.Value); + var instancesAndIdentifiers = GetInstancesAndIdentifiers(projectAndInstances.Value); + PopulateCleanNamesTemplate(projectAndInstances.Value, instancesAndIdentifiers); + Serialize(projectAndInstances.Key + "_CleanNames"); } } private void FilterInstances(List instances) { RemoveFunctions(instances); - + } + + private Dictionary>> GetInstancesAndIdentifiers(List instances) + { + Dictionary>> instanceIdentifiers = new Dictionary>>(); + foreach (var instance in instances) + { + Dictionary> identifierTypes = new Dictionary>(); + instance.Identifiers.ForEach(ident => AddTypeForIdentifier(ident, identifierTypes)); + instanceIdentifiers.Add(instance.Id, identifierTypes); + } + return instanceIdentifiers; + } + + private void AddTypeForIdentifier(Identifier identifier, Dictionary> identifierTypes) + { + if (identifierTypes.ContainsKey(identifier.Name)) identifierTypes[identifier.Name].Add(identifier.Type); + else + { + identifierTypes.Add(identifier.Name, new List()); + identifierTypes[identifier.Name].Add(identifier.Type); + } } private void RemoveFunctions(List instances) @@ -82,7 +106,7 @@ private void RemoveFunctions(List instances) instances.RemoveAll(i => i.Type.Equals(SnippetType.Function)); } - private void PopulateCleanNamesTemplate(List instances) + private void PopulateCleanNamesTemplate(List instances, Dictionary>> instancesAndIdentifiers) { var identifierCount = 0; for (var i = 0; i < instances.Count; i++) @@ -91,16 +115,38 @@ private void PopulateCleanNamesTemplate(List instances) _sheet.Cells[row, 1].Value = instances[i].CodeSnippetId; _sheet.Cells[row, 2].Value = instances[i].Link; - instances[i].Identifiers.Sort((x, y) => x.Type.CompareTo(y.Type)); - for (var j = 0; j < instances[i].Identifiers.Count; j++) - { - _sheet.Cells[row + j, 3].Value = instances[i].Identifiers[j].Name; - _sheet.Cells[row + j, 4].Value = instances[i].Identifiers[j].Type.ToString(); - } - identifierCount += instances[i].Identifiers.Count; + var identifiersAndTypes = instancesAndIdentifiers[instances[i].Id]; + PopulateIdentifiers(row, identifiersAndTypes); + identifierCount += identifiersAndTypes.Count; } } + private void PopulateIdentifiers(int row, Dictionary> identifiersAndTypes) + { + var j = 0; + foreach (var identifierAndType in identifiersAndTypes) + { + _sheet.Cells[row + j, 3].Value = identifierAndType.Key; + PopulateIdentifierTypes(row, j, identifierAndType.Value); + j++; + } + } + + private void PopulateIdentifierTypes(int row, int j, List types) + { + Dictionary typeOccurrence = CountTypeOccurrence(types); + _sheet.Cells[row + j, 4].Value = ""; + foreach (var occurrence in typeOccurrence) + { + _sheet.Cells[row + j, 4].Value += occurrence.Value + "x " + occurrence.Key + "; "; + } + } + + private static Dictionary CountTypeOccurrence(List types) + { + return types.GroupBy(t => t.ToString()).ToDictionary(t => t.Key, t => t.Count()); + } + private void ExportCleanFunctionsAnalysis(Dictionary> instances) { if (instances == default) return; From f692235cbcce6deb6e3fcb0bc158aaa97ab99ecc Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Sat, 25 Mar 2023 18:14:58 +0100 Subject: [PATCH 42/46] Analyze params and vars from methods instead of members (clean names analysis) --- .../CleanCodeAnalysis/CleanCodeAnalysisService.cs | 11 +++++++++-- .../Core/DataSets/CaDETToDataSetProjectBuilder.cs | 9 ++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index f9d8c10f..4d5f9487 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -116,16 +116,23 @@ private void PopulateCleanNamesTemplate(List instances, Dictionary i.Type.Equals(IdentifierType.Class)); + PopulateIdentifiers(row, mainIdentifier, identifiersAndTypes); identifierCount += identifiersAndTypes.Count; } } - private void PopulateIdentifiers(int row, Dictionary> identifiersAndTypes) + private void PopulateIdentifiers(int row, Identifier mainIdentifier, Dictionary> identifiersAndTypes) { var j = 0; + + _sheet.Cells[row + j, 3].Value = mainIdentifier.Name; + _sheet.Cells[row + j, 4].Value = mainIdentifier.Type.ToString(); + j++; + foreach (var identifierAndType in identifiersAndTypes) { + if (identifierAndType.Key.Equals(mainIdentifier.Name)) continue; _sheet.Cells[row + j, 3].Value = identifierAndType.Key; PopulateIdentifierTypes(row, j, identifierAndType.Value); j++; diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index d9adb023..ba6f3e45 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -221,15 +221,18 @@ private List FindAllIdentifiers(CaDETClass cadetClass) identifiers.Add(new Identifier(cadetClass.Name, IdentifierType.Class)); cadetClass.Fields.ForEach(field => identifiers.Add(new Identifier(field.Name, IdentifierType.Field))); - cadetClass.Members.ForEach(member => member.Variables.ForEach(variable => identifiers.Add(new Identifier(variable.Name, IdentifierType.Variable)))); - cadetClass.Members.ForEach(member => member.Params.ForEach(param => identifiers.Add(new Identifier(param.Name, IdentifierType.Parameter)))); var properties = cadetClass.Members.FindAll(member => member.Type.Equals(CaDETMemberType.Property)); properties.ForEach(property => identifiers.Add(new Identifier(property.Name, IdentifierType.Property))); var methods = cadetClass.Members.FindAll(member => member.Type.Equals(CaDETMemberType.Method)); - methods.ForEach(method => identifiers.Add(new Identifier(method.Name, IdentifierType.Method))); + foreach (var method in methods) + { + identifiers.Add(new Identifier(method.Name, IdentifierType.Method)); + method.Params.ForEach(param => identifiers.Add(new Identifier(param.Name, IdentifierType.Parameter))); + method.Variables.ForEach(variable => identifiers.Add(new Identifier(variable.Name, IdentifierType.Variable))); + } return identifiers; } From 89a730f83af17dae0dca17ecd8b0a7acf236cd40 Mon Sep 17 00:00:00 2001 From: Simona Prokic <167simonap@gmail.com> Date: Sat, 25 Mar 2023 19:59:40 +0100 Subject: [PATCH 43/46] Add additional metrics and remove constructors (clean functions analysis) --- .../CleanCodeAnalysisService.cs | 45 ++++++++++++++----- .../DataSets/CaDETToDataSetProjectBuilder.cs | 1 - 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs index 4d5f9487..044312cf 100644 --- a/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs +++ b/DataSetExplorer/Core/CleanCodeAnalysis/CleanCodeAnalysisService.cs @@ -67,18 +67,13 @@ private void ExportCleanNamesAnalysis(Dictionary> project _excelFile = new ExcelPackage(new FileInfo(_cleanNamesAnalysisTemplatePath)); _sheet = _excelFile.Workbook.Worksheets[0]; - FilterInstances(projectAndInstances.Value); + RemoveFunctions(projectAndInstances.Value); var instancesAndIdentifiers = GetInstancesAndIdentifiers(projectAndInstances.Value); PopulateCleanNamesTemplate(projectAndInstances.Value, instancesAndIdentifiers); Serialize(projectAndInstances.Key + "_CleanNames"); } } - private void FilterInstances(List instances) - { - RemoveFunctions(instances); - } - private Dictionary>> GetInstancesAndIdentifiers(List instances) { Dictionary>> instanceIdentifiers = new Dictionary>>(); @@ -170,24 +165,52 @@ private void ExportCleanFunctionsAnalysis(Dictionary> ins private void PopulateCleanFunctionsTemplate(List instances) { - instances.RemoveAll(i => i.Type.Equals(SnippetType.Class)); + instances = FilterInstances(instances); for (var i = 0; i < instances.Count; i++) { var row = 5 + i; PopulateInstanceInfo(row, instances[i]); - PopulateMetrics(row, 3, CaDETMetric.MLOC, 15, 25, instances[i]); + PopulateMetrics(row, 3, CaDETMetric.MELOC, 15, 25, instances[i]); SetConditionalFormatting(new ExcelAddress(5, 3, instances.Count + 4, 3), _sheet.Cells[3, 3].Value, Color.Red); SetConditionalFormatting(new ExcelAddress(5, 3, instances.Count + 4, 3), _sheet.Cells[2, 3].Value, Color.Yellow); - PopulateMetrics(row, 4, CaDETMetric.CYCLO_SWITCH, 6, 12, instances[i]); + PopulateMetrics(row, 4, CaDETMetric.CYCLO_SWITCH, 5, 12, instances[i]); SetConditionalFormatting(new ExcelAddress(5, 4, instances.Count + 4, 4), _sheet.Cells[3, 4].Value, Color.Red); SetConditionalFormatting(new ExcelAddress(5, 4, instances.Count + 4, 4), _sheet.Cells[2, 4].Value, Color.Yellow); - - PopulateMetrics(row, 5, CaDETMetric.MMNB, 4, 6, instances[i]); + + PopulateMetrics(row, 5, CaDETMetric.MNOL, 2, 4, instances[i]); SetConditionalFormatting(new ExcelAddress(5, 5, instances.Count + 4, 5), _sheet.Cells[3, 5].Value, Color.Red); SetConditionalFormatting(new ExcelAddress(5, 5, instances.Count + 4, 5), _sheet.Cells[2, 5].Value, Color.Yellow); + + PopulateMetrics(row, 6, CaDETMetric.NOP, 3, 6, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 6, instances.Count + 4, 6), _sheet.Cells[3, 6].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 6, instances.Count + 4, 6), _sheet.Cells[2, 6].Value, Color.Yellow); + + PopulateMetrics(row, 7, CaDETMetric.MNOC, 2, 4, instances[i]); + SetConditionalFormatting(new ExcelAddress(5, 7, instances.Count + 4, 7), _sheet.Cells[3, 7].Value, Color.Red); + SetConditionalFormatting(new ExcelAddress(5, 7, instances.Count + 4, 7), _sheet.Cells[2, 7].Value, Color.Yellow); + } + } + + private List FilterInstances(List instances) + { + instances.RemoveAll(i => i.Type.Equals(SnippetType.Class)); + return RemoveConstructors(instances); + } + + private List RemoveConstructors(List instances) + { + var instancesWithoutConstructors = new List(); + foreach (Instance instance in instances) + { + var snippetPartsWithoutParams = instance.CodeSnippetId.Split("(")[0]; + var snippetParts = snippetPartsWithoutParams.Split("."); + var methodName = snippetParts.Last(); + var className = snippetParts[snippetParts.Length - 2]; + if (!methodName.Equals(className)) instancesWithoutConstructors.Add(instance); } + return instancesWithoutConstructors; } private void ExportCleanClassesAnalysis(Dictionary> instances) diff --git a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs index ba6f3e45..f12a07f2 100644 --- a/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs +++ b/DataSetExplorer/Core/DataSets/CaDETToDataSetProjectBuilder.cs @@ -28,7 +28,6 @@ internal class CaDETToDataSetProjectBuilder private readonly List _codeSmells; private readonly InstanceFilter _instanceFilter; private readonly Dictionary> _classCouplings = new Dictionary>(); - private readonly List _cleanClassNaming = new List(); internal CaDETToDataSetProjectBuilder(InstanceFilter instanceFilter, string projectAndCommitUrl, string projectName, string projectPath, List ignoredFolders, LanguageEnum language, bool includeClasses, bool includeMembers, List codeSmells) { From c9408de331b77e5cbfd2cb9a1f23af3605dc38c5 Mon Sep 17 00:00:00 2001 From: Nikola Luburic Date: Wed, 31 Jan 2024 13:26:13 +0100 Subject: [PATCH 44/46] feat: Enables CSharpCodeParser to process partial classes. --- CodeModel/CodeModel.csproj | 1 + CodeModel/CodeModelFactory.cs | 6 ++++-- CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs | 14 +++++++++++--- CodeModel/CodeParsers/ICodeParser.cs | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CodeModel/CodeModel.csproj b/CodeModel/CodeModel.csproj index 0f29c52a..27509463 100644 --- a/CodeModel/CodeModel.csproj +++ b/CodeModel/CodeModel.csproj @@ -13,6 +13,7 @@ https://github.com/Clean-CaDET/platform/tree/master/CodeModel GPL-3.0-or-later true + 1.0.2 diff --git a/CodeModel/CodeModelFactory.cs b/CodeModel/CodeModelFactory.cs index 3f19f246..e3e93b41 100644 --- a/CodeModel/CodeModelFactory.cs +++ b/CodeModel/CodeModelFactory.cs @@ -12,16 +12,18 @@ namespace CodeModel public class CodeModelFactory { private readonly LanguageEnum _language; + private readonly bool _includePartial; - public CodeModelFactory(LanguageEnum language = LanguageEnum.CSharp) + public CodeModelFactory(LanguageEnum language = LanguageEnum.CSharp, bool includePartial = false) { _language = language; + _includePartial = includePartial; } public CaDETProject CreateProject(IEnumerable multipleClassSourceCode) { ICodeParser codeParser = SimpleParserFactory.CreateParser(_language); - return codeParser.Parse(multipleClassSourceCode); + return _includePartial ? codeParser.ParseWithPartial(multipleClassSourceCode) : codeParser.Parse(multipleClassSourceCode); } public CaDETProject CreateProject(string sourceCodeLocation, List ignoredFolders) diff --git a/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs b/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs index 06e736e1..e4aaa8cf 100644 --- a/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs +++ b/CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs @@ -27,12 +27,20 @@ public CSharpCodeParser() public CaDETProject Parse(IEnumerable sourceCode) { var syntaxErrors = LoadSyntaxTrees(sourceCode); - var parsedClasses = ParseClasses(); + var parsedClasses = ParseClasses(false); ValidateUniqueFullNameForNonPartial(parsedClasses); parsedClasses = ConnectCaDETGraph(parsedClasses); return new CaDETProject(LanguageEnum.CSharp, CalculateMetrics(parsedClasses), syntaxErrors); } + public CaDETProject ParseWithPartial(IEnumerable sourceCode) + { + var syntaxErrors = LoadSyntaxTrees(sourceCode); + var parsedClasses = ParseClasses(true); + parsedClasses = ConnectCaDETGraph(parsedClasses); + return new CaDETProject(LanguageEnum.CSharp, CalculateMetrics(parsedClasses), syntaxErrors); + } + private List LoadSyntaxTrees(IEnumerable sourceCode) { var syntaxErrors = new List(); @@ -47,7 +55,7 @@ private List LoadSyntaxTrees(IEnumerable sourceCode) return syntaxErrors; } - private List ParseClasses() + private List ParseClasses(bool includePartial) { List builtClasses = new List(); foreach (var ast in _compilation.SyntaxTrees) @@ -59,7 +67,7 @@ private List ParseClasses() { try { - ValidateNoPartialModifier(node); + if(!includePartial) ValidateNoPartialModifier(node); ValidateNoStructParent(node); builtClasses.Add(ParseClass(semanticModel, node)); } diff --git a/CodeModel/CodeParsers/ICodeParser.cs b/CodeModel/CodeParsers/ICodeParser.cs index 092b2a43..d2d35702 100644 --- a/CodeModel/CodeParsers/ICodeParser.cs +++ b/CodeModel/CodeParsers/ICodeParser.cs @@ -6,5 +6,6 @@ namespace CodeModel.CodeParsers public interface ICodeParser { CaDETProject Parse(IEnumerable sourceCode); + CaDETProject ParseWithPartial(IEnumerable sourceCode); } } \ No newline at end of file From 8c788fa172298af9672a1750d55e0f8d27968967 Mon Sep 17 00:00:00 2001 From: Nikola Luburic Date: Wed, 31 Jan 2024 13:28:35 +0100 Subject: [PATCH 45/46] fix: Minor tweak to CodeModelFactory constructor. --- CodeModel/CodeModelCache.cs | 2 +- CodeModel/CodeModelFactory.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CodeModel/CodeModelCache.cs b/CodeModel/CodeModelCache.cs index 0a8ff77a..c36a6e59 100644 --- a/CodeModel/CodeModelCache.cs +++ b/CodeModel/CodeModelCache.cs @@ -17,7 +17,7 @@ public CaDETProject GetOrCreate(string repoAndCommitUrl, string repoFolder, Lang { if (_cache.TryGetValue(repoAndCommitUrl, out CaDETProject cacheEntry)) return cacheEntry; - cacheEntry = new CodeModelFactory(language).CreateProjectWithCodeFileLinks(repoFolder); + cacheEntry = new CodeModelFactory(false, language).CreateProjectWithCodeFileLinks(repoFolder); var cacheEntryOptions = new MemoryCacheEntryOptions { diff --git a/CodeModel/CodeModelFactory.cs b/CodeModel/CodeModelFactory.cs index e3e93b41..325394b9 100644 --- a/CodeModel/CodeModelFactory.cs +++ b/CodeModel/CodeModelFactory.cs @@ -14,10 +14,10 @@ public class CodeModelFactory private readonly LanguageEnum _language; private readonly bool _includePartial; - public CodeModelFactory(LanguageEnum language = LanguageEnum.CSharp, bool includePartial = false) + public CodeModelFactory(bool includePartial = false, LanguageEnum language = LanguageEnum.CSharp) { - _language = language; _includePartial = includePartial; + _language = language; } public CaDETProject CreateProject(IEnumerable multipleClassSourceCode) From 627410c6d82460c9c27cfd645e5849cb3e0f2be2 Mon Sep 17 00:00:00 2001 From: Nikola Luburic Date: Thu, 1 Feb 2024 07:17:15 +0100 Subject: [PATCH 46/46] fix: Resolves partial issue. --- .../Integration/CodeModelFactoryTests.cs | 33 +++++++++++++++++++ .../CaDETModel/CodeItems/CaDETModifier.cs | 5 ++- CodeModel/CodeModel.csproj | 2 +- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/CodeModel.Tests/Integration/CodeModelFactoryTests.cs b/CodeModel.Tests/Integration/CodeModelFactoryTests.cs index 4a137319..891776c2 100644 --- a/CodeModel.Tests/Integration/CodeModelFactoryTests.cs +++ b/CodeModel.Tests/Integration/CodeModelFactoryTests.cs @@ -74,6 +74,17 @@ public void Create_code_model_with_links(string folderLocation) difference.ShouldBeEmpty(); } + [Fact] + public void Create_code_model_with_links_with_partial_classes() + { + CodeModelFactory factory = new CodeModelFactory(true); + var project = factory.CreateProjectWithCodeFileLinks("C:/sdataset-partial"); + + var projectClassesAndMembersCount = project.Classes.Count + project.Classes.Sum(c => c.Members.Count); + + project.CodeLinks.Count.ShouldBe(projectClassesAndMembersCount); + } + [Fact] public void Create_code_model_with_links_on_large_repo() { @@ -93,5 +104,27 @@ public void Create_code_model_with_links_on_large_repo() locationLink.StartLoC.ShouldBe(15); locationLink.EndLoC.ShouldBe(16); } + + [Theory] + //[InlineData("C:\\temp\\challenge-sandbox\\start\\01. Structural Cohesion")] + //[InlineData("C:\\temp\\challenge-sandbox\\end\\01. structural")] + //[InlineData("C:\\temp\\challenge-sandbox\\start\\03. Coupling\\Employees")] + //[InlineData("C:\\temp\\challenge-sandbox\\end\\03. coupling employee")] + //[InlineData("C:\\temp\\challenge-sandbox\\start\\03. Coupling\\Rental")] + //[InlineData("C:\\temp\\challenge-sandbox\\end\\03. coupling rental")] + //[InlineData("C:\\temp\\challenge-sandbox\\start\\04. SRP\\Achievements")] + //[InlineData("C:\\temp\\challenge-sandbox\\end\\04. srp achievements")] + [InlineData("C:\\temp\\challenge-sandbox\\start\\04. SRP\\Books")] + [InlineData("C:\\temp\\challenge-sandbox\\end\\04. srp books")] + public void Create_code_model(string folderLocation) + { + CodeModelFactory factory = new CodeModelFactory(); + var project = factory.CreateProjectWithCodeFileLinks(folderLocation); + + var classes = project.Classes; + var members = project.Classes.SelectMany(c => c.Members); + + var firstClassMetrics = classes.First().Metrics; + } } } diff --git a/CodeModel/CaDETModel/CodeItems/CaDETModifier.cs b/CodeModel/CaDETModel/CodeItems/CaDETModifier.cs index 0496ea47..69ea6136 100644 --- a/CodeModel/CaDETModel/CodeItems/CaDETModifier.cs +++ b/CodeModel/CaDETModel/CodeItems/CaDETModifier.cs @@ -1,5 +1,4 @@ -using CodeModel.CodeParsers.CSharp.Exceptions; -using System.ComponentModel; +using System.ComponentModel; namespace CodeModel.CaDETModel.CodeItems { @@ -27,7 +26,7 @@ public CaDETModifier(string modifier) "const" => CaDETModifierValue.Const, "async" => CaDETModifierValue.Async, "volatile" => CaDETModifierValue.Volatile, - "partial" => throw new PartialIsNotSupportedException(), + "partial" => CaDETModifierValue.Partial, _ => throw new InvalidEnumArgumentException(modifier) }; } diff --git a/CodeModel/CodeModel.csproj b/CodeModel/CodeModel.csproj index 27509463..f783ef42 100644 --- a/CodeModel/CodeModel.csproj +++ b/CodeModel/CodeModel.csproj @@ -13,7 +13,7 @@ https://github.com/Clean-CaDET/platform/tree/master/CodeModel GPL-3.0-or-later true - 1.0.2 + 1.0.3