168 lines
5.2 KiB
C#
168 lines
5.2 KiB
C#
|
|
using Microsoft.EntityFrameworkCore;
|
||
|
|
using public_valetax.Data;
|
||
|
|
using public_valetax.Models;
|
||
|
|
using public_valetax.DTOs;
|
||
|
|
using public_valetax.Exceptions;
|
||
|
|
|
||
|
|
namespace public_valetax.Repositories
|
||
|
|
{
|
||
|
|
public class TreeRepository(ApplicationDbContext _context) : ITreeRepository
|
||
|
|
{
|
||
|
|
public async Task<Tree?> GetTreeByNameAsync(string name)
|
||
|
|
{
|
||
|
|
return await _context.Trees
|
||
|
|
.Include(t => t.Nodes)
|
||
|
|
.FirstOrDefaultAsync(t => t.Name == name);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<Tree> CreateTreeAsync(string name)
|
||
|
|
{
|
||
|
|
var tree = new Tree
|
||
|
|
{
|
||
|
|
Name = name,
|
||
|
|
CreatedAt = DateTime.UtcNow
|
||
|
|
};
|
||
|
|
|
||
|
|
if (await _context.Trees.AnyAsync(t => t.Name == name))
|
||
|
|
{
|
||
|
|
throw new SecureException("Tree with such name already exist");
|
||
|
|
}
|
||
|
|
|
||
|
|
_context.Trees.Add(tree);
|
||
|
|
await _context.SaveChangesAsync();
|
||
|
|
return tree;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<Node?> GetNodeByIdAsync(long nodeId)
|
||
|
|
{
|
||
|
|
return await _context.Nodes.FindAsync(nodeId);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<Node> CreateNodeAsync(long treeId, long? parentId, string name)
|
||
|
|
{
|
||
|
|
// Verify that parent node belongs to the same tree if provided
|
||
|
|
if (parentId.HasValue)
|
||
|
|
{
|
||
|
|
var parentNode = await _context.Nodes.FindAsync(parentId.Value);
|
||
|
|
if (parentNode == null || parentNode.TreeId != treeId)
|
||
|
|
{
|
||
|
|
throw new SecureException("Parent node does not belong to the specified tree");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if a node with the same name already exists in the same tree
|
||
|
|
var existingNode = await _context.Nodes
|
||
|
|
.FirstOrDefaultAsync(n => n.TreeId == treeId && n.Name == name && n.ParentId == parentId);
|
||
|
|
|
||
|
|
if (existingNode != null)
|
||
|
|
{
|
||
|
|
throw new SecureException("A node with the same name already exists in this location");
|
||
|
|
}
|
||
|
|
|
||
|
|
var node = new Node
|
||
|
|
{
|
||
|
|
TreeId = treeId,
|
||
|
|
ParentId = parentId,
|
||
|
|
Name = name,
|
||
|
|
CreatedAt = DateTime.UtcNow
|
||
|
|
};
|
||
|
|
|
||
|
|
_context.Nodes.Add(node);
|
||
|
|
await _context.SaveChangesAsync();
|
||
|
|
return node;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task DeleteNodeAsync(long nodeId)
|
||
|
|
{
|
||
|
|
var node = await _context.Nodes
|
||
|
|
.Include(n => n.Children)
|
||
|
|
.FirstOrDefaultAsync(n => n.Id == nodeId);
|
||
|
|
|
||
|
|
if (node == null)
|
||
|
|
{
|
||
|
|
throw new SecureException("Node not found");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if node has children
|
||
|
|
if (node.Children.Any())
|
||
|
|
{
|
||
|
|
throw new SecureException("You have to delete all children nodes first");
|
||
|
|
}
|
||
|
|
|
||
|
|
_context.Nodes.Remove(node);
|
||
|
|
await _context.SaveChangesAsync();
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task RenameNodeAsync(long nodeId, string newName)
|
||
|
|
{
|
||
|
|
var node = await _context.Nodes.FindAsync(nodeId);
|
||
|
|
|
||
|
|
if (node == null)
|
||
|
|
{
|
||
|
|
throw new SecureException("Node not found");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if another node with the same name already exists in the same parent
|
||
|
|
var existingNode = await _context.Nodes
|
||
|
|
.FirstOrDefaultAsync(n => n.TreeId == node.TreeId && n.Name == newName && n.ParentId == node.ParentId && n.Id != nodeId);
|
||
|
|
|
||
|
|
if (existingNode != null)
|
||
|
|
{
|
||
|
|
throw new SecureException("A node with the same name already exists in this location");
|
||
|
|
}
|
||
|
|
|
||
|
|
node.Name = newName;
|
||
|
|
await _context.SaveChangesAsync();
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<MNode?> GetTreeStructureAsync(string treeName)
|
||
|
|
{
|
||
|
|
var tree = await _context.Trees
|
||
|
|
.Include(t => t.Nodes)
|
||
|
|
.FirstOrDefaultAsync(t => t.Name == treeName);
|
||
|
|
|
||
|
|
if (tree == null)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Build the tree structure recursively
|
||
|
|
var rootNodes = tree.Nodes
|
||
|
|
.Where(n => n.ParentId == null)
|
||
|
|
.Select(n => BuildMNode(n, tree.Nodes))
|
||
|
|
.ToList();
|
||
|
|
|
||
|
|
// If no root node exists, create one
|
||
|
|
if (!rootNodes.Any())
|
||
|
|
{
|
||
|
|
return new MNode
|
||
|
|
{
|
||
|
|
Id = 0,
|
||
|
|
Name = tree.Name,
|
||
|
|
Children = []
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return rootNodes.First();
|
||
|
|
}
|
||
|
|
|
||
|
|
private MNode BuildMNode(Node node, ICollection<Node> allNodes)
|
||
|
|
{
|
||
|
|
var mNode = new MNode
|
||
|
|
{
|
||
|
|
Id = node.Id,
|
||
|
|
Name = node.Name,
|
||
|
|
Children = []
|
||
|
|
};
|
||
|
|
|
||
|
|
// Add children recursively
|
||
|
|
var children = allNodes.Where(n => n.ParentId == node.Id).ToList();
|
||
|
|
foreach (var child in children)
|
||
|
|
{
|
||
|
|
mNode.Children.Add(BuildMNode(child, allNodes));
|
||
|
|
}
|
||
|
|
|
||
|
|
return mNode;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|