diff --git a/src/KPI Generator/Reportings/Resource/ResourceReporting.cs b/src/KPI Generator/Reportings/Resource/ResourceReporting.cs index 1f042c194a6d3bc162c7d7de58dc5eb7217cb6a9..845dfe026cd46cd9ff4b7c5dbf9a6349492b0c1e 100644 --- a/src/KPI Generator/Reportings/Resource/ResourceReporting.cs +++ b/src/KPI Generator/Reportings/Resource/ResourceReporting.cs @@ -1,22 +1,154 @@ -using KPIGenerator.Utils; +using Coscine.Database.Models; +using Coscine.Database.ReturnObjects; +using Coscine.ResourceTypes; +using Coscine.ResourceTypes.Base; +using KPIGenerator.Utils; +using Newtonsoft.Json; using static KPIGenerator.Utils.CommandLineOptions; namespace KPIGenerator.Reportings.Resource; public class ResourceReporting : Reporting<ResourceReportingOptions> { + private readonly ResourceModel _resourceModel; + private readonly ProjectModel _projectModel; + private readonly ProjectResourceModel _projectResourceModel; + public ResourceReporting(ResourceReportingOptions options) : base(options) { ReportingFileName = "resources.json"; + _resourceModel = new ResourceModel(); + _projectModel = new ProjectModel(); + _projectResourceModel = new ProjectResourceModel(); } public override IEnumerable<ReportingFileObject> GenerateReporting() { - /* - * 1. Collect the reporting for the whole database -- General/{ReportingReportingFileName} - * 2. Append to the list the same information per organization as folders -- Organizations/{OrgRorId}/{ReportingReportingFileName} - * --> See envisioned folder structure. - */ - throw new NotImplementedException(); + var resources = _resourceModel.GetAllWhere(r => r.Deleted.Equals(true) || r.Deleted.Equals(false)); + var reportingFiles = new List<ReportingFileObject>(); + var returnObjects = Generate(resources); + + // General File + reportingFiles.Add(new ReportingFileObject + { + Path = GetReportingPathGeneral(ReportingFileName), + Content = ConvertStringContentsToStream(JsonConvert.SerializeObject(returnObjects, Formatting.Indented)) + }); + // Per Organization + reportingFiles.AddRange(GeneratePerOrganization(returnObjects)); + + return reportingFiles; + } + + private List<ReturnObject> Generate(IEnumerable<Coscine.Database.DataModel.Resource> resources) + { + var returnObjects = new List<ReturnObject>(); + foreach (var resource in resources) + { + var resourceReturnObject = _resourceModel.CreateReturnObjectFromDatabaseObject(resource); + + var resourceReportEntry = new ReturnObject + { + Id = resourceReturnObject.Id, + ResourceType = resourceReturnObject.Type.DisplayName, + DateCreated = resourceReturnObject.DateCreated, + Archived = resourceReturnObject.Archived, + Deleted = resourceReturnObject.Deleted, + MetadataVisibilityId = resourceReturnObject.Visibility.Id, + RelatedProjectId = GetRelatedProject(resource.Id), + Organizations = GetOrganizations(resourceReturnObject.Id), + Disciplines = resourceReturnObject.Disciplines.ToList(), + License = resourceReturnObject.License is not null ? resourceReturnObject.License.DisplayName : null, + ApplicationProfile = resourceReturnObject.ApplicationProfile, + ResourceQuota = GetResourceQuota(resource) + }; + returnObjects.Add(resourceReportEntry); + } + return returnObjects; + } + + private IEnumerable<ReportingFileObject> GeneratePerOrganization(List<ReturnObject> returnObjects) + { + var reportingFilesPerOrganization = new List<ReportingFileObject>(); + var organizationsFromResources = returnObjects.SelectMany(ro => ro.Organizations).DistinctBy(o => o.RorUrl); + foreach (var entry in organizationsFromResources) + { + var organization = Organizations.Find(o => o.Equals(entry)); + if (organization is null) + { + organization = _otherOrganization; + Console.WriteLine($"WARNING!: Organization \"{entry.RorUrl}\" could not be correctly identified. Will use \"{_otherOrganization.RorUrl}\"."); + } + var returnObjectsForOrganization = returnObjects.Where(ro => ro.Organizations.Select(o => o.RorUrl).Any(e => e.Equals(entry.RorUrl))); + + reportingFilesPerOrganization.Add(new ReportingFileObject + { + Path = GetReportingPathOrganization(organization.RorUrl.Replace("https://ror.org/", "").ToLower(), ReportingFileName), + Content = ConvertStringContentsToStream(JsonConvert.SerializeObject(returnObjectsForOrganization, Formatting.Indented)) + }); + } + return reportingFilesPerOrganization; + } + + private Guid? GetRelatedProject(Guid resourceId) + { + try + { + return _projectResourceModel.GetProjectForResource(resourceId); + } + catch + { + Console.WriteLine($"There is no project related to resource with ID \"{resourceId}\"."); + return null; + } + } + + private static ResourceQuotaReturnObject? GetResourceQuota(Coscine.Database.DataModel.Resource resource) + { + BaseResourceType? resourceTypeDefinition; + try + { + resourceTypeDefinition = ResourceTypeFactory.Instance.GetResourceType(resource); + } + catch + { + Console.WriteLine($"No resource type definition found for resource with ID \"{resource.Id}\"."); + resourceTypeDefinition = null; + } + + if (resourceTypeDefinition is not null && resourceTypeDefinition.GetResourceTypeInformation().Result.IsQuotaAdjustable) + { + return Helpers.CreateResourceQuotaReturnObject(resource, resourceTypeDefinition); + } + else + { + return null; + } + } + + private List<Organization> GetOrganizations(Guid resourceId) + { + var result = new List<Organization>(); + Guid? relatedProjectId; + try + { + relatedProjectId = _projectResourceModel.GetProjectForResource(resourceId); + } + catch + { + relatedProjectId = null; + } + + if (relatedProjectId is not null) + { + var parentProject = _projectModel.GetByIdIncludingDeleted(relatedProjectId.Value); + var organizations = _projectModel.CreateReturnObjectFromDatabaseObject(parentProject).Organizations.ToList(); + + foreach (var entry in organizations) + { + result.Add(FetchOrganizationByRor(entry.Url)); + } + } + return result; } -} +} \ No newline at end of file diff --git a/src/KPI Generator/Reportings/Resource/ReturnObject.cs b/src/KPI Generator/Reportings/Resource/ReturnObject.cs index 550bafe6d8d978b935b2c1271012cb957e1254b1..04584f0377a5f4819884608ab51b99f42a9d9754 100644 --- a/src/KPI Generator/Reportings/Resource/ReturnObject.cs +++ b/src/KPI Generator/Reportings/Resource/ReturnObject.cs @@ -1,9 +1,24 @@ -namespace KPIGenerator.Reportings.Resource; +using Coscine.Database.ReturnObjects; +using KPIGenerator.Utils; + +namespace KPIGenerator.Reportings.Resource; /// <summary> /// Object containing the JSON structure for the reporting /// </summary> public class ReturnObject { + public Guid Id { get; set; } + public string ResourceType { get; set; } = null!; + public DateTime? DateCreated { get; set; } = null; + public bool Archived { get; set; } + public bool Deleted { get; set; } + public Guid MetadataVisibilityId { get; set; } + public Guid? RelatedProjectId { get; set; } + public List<Organization> Organizations { get; set; } = new(); + public List<DisciplineObject> Disciplines { get; set; } = new(); + public string? License { get; set; } = null; + public string ApplicationProfile { get; set; } = null!; + public ResourceQuotaReturnObject? ResourceQuota { get; set; } = null!; } diff --git a/src/KPI Generator/Reportings/User/ReturnObject.cs b/src/KPI Generator/Reportings/User/ReturnObject.cs index ae16dd4cdfb03a45e167753113ad23b65b659934..61a84e92f316aee7d0585b3d4038354a55baf81a 100644 --- a/src/KPI Generator/Reportings/User/ReturnObject.cs +++ b/src/KPI Generator/Reportings/User/ReturnObject.cs @@ -1,5 +1,4 @@ using Coscine.Database.ReturnObjects; -using Newtonsoft.Json; namespace KPIGenerator.Reportings.User; diff --git a/src/KPI Generator/Reportings/User/UserReporting.cs b/src/KPI Generator/Reportings/User/UserReporting.cs index b666f41cde0b73b195699048d3654c3beaa5739b..24779b64aa79c0730351aeddea255541d2b13bce 100644 --- a/src/KPI Generator/Reportings/User/UserReporting.cs +++ b/src/KPI Generator/Reportings/User/UserReporting.cs @@ -72,7 +72,7 @@ public class UserReporting : Reporting<UserReportingOptions> private IEnumerable<ReportingFileObject> GeneratePerOrganization(List<ReturnObject> returnObjects) { var reportingFilesPerOrganization = new List<ReportingFileObject>(); - var organizationsFromUsers = returnObjects.SelectMany(ro => ro.Organizations).Distinct(); + var organizationsFromUsers = returnObjects.SelectMany(ro => ro.Organizations); foreach (var entry in organizationsFromUsers) { var organization = Organizations.Find(o => o.Name.Equals(entry)); diff --git a/src/KPI Generator/Utils/Organization.cs b/src/KPI Generator/Utils/Organization.cs index b33b0f4d42c28177acbd4027fb11691a141d6976..6a9b80a53d32ffdffbecbae1a7f452170a30a3ec 100644 --- a/src/KPI Generator/Utils/Organization.cs +++ b/src/KPI Generator/Utils/Organization.cs @@ -8,12 +8,8 @@ public class Organization /// <example>RWTH Aachen University</example> public string Name { get; set; } = null!; /// <summary> - /// Organizaiton ROR from GitLab project's title - /// </summary> - /// <example>04xfq0f34</example> - public string RorUrl { get; set; } = null!; - /// <summary> /// Organizaiton ROR URL from GitLab project's title /// </summary> /// <example>https://ror.org/04xfq0f34</example> + public string RorUrl { get; set; } = null!; } \ No newline at end of file