diff --git a/RelationshipAnalysis/Controllers/EdgeController.cs b/RelationshipAnalysis/Controllers/EdgeController.cs index 5734321..5a5d8d5 100644 --- a/RelationshipAnalysis/Controllers/EdgeController.cs +++ b/RelationshipAnalysis/Controllers/EdgeController.cs @@ -14,7 +14,8 @@ namespace RelationshipAnalysis.Controllers; public class EdgeController( ICreateEdgeCategoryService createEdgeCategoryService, IEdgeCategoryReceiver edgeCategoryReceiver, - IEdgesAdditionService edgesAdditionService) + IEdgesAdditionService edgesAdditionService, + [FromKeyedServices("edge")] IInfoReceiver infoReceiver) : ControllerBase { @@ -25,6 +26,14 @@ public async Task GetAllEdgeCategories() return Ok(result); } + + [HttpGet] + public async Task GetInfo(int edgeId) + { + var result = await infoReceiver.GetInfo(edgeId); + return StatusCode((int)result.StatusCode, result.Data); + } + [HttpPost("categories")] public async Task CreateEdgeCategory([FromBody] CreateEdgeCategoryDto createEdgeCategoryDto) { diff --git a/RelationshipAnalysis/Controllers/GraphController.cs b/RelationshipAnalysis/Controllers/GraphController.cs index b5cf057..ad26917 100644 --- a/RelationshipAnalysis/Controllers/GraphController.cs +++ b/RelationshipAnalysis/Controllers/GraphController.cs @@ -8,11 +8,18 @@ namespace RelationshipAnalysis.Controllers; [ApiController] [Authorize] [Route("api/[controller]")] -public class GraphController(IGraphReceiver graphReceiver) : ControllerBase +public class GraphController(IGraphReceiver graphReceiver, + IExpansionGraphReceiver expansionGraphReceiver) : ControllerBase { [HttpGet] public async Task GetGraph() { return Ok(await graphReceiver.GetGraph()); } + [HttpGet("expansion")] + public async Task GetExpansionGraph(int nodeId, string sourceCategoryName, string targetCategoryName, string edgeCategoryName) + { + var result = await expansionGraphReceiver.GetExpansionGraph(nodeId, sourceCategoryName, targetCategoryName, edgeCategoryName); + return Ok(result); + } } \ No newline at end of file diff --git a/RelationshipAnalysis/Controllers/NodeController.cs b/RelationshipAnalysis/Controllers/NodeController.cs index b70c9bc..0611480 100644 --- a/RelationshipAnalysis/Controllers/NodeController.cs +++ b/RelationshipAnalysis/Controllers/NodeController.cs @@ -14,7 +14,8 @@ namespace RelationshipAnalysis.Controllers; public class NodeController( ICreateNodeCategoryService createNodeCategoryService, INodeCategoryReceiver nodeCategoryReceiver, - INodesAdditionService nodesAdditionService) + INodesAdditionService nodesAdditionService, + [FromKeyedServices("node")] IInfoReceiver infoReceiver) : ControllerBase { [HttpGet("categories")] @@ -24,6 +25,12 @@ public async Task GetAllNodeCategories() return Ok(result); } + [HttpGet] + public async Task GetInfo(int nodeId) + { + var result = await infoReceiver.GetInfo(nodeId); + return StatusCode((int)result.StatusCode, result.Data); + } [HttpPost("categories")] public async Task CreateNodeCategory([FromBody] CreateNodeCategoryDto createNodeCategoryDto) diff --git a/RelationshipAnalysis/Dto/Graph/ExpansionDto.cs b/RelationshipAnalysis/Dto/Graph/ExpansionDto.cs new file mode 100644 index 0000000..61ef24d --- /dev/null +++ b/RelationshipAnalysis/Dto/Graph/ExpansionDto.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace RelationshipAnalysis.Dto.Graph; + +public class ExpansionDto +{ + [Required] + public int NodeId { get; set; } + [Required] + public int SourceCategoryId { get; set; } + [Required] + public int TargetCategoryId { get; set; } + [Required] + public int EdgeCategoryId { get; set; } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Program.cs b/RelationshipAnalysis/Program.cs index 69a0c6c..38b0d15 100644 --- a/RelationshipAnalysis/Program.cs +++ b/RelationshipAnalysis/Program.cs @@ -56,7 +56,11 @@ .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton(); + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddKeyedSingleton("node") + .AddKeyedSingleton("edge"); diff --git a/RelationshipAnalysis/Services/GraphServices/Abstraction/IExpansionGraphReceiver.cs b/RelationshipAnalysis/Services/GraphServices/Abstraction/IExpansionGraphReceiver.cs new file mode 100644 index 0000000..255cfaf --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/Abstraction/IExpansionGraphReceiver.cs @@ -0,0 +1,10 @@ +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Graph; + +namespace RelationshipAnalysis.Services.GraphServices.Abstraction; + +public interface IExpansionGraphReceiver +{ + Task GetExpansionGraph(int nodeId, string sourceCategoryName, string targetCategoryName, + string edgeCategoryName); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/Abstraction/IGraphDtoCreator.cs b/RelationshipAnalysis/Services/GraphServices/Abstraction/IGraphDtoCreator.cs new file mode 100644 index 0000000..afc0867 --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/Abstraction/IGraphDtoCreator.cs @@ -0,0 +1,10 @@ +using RelationshipAnalysis.Dto.Graph; +using RelationshipAnalysis.Models.Graph; +using Node = AngleSharp.Dom.Node; + +namespace RelationshipAnalysis.Services.GraphServices.Abstraction; + +public interface IGraphDtoCreator +{ + GraphDto CreateResultGraphDto(List contextNodes, List contextEdges); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/Abstraction/IInfoReceiver.cs b/RelationshipAnalysis/Services/GraphServices/Abstraction/IInfoReceiver.cs new file mode 100644 index 0000000..03b62b9 --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/Abstraction/IInfoReceiver.cs @@ -0,0 +1,8 @@ +using RelationshipAnalysis.Dto; + +namespace RelationshipAnalysis.Services.GraphServices.Abstraction; + +public interface IInfoReceiver +{ + Task>> GetInfo(int id); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/EdgeInfoReceiver.cs b/RelationshipAnalysis/Services/GraphServices/EdgeInfoReceiver.cs new file mode 100644 index 0000000..8061e7c --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/EdgeInfoReceiver.cs @@ -0,0 +1,41 @@ +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Enums; +using RelationshipAnalysis.Services.GraphServices.Abstraction; + +namespace RelationshipAnalysis.Services.GraphServices; + +public class EdgeInfoReceiver(IServiceProvider serviceProvider) : IInfoReceiver +{ + public Task>> GetInfo(int edgeId) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + + var result = new Dictionary(); + var selectedEdge = context.Edges.SingleOrDefault(e => e.EdgeId == edgeId); + if (selectedEdge == null) + { + return NotFoundResult(); + } + selectedEdge.EdgeValues.ToList().ForEach(v => result.Add(v.EdgeAttribute.EdgeAttributeName, v.ValueData)); + return SuccessResult(result); + } + + private async Task>> NotFoundResult() + { + return new ActionResponse>() + { + StatusCode = StatusCodeType.NotFound + }; + } + + private async Task>> SuccessResult(Dictionary result) + { + return new ActionResponse>() + { + StatusCode = StatusCodeType.Success, + Data = result + }; + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/ExpansionGraphReceiver.cs b/RelationshipAnalysis/Services/GraphServices/ExpansionGraphReceiver.cs new file mode 100644 index 0000000..f9d0015 --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/ExpansionGraphReceiver.cs @@ -0,0 +1,46 @@ +using Microsoft.EntityFrameworkCore; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto.Graph; +using RelationshipAnalysis.Models.Graph; +using RelationshipAnalysis.Services.GraphServices.Abstraction; + +namespace RelationshipAnalysis.Services.GraphServices; + +public class ExpansionGraphReceiver(IServiceProvider serviceProvider, IGraphDtoCreator graphDtoCreator) : IExpansionGraphReceiver +{ + public async Task GetExpansionGraph(int nodeId, string sourceCategoryName, string targetCategoryName, string edgeCategoryName) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + + var inputNodes = await GetInputNodes(sourceCategoryName, context); + var outputNodes = await GetOutputNodes(targetCategoryName, context); + var validEdges = await GetValidEdges(edgeCategoryName, context, inputNodes, outputNodes); + + return graphDtoCreator.CreateResultGraphDto(inputNodes.Union(outputNodes).ToList(), validEdges); + } + + private async Task> GetValidEdges(string edgeCategoryName, ApplicationDbContext context, List inputNodes, + List outputNodes) + { + var validEdges = await context.Edges.Where(e => + e.EdgeCategory.EdgeCategoryName == edgeCategoryName && + inputNodes.Contains(e.NodeSource) && + outputNodes.Contains(e.NodeDestination)).ToListAsync(); + return validEdges; + } + + private async Task> GetOutputNodes(string targetCategoryName, ApplicationDbContext context) + { + var outputNodes = + await context.Nodes.Where(n => n.NodeCategory.NodeCategoryName == targetCategoryName).ToListAsync(); + return outputNodes; + } + + private async Task> GetInputNodes(string sourceCategoryName, ApplicationDbContext context) + { + var inputNodes = + await context.Nodes.Where(n => n.NodeCategory.NodeCategoryName == sourceCategoryName).ToListAsync(); + return inputNodes; + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/GraphDtoCreator.cs b/RelationshipAnalysis/Services/GraphServices/GraphDtoCreator.cs new file mode 100644 index 0000000..02a8db2 --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/GraphDtoCreator.cs @@ -0,0 +1,28 @@ +using RelationshipAnalysis.Dto.Graph; +using RelationshipAnalysis.Models.Graph; +using RelationshipAnalysis.Services.GraphServices.Abstraction; +using Node = AngleSharp.Dom.Node; + +namespace RelationshipAnalysis.Services.GraphServices; + +public class GraphDtoCreator : IGraphDtoCreator +{ + + public GraphDto CreateResultGraphDto(List contextNodes, List contextEdges) + { + if (contextEdges == null || contextNodes == null) throw new ArgumentNullException(); + var resultGraphDto = new GraphDto(); + contextNodes.ForEach(n => resultGraphDto.nodes.Add(new NodeDto + { + id = n.NodeId.ToString(), + label = $"{n.NodeCategory.NodeCategoryName}/{n.NodeUniqueString}" + })); + contextEdges.ForEach(e => resultGraphDto.edges.Add(new EdgeDto + { + id = e.EdgeId.ToString(), + source = e.EdgeSourceNodeId.ToString(), + target = e.EdgeDestinationNodeId.ToString() + })); + return resultGraphDto; + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/NodeInfoReceiver.cs b/RelationshipAnalysis/Services/GraphServices/NodeInfoReceiver.cs new file mode 100644 index 0000000..0d8fa2e --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/NodeInfoReceiver.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Mvc; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Enums; +using RelationshipAnalysis.Services.GraphServices.Abstraction; + +namespace RelationshipAnalysis.Services.GraphServices; + +public class NodeInfoReceiver(IServiceProvider serviceProvider) : IInfoReceiver +{ + public Task>> GetInfo(int nodeId) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + + var result = new Dictionary(); + var selectedNode = context.Nodes.SingleOrDefault(n => n.NodeId == nodeId); + if (selectedNode == null) + { + return NotFoundResult(); + } + selectedNode.Values.ToList().ForEach(v => result.Add(v.NodeAttribute.NodeAttributeName, v.ValueData)); + return SuccessResult(result); + } + + private async Task>> NotFoundResult() + { + return new ActionResponse>() + { + StatusCode = StatusCodeType.NotFound + }; + } + + private async Task>> SuccessResult(Dictionary result) + { + return new ActionResponse>() + { + StatusCode = StatusCodeType.Success, + Data = result + }; + } +} \ No newline at end of file