using Coscine.ApiClient; using Coscine.ApiClient.Core.Model; using SQL2Linked.Utils; using VDS.RDF; namespace SQL2Linked.Implementations; /// <summary> /// Class responsible for converting project data into linked data graphs. /// It retrieves project information from the API and then transforms this data into a series of RDF graphs, /// making use of predefined URIs and RDF constructs. /// </summary> public class ProjectStructuralData : StructuralData<ProjectAdminDto> { public override IAsyncEnumerable<ProjectAdminDto> GetAll() => PaginationHelper.GetAllAsync<ProjectAdminDtoPagedResponse, ProjectAdminDto>( (currentPage) => _adminApi.GetAllProjectsAsync(includeDeleted: true, pageNumber: currentPage, pageSize: 50)); public override async IAsyncEnumerable<IGraph> ConvertToLinkedDataAsync(IAsyncEnumerable<ProjectAdminDto> entries) { var coscineHandlePrefix = UriHelper.TryCombinePath(RdfUris.HandlePrefix, _pidConfiguration.Prefix) ?? throw new Exception("Could not combine handle prefix with PID prefix"); var coscineGraph = new Graph { BaseUri = RdfUris.CoscinePrefix }; AssertToGraphUriNode(coscineGraph, RdfUris.CoscinePrefix, RdfUris.DcatCatalog, RdfUris.CoscineProjects); AssertToGraphUriNode(coscineGraph, RdfUris.CoscinePrefix, RdfUris.DcatCatalog, RdfUris.CoscineResources); yield return coscineGraph; // yield coscineGraph first var trellisGraph = PatchGraph.Empty(RdfUris.TrellisGraph); await foreach (var entry in entries) { var projectGraphName = UriHelper.TryCombineUri(RdfUris.CoscineProjects, entry.Id) ?? throw new Exception("Could not combine projects prefix with project ID"); var projectHandleName = UriHelper.TryCombineUri(coscineHandlePrefix, entry.Id); var graph = new Graph { BaseUri = projectGraphName }; AssertToGraphUriNode(graph, projectGraphName, RdfUris.A, RdfUris.DcatCatalogClass); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.A} {RdfUris.DcatCatalogClass}'. "); AssertToGraphUriNode(graph, projectGraphName, RdfUris.A, RdfUris.OrgOrganizationalCollaborationClass); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.A} {RdfUris.OrgOrganizationalCollaborationClass}'. "); AssertToGraphUriNode(graph, projectGraphName, RdfUris.A, RdfUris.VcardGroupClass); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.A} {RdfUris.VcardGroupClass}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsTitle, entry.Name); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsTitle} {entry.Name}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsDescription, entry.Description); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsDescription} {entry.Description}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsStartDate, entry.StartDate.ToString(), new Uri("http://www.w3.org/2001/XMLSchema#dateTime")); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsStartDate} {entry.StartDate}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsEndDate, entry.EndDate.ToString(), new Uri("http://www.w3.org/2001/XMLSchema#dateTime")); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsEndDate} {entry.EndDate}'. "); if (entry.Keywords.Count > 0) { foreach (var keyword in entry.Keywords) { AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsSubject, keyword); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsSubject} {keyword}'. "); } } AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsAlternative, entry.DisplayName); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsAlternative} {entry.DisplayName}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsRightsHolder, entry.PrincipleInvestigators); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsRightsHolder} {entry.PrincipleInvestigators}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.SchemaFunding, entry.GrantId); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.SchemaFunding} {entry.GrantId}'. "); if (entry.Visibility.DisplayName.Contains("Public")) { AssertToGraphUriNode(graph, projectGraphName, RdfUris.CoscineTermsProjectVisibility, RdfUris.CoscineTermsVisibilityPublic); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.CoscineTermsProjectVisibility} {RdfUris.CoscineTermsVisibilityPublic}'. "); } else if (entry.Visibility.DisplayName.Contains("Project Members")) { AssertToGraphUriNode(graph, projectGraphName, RdfUris.CoscineTermsProjectVisibility, RdfUris.CoscineTermsVisibilityProjectMember); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.CoscineTermsProjectVisibility} {RdfUris.CoscineTermsVisibilityProjectMember}'. "); } AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.CoscineTermsProjectDeleted, entry.Deleted.ToString().ToLower(), RdfUris.XsdBoolean); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.CoscineTermsProjectDeleted} {entry.Deleted}'. "); AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.CoscineTermsProjectSlug, entry.Slug); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.CoscineTermsProjectSlug} {entry.Slug}'. "); AssertToGraphUriNode(graph, projectGraphName, RdfUris.FoafHomepage, projectHandleName); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.FoafHomepage} {projectHandleName}'. "); foreach (var projectRole in entry.ProjectRoles) { AssertToGraphUriNode(graph, projectGraphName, RdfUris.VcardHasMember, UriHelper.TryCombineUri(RdfUris.CoscineUsers, projectRole.UserId)); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.VcardHasMember} {UriHelper.TryCombineUri(RdfUris.CoscineUsers, projectRole.UserId)}'. "); var blankNode = graph.CreateBlankNode(); AssertToGraphBlankAndUriNode(graph, blankNode, RdfUris.A, RdfUris.OrgMembershipClass); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{blankNode} {RdfUris.A} {RdfUris.OrgMembershipClass}'. "); AssertToGraphBlankAndUriNode(graph, blankNode, RdfUris.OrgOrganization, projectGraphName); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{blankNode} {RdfUris.OrgOrganization} {projectGraphName}'. "); AssertToGraphBlankAndUriNode(graph, blankNode, RdfUris.OrgRole, UriHelper.TryCombineUri(RdfUris.CoscineRoles, projectRole.RoleId)); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{blankNode} {RdfUris.OrgRole} {UriHelper.TryCombineUri(RdfUris.CoscineRoles, projectRole.RoleId)}'. "); AssertToGraphBlankAndUriNode(graph, blankNode, RdfUris.OrgMember, UriHelper.TryCombineUri(RdfUris.CoscineUsers, projectRole.UserId)); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{blankNode} {RdfUris.OrgMember} {UriHelper.TryCombineUri(RdfUris.CoscineUsers, projectRole.UserId)}'. "); } foreach (var projectResource in entry.ProjectResources) { AssertToGraphUriNode(graph, projectGraphName, RdfUris.DcatCatalog, UriHelper.TryCombineUri(RdfUris.CoscineResources, projectResource.ResourceId)); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcatCatalog} {UriHelper.TryCombineUri(RdfUris.CoscineResources, projectResource.ResourceId)}'. "); } foreach (var projectInstitute in entry.Organizations) { AssertToGraphUriNode(graph, projectGraphName, RdfUris.OrgOrganization, new Uri(projectInstitute.Uri)); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.OrgOrganization} {projectInstitute.Uri}'. "); } if (entry.Creator is not null) { AssertToGraphUriNode(graph, projectGraphName, RdfUris.DcTermsCreator, UriHelper.TryCombineUri(RdfUris.CoscineUsers, entry.Creator.Id)); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsCreator} {UriHelper.TryCombineUri(RdfUris.CoscineUsers, entry.Creator.Id)}'. "); } if (entry.CreationDate is not null && entry.CreationDate.HasValue) { AssertToGraphLiteralNode(graph, projectGraphName, RdfUris.DcTermsCreated, entry.CreationDate.Value.ToString(), RdfUris.XsdDateTime); Console.WriteLine($"For project '{entry.DisplayName}' will migrate triple '{projectGraphName} {RdfUris.DcTermsCreated} {entry.CreationDate}'. "); } // Add data to the trellis graph AssertToGraphUriNode(trellisGraph, projectGraphName, RdfUris.A, RdfUris.LdpBasicContainerClass); AddModifiedDate(trellisGraph, projectGraphName); AssertToGraphUriNode(trellisGraph, projectGraphName, RdfUris.DcTermsIsPartOf, RdfUris.CoscineProjectsEntity); AssertToGraphUriNode(trellisGraph, RdfUris.CoscineProjectsEntity, RdfUris.A, RdfUris.LdpBasicContainerClass); AddModifiedDate(trellisGraph, RdfUris.CoscineProjectsEntity); AssertToGraphUriNode(trellisGraph, RdfUris.CoscineProjectsEntity, RdfUris.DcTermsIsPartOf, RdfUris.CoscinePrefix); AssertToGraphUriNode(trellisGraph, RdfUris.CoscinePrefix, RdfUris.A, RdfUris.LdpBasicContainerClass); AddModifiedDate(trellisGraph, RdfUris.CoscinePrefix); yield return graph; } yield return trellisGraph; } }