From 7603e60b76fc34571e664960648da4a41c5a3e51 Mon Sep 17 00:00:00 2001 From: Sirieam Marie Hunke <hunke@itc.rwth-aachen.de> Date: Tue, 27 Aug 2024 14:00:16 +0000 Subject: [PATCH] New: Migrate SQL2Linked to GD --- src/GraphDeployer/Deployer.cs | 135 +++++++++- .../Implementations/PatchGraph.cs | 77 ++++++ .../ResourcetypeStructuralData.cs | 93 +++++++ .../Implementations/RoleStructuralData.cs | 77 ++++++ .../SQL2LinkedConfiguration.cs | 17 ++ src/GraphDeployer/Utils/RdfUris.cs | 234 ++++++++++++++++++ src/GraphDeployer/Utils/UriHelper.cs | 52 ++++ 7 files changed, 684 insertions(+), 1 deletion(-) create mode 100644 src/GraphDeployer/Implementations/PatchGraph.cs create mode 100644 src/GraphDeployer/Implementations/ResourcetypeStructuralData.cs create mode 100644 src/GraphDeployer/Implementations/RoleStructuralData.cs create mode 100644 src/GraphDeployer/Models/ConfigurationModels/SQL2LinkedConfiguration.cs create mode 100644 src/GraphDeployer/Utils/RdfUris.cs create mode 100644 src/GraphDeployer/Utils/UriHelper.cs diff --git a/src/GraphDeployer/Deployer.cs b/src/GraphDeployer/Deployer.cs index 790c84c..46484df 100644 --- a/src/GraphDeployer/Deployer.cs +++ b/src/GraphDeployer/Deployer.cs @@ -1,4 +1,5 @@ -using Coscine.ApiClient; +using System.Globalization; +using Coscine.ApiClient; using Coscine.ApiClient.Core.Api; using Coscine.ApiClient.Core.Model; using Coscine.GraphDeployer.Models.ConfigurationModels; @@ -8,6 +9,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Polly; using VDS.RDF; +using VDS.RDF.Parsing; using static Coscine.GraphDeployer.Utils.CommandLineOptions; using Configuration = Coscine.ApiClient.Core.Client.Configuration; @@ -166,6 +168,9 @@ public class Deployer continue; } } + // Convert to linked data + + // Store the graph } // Clean up the working folder @@ -265,4 +270,132 @@ public class Deployer _logger.LogError(e, "Failed to delete contents of the working folder: \"{workingFolder}\"", WorkingFolder); } } + /// <summary> + /// Asynchronously stores a collection of RDF graphs in the underlying data store. + /// </summary> + /// <param name="graphs">An asynchronous enumerable of RDF graphs (<see cref="IAsyncEnumerable{IGraph}"/>) to be stored.</param> + /// <returns>A task representing the asynchronous operation of storing the graphs.</returns> + public async Task StoreGraphs(IAsyncEnumerable<IGraph> graphs) + { + var formatEnum = RdfFormat.TextTurtle; + var format = "text/turtle"; + + await foreach (var graph in graphs) + { + Console.WriteLine($" ({graph.BaseUri})"); + + try + { + var rdfWriter = MimeTypesHelper.GetWriter(format); + var content = VDS.RDF.Writing.StringWriter.Write(graph, rdfWriter); + + if (graph is PatchGraph patchGraph) + { + var patchOperations = new List<RdfPatchOperationDto> + { + new(RdfPatchOperationType.A, new RdfDefinitionForManipulationDto(content, formatEnum)) + }; + + await _adminApi.PatchMetadataAsync( + graph.BaseUri.AbsoluteUri, + new RdfPatchDocumentDto(patchOperations) + ); + } + else + { + await _adminApi.UpdateMetadataGraphAsync( + graph.BaseUri.AbsoluteUri, + new MetadataUpdateAdminParameters(new RdfDefinitionForManipulationDto(content, formatEnum)) + ); + } + + Console.WriteLine($" - Graph {graph.BaseUri} added successfully"); + Console.WriteLine(); + } + catch (Exception e) + { + Console.Error.WriteLine($"Error on ({graph.BaseUri}):"); + Console.Error.WriteLine(e); + Console.Error.WriteLine(e.InnerException); + Console.Error.WriteLine(); + } + } + } + + + // TODO: Move to own class + public void AddModifiedDate(IGraph graph, Uri rootUri) + { + AssertToGraphLiteralNode( + graph, + rootUri, + RdfUris.DcTermsModified, + DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture), + new Uri(XmlSpecsHelper.XmlSchemaDataTypeDateTime) + ); + } + + /// <summary> + /// Asserts a triple to the graph with a URI node object. + /// </summary> + /// <param name="graph">The graph to assert to.</param> + /// <param name="graphSubject">The subject URI of the triple.</param> + /// <param name="graphPredicate">The predicate URI of the triple.</param> + /// <param name="graphObject">The object URI of the triple.</param> + public void AssertToGraphUriNode(IGraph graph, Uri graphSubject, Uri graphPredicate, Uri? graphObject) + { + if (graphObject != null) + { + graph.Assert( + new Triple( + graph.CreateUriNode(graphSubject), + graph.CreateUriNode(graphPredicate), + graph.CreateUriNode(graphObject) + ) + ); + } + } + + /// <summary> + /// Asserts a triple to the graph with a literal node object. + /// </summary> + /// <param name="graph">The graph to assert to.</param> + /// <param name="graphSubject">The subject URI of the triple.</param> + /// <param name="graphPredicate">The predicate URI of the triple.</param> + /// <param name="graphObject">The literal object of the triple.</param> + /// <param name="objectType">The data type URI of the literal object, if any.</param> + public void AssertToGraphLiteralNode(IGraph graph, Uri graphSubject, Uri graphPredicate, string? graphObject, Uri? objectType = null) + { + if (graphObject != null) + { + graph.Assert( + new Triple( + graph.CreateUriNode(graphSubject), + graph.CreateUriNode(graphPredicate), + objectType is not null ? graph.CreateLiteralNode(graphObject, objectType) : graph.CreateLiteralNode(graphObject) + ) + ); + } + } + + /// <summary> + /// Asserts a triple to the graph with a blank node subject and a URI node object. + /// </summary> + /// <param name="graph">The graph to assert to.</param> + /// <param name="graphSubject">The blank node subject of the triple.</param> + /// <param name="graphPredicate">The predicate URI of the triple.</param> + /// <param name="graphObject">The object URI of the triple.</param> + public void AssertToGraphBlankAndUriNode(IGraph graph, IBlankNode graphSubject, Uri graphPredicate, Uri? graphObject) + { + if (graphObject != null) + { + graph.Assert( + new Triple( + graphSubject, + graph.CreateUriNode(graphPredicate), + graph.CreateUriNode(graphObject) + ) + ); + } + } } \ No newline at end of file diff --git a/src/GraphDeployer/Implementations/PatchGraph.cs b/src/GraphDeployer/Implementations/PatchGraph.cs new file mode 100644 index 0000000..ff4ad94 --- /dev/null +++ b/src/GraphDeployer/Implementations/PatchGraph.cs @@ -0,0 +1,77 @@ +using VDS.RDF; + +namespace Coscine.GraphDeployer; + +/// <summary> +/// Represents a specialized RDF graph for small-scale updates. +/// This class extends the standard Graph class with additional +/// functionalities for tracking changes (assertions and retractions). +/// </summary> +/// <remarks><i>TODO: Consider extending <see cref="ITransactionalGraph"/> to allow for rollback and commit operations.</i></remarks> +public class PatchGraph : Graph +{ + public List<Triple> AssertList { get; set; } = new(); + + public List<Triple> RetractList { get; set; } = new(); + + /// <summary> + /// Initializes a new instance of the <see cref="PatchGraph"/> class. + /// </summary> + public PatchGraph() : base() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="PatchGraph"/> class. + /// </summary> + public PatchGraph(Uri graphUri) : base(graphUri) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="IPatchGraph"/> class with the specified graph URI. + /// </summary> + /// <param name="graphUri">The base URI for the graph.</param> + /// <returns>A new empty instance of <see cref="IPatchGraph"/> with the provided base URI.</returns> + public static PatchGraph Empty(Uri graphUri) + { + return new PatchGraph(graphUri) + { + BaseUri = graphUri + }; + } + + /// <summary> + /// Initializes a new instance of the <see cref="IPatchGraph"/> class with the specified graph URI. + /// </summary> + /// <param name="graphUri">The base URI for the graph as a string.</param> + /// <returns>A new empty instance of <see cref="IPatchGraph"/> with the provided base URI.</returns> + public static PatchGraph Empty(string graphUri) + { + return Empty(new Uri(graphUri)); + } + + public override bool Assert(Triple t) + { + AssertList.Add(t); + return base.Assert(t); + } + + public override bool Assert(IEnumerable<Triple> triples) + { + AssertList.AddRange(triples); + return base.Assert(triples); + } + + public override bool Retract(Triple t) + { + RetractList.Add(t); + return base.Retract(t); + } + + public override bool Retract(IEnumerable<Triple> triples) + { + RetractList.AddRange(triples); + return base.Retract(triples); + } +} diff --git a/src/GraphDeployer/Implementations/ResourcetypeStructuralData.cs b/src/GraphDeployer/Implementations/ResourcetypeStructuralData.cs new file mode 100644 index 0000000..3b5356d --- /dev/null +++ b/src/GraphDeployer/Implementations/ResourcetypeStructuralData.cs @@ -0,0 +1,93 @@ +using Coscine.ApiClient.Core.Api; +using Coscine.ApiClient.Core.Model; +using VDS.RDF; +using VDS.RDF.Parsing; + +namespace Coscine.GraphDeployer; +/// <summary> +/// Class responsible for converting resource type data into linked data graphs. +/// It retrieves resource type 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 ResourceTypeStructuralData +{ + private readonly Deployer _deployer; + private readonly AdminApi _adminApi; + public ResourceTypeStructuralData(AdminApi adminApi, Deployer deployer) + { + _adminApi = adminApi; + _deployer = deployer; + + } + public async IAsyncEnumerable<ResourceTypeInformationDto> GetAll() + { + var resourceTypeApi = new ResourceTypeApi(apiClientConfig); + var resourceTypeInformationsResponse = await resourceTypeApi.GetAllResourceTypesInformationAsync(); + foreach (var item in resourceTypeInformationsResponse.Data) + { + yield return item; // Yield each item in the list to keep the IAsyncEnumerable logic + } + } + + public override async IAsyncEnumerable<IGraph> ConvertToLinkedDataAsync(IAsyncEnumerable<ResourceTypeInformationDto> entries) + { + await foreach (var entry in entries) + { + var resourceTypeGraphName = UriHelper.TryCombineUri(RdfUris.CoscineResourceTypes, entry.Id) + ?? throw new Exception("Could not combine resource types prefix with resource type ID"); + var response = _adminApi.GetMetadataGraph(resourceTypeGraphName.AbsoluteUri, RdfFormat.TextTurtle); + + var graph = new Graph() + { + BaseUri = resourceTypeGraphName + }; + + graph.LoadFromString(response.Data.Content, new TurtleParser()); + + // check if a triple with a dcat:DataService already exists in the resourcetype graph + var getTriplesDcatDataService = graph.GetTriplesWithObject(RdfUris.DcatDataServiceClass); + + if (!getTriplesDcatDataService.Any()) + { + _deployer.AssertToGraphUriNode(graph, resourceTypeGraphName, RdfUris.A, RdfUris.DcatDataServiceClass); + Console.WriteLine($"For resource type '{entry.SpecificType}' will migrate triple '{graph.BaseUri} {RdfUris.A} {RdfUris.DcatDataServiceClass}'. "); + } + else + { + Console.WriteLine($"For resource type '{entry.SpecificType}' will NOT migrate triple '{graph.BaseUri} {RdfUris.A} {RdfUris.DcatDataServiceClass}'. "); + } + + // check if a triple with dcterms:title '{entry.DisplayName}' already exists in the role graph + var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(RdfUris.DcTermsTitle); + + if (!getTriplesDctermsTitle.Any()) + { + _deployer.AssertToGraphLiteralNode(graph, resourceTypeGraphName, RdfUris.DcTermsTitle, entry.SpecificType); + Console.WriteLine($"For resource type '{entry.SpecificType}' will migrate triple '{graph.BaseUri} {RdfUris.DcTermsTitle} {entry.SpecificType}'. "); + } + else + { + Console.WriteLine($"For resource type '{entry.SpecificType}' will NOT migrate triple '{graph.BaseUri} {RdfUris.DcTermsTitle} {entry.SpecificType}'. "); + } + + + // check if a triple with dcterms:title '{entry.DisplayName}' already exists in the role graph + var getTriplesDctermsAlternative = graph.GetTriplesWithPredicate(RdfUris.DcTermsAlternative); + + if (!getTriplesDctermsAlternative.Any()) + { + _deployer.AssertToGraphLiteralNode(graph, resourceTypeGraphName, RdfUris.DcTermsAlternative, entry.GeneralType); + Console.WriteLine($"For resource type '{entry.SpecificType}' will migrate triple '{graph.BaseUri} {RdfUris.DcTermsAlternative} {entry.GeneralType}'. "); + } + else + { + Console.WriteLine($"For resource type '{entry.SpecificType}' will NOT migrate triple '{graph.BaseUri} {RdfUris.DcTermsAlternative} {entry.GeneralType}'. "); + } + + if (!getTriplesDcatDataService.Any() || !getTriplesDctermsTitle.Any()) + { + yield return graph; + } + } + } +} diff --git a/src/GraphDeployer/Implementations/RoleStructuralData.cs b/src/GraphDeployer/Implementations/RoleStructuralData.cs new file mode 100644 index 0000000..a9e2734 --- /dev/null +++ b/src/GraphDeployer/Implementations/RoleStructuralData.cs @@ -0,0 +1,77 @@ +using Coscine.ApiClient; +using Coscine.ApiClient.Core.Api; +using Coscine.ApiClient.Core.Model; +using VDS.RDF; +using VDS.RDF.Parsing; + +namespace Coscine.GraphDeployer; + +/// <summary> +/// Class responsible for converting role data into linked data graphs. +/// It retrieves role 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 RoleStructuralData +{ + private readonly AdminApi _adminApi; + private readonly Deployer _deployer; + public RoleStructuralData(AdminApi adminApi, Deployer deployer) + { + _adminApi = adminApi; + _deployer = deployer; + + } + public IAsyncEnumerable<RoleDto> GetAll() + { + var roleApi = new RoleApi(apiClientConfig); + return PaginationHelper.GetAllAsync<RoleDtoPagedResponse, RoleDto>( + (currentPage) => roleApi.GetRolesAsync(pageNumber: currentPage)); + } + public async IAsyncEnumerable<IGraph> ConvertToLinkedDataAsync(IAsyncEnumerable<RoleDto> entries) + { + await foreach (var entry in entries) + { + var roleGraphName = UriHelper.TryCombineUri(RdfUris.CoscineRoles, entry.Id) + ?? throw new Exception("Could not combine role prefix with role ID"); + var response = await _adminApi.GetMetadataGraphAsync(roleGraphName.AbsoluteUri, RdfFormat.TextTurtle); + + var graph = new Graph() + { + BaseUri = roleGraphName + }; + + graph.LoadFromString(response.Data.Content, new TurtleParser()); + + // check if a triple with a org:role already exists in the role graph + var getTriplesOrgRole = graph.GetTriplesWithObject(RdfUris.OrgRoleClass); + + if (!getTriplesOrgRole.Any()) + { + _deployer.AssertToGraphUriNode(graph, roleGraphName, RdfUris.A, RdfUris.OrgRoleClass); + Console.WriteLine($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {RdfUris.A} {RdfUris.OrgRoleClass}'. "); + } + else + { + Console.WriteLine($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {RdfUris.A} {RdfUris.OrgRoleClass}'. "); + } + + // check if a triple with dcterms:title '{entry.DisplayName}' already exists in the role graph + var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(RdfUris.DcTermsTitle); + + if (!getTriplesDctermsTitle.Any()) + { + _deployer.AssertToGraphLiteralNode(graph, roleGraphName, RdfUris.DcTermsTitle, entry.DisplayName); + Console.WriteLine($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {RdfUris.DcTermsTitle} {entry.DisplayName}'. "); + } + else + { + Console.WriteLine($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {RdfUris.DcTermsTitle} {entry.DisplayName}'. "); + } + if (!getTriplesOrgRole.Any() || !getTriplesDctermsTitle.Any()) + { + yield return graph; + } + } + } + +} diff --git a/src/GraphDeployer/Models/ConfigurationModels/SQL2LinkedConfiguration.cs b/src/GraphDeployer/Models/ConfigurationModels/SQL2LinkedConfiguration.cs new file mode 100644 index 0000000..a7e30c6 --- /dev/null +++ b/src/GraphDeployer/Models/ConfigurationModels/SQL2LinkedConfiguration.cs @@ -0,0 +1,17 @@ +namespace Coscine.GraphDeployer.Models.ConfigurationModels; + +/// <summary> +/// Represents the configuration settings used in the application. +/// </summary> +public class SQL2LinkedConfiguration +{ + /// <summary> + /// The section name in the configuration file. + /// </summary> + public static readonly string Section = "SQL2LinkedConfiguration"; + + /// <summary> + /// Value indicating whether SQL2Linked is enabled. + /// </summary> + public bool IsEnabled { get; init; } +} diff --git a/src/GraphDeployer/Utils/RdfUris.cs b/src/GraphDeployer/Utils/RdfUris.cs new file mode 100644 index 0000000..2eedac6 --- /dev/null +++ b/src/GraphDeployer/Utils/RdfUris.cs @@ -0,0 +1,234 @@ +// Ignore Spelling: Foaf Dcat Dcterms Ebocore Fdp Ldp Xsd + +/// ------------------ +/// TAKEN FROM THE API +/// ------------------ + +namespace Coscine.GraphDeployer; + +/// <summary> +/// Contains URIs relevant to RDF (Resource Description Framework) and related schemas/ontologies. +/// </summary> +public static class RdfUris +{ + // ACL + public static readonly Uri AclPrefix = new("http://www.w3.org/ns/auth/acl#"); + + public static readonly Uri AclAccessTo = new("http://www.w3.org/ns/auth/acl#accessTo"); + public static readonly Uri AclAgentGroup = new("http://www.w3.org/ns/auth/acl#agentGroup"); + public static readonly Uri AclDefault = new("http://www.w3.org/ns/auth/acl#default"); + public static readonly Uri AclMode = new("http://www.w3.org/ns/auth/acl#mode"); + + public static readonly Uri AclAuthorizationClass = new("http://www.w3.org/ns/auth/acl#Authorization"); + public static readonly Uri AclReadClass = new("http://www.w3.org/ns/auth/acl#Read"); + public static readonly Uri AclWriteClass = new("http://www.w3.org/ns/auth/acl#Write"); + + // Coscine + public static readonly Uri CoscinePrefix = new("https://purl.org/coscine/"); + + public static readonly Uri CoscineApplicationProfile = new("https://purl.org/coscine/ap/"); + public static readonly Uri CoscineFixedValue = new("https://purl.org/coscine/fixedValue"); + public static readonly Uri CoscineMetadataExtractionEntity = new("https://purl.org/coscine/terms/metatadataextraction#Entity"); + public static readonly Uri CoscineMetadataExtractionExtracted = new("https://purl.org/coscine/terms/metatadataextraction#extracted"); + public static readonly Uri CoscineMetadataExtractionVersion = new("https://purl.org/coscine/terms/metatadataextraction#version"); + public static readonly Uri CoscineMetadataTrackerIsVariantOf = new("https://purl.org/coscine/terms/metadatatracker#isVariantOf"); + public static readonly Uri CoscineMetadataTrackerSimilarity = new("https://purl.org/coscine/terms/metadatatracker#similarity"); + public static readonly Uri CoscineMetadataTrackerSimilarityToLastVersion = new("https://purl.org/coscine/terms/metadatatracker#similarityToLastVersion"); + public static readonly Uri CoscineMetadataTrackerHasVariant = new("https://purl.org/coscine/terms/metadatatracker#hasVariant"); + public static readonly Uri CoscineMetadataTrackerVariant = new("https://purl.org/coscine/terms/metadatatracker#Variant"); + public static readonly Uri CoscineProjects = new("https://purl.org/coscine/projects/"); + public static readonly Uri CoscineResourceTypes = new("https://purl.org/coscine/resourcetypes/"); + public static readonly Uri CoscineResources = new("https://purl.org/coscine/resources/"); + public static readonly Uri CoscineRoles = new("https://purl.org/coscine/roles/"); + public static readonly Uri CoscineUsers = new("https://purl.org/coscine/users/"); + + [Obsolete($"Beware the side-effects before changing! Use {nameof(CoscineUsers)} instead.")] + public static readonly Uri CoscineUserLegacy = new("https://coscine.rwth-aachen.de/u/"); + + // Coscine Entities + public static readonly Uri CoscineEntitiesGraph = new("https://purl.org/coscine/entities/graph#"); + public static readonly Uri CoscineEntitiesGraphDeployed = new("https://purl.org/coscine/entities/graph#deployed"); + + // Coscine Terms + public static readonly Uri CoscineTermsPrefix = new("https://purl.org/coscine/terms/"); + + public static readonly Uri CoscineTermsLinkedBody = new("https://purl.org/coscine/terms/linked#body"); + public static readonly Uri CoscineTermsMetadataTrackerAgent = new("https://purl.org/coscine/terms/metadatatracker#Agent"); + public static readonly Uri CoscineTermsProject = new("https://purl.org/coscine/terms/project#"); + public static readonly Uri CoscineTermsProjectDeleted = new("https://purl.org/coscine/terms/project#deleted"); + public static readonly Uri CoscineTermsProjectSlug = new("https://purl.org/coscine/terms/project#slug"); + public static readonly Uri CoscineTermsProjectVisibility = new("https://purl.org/coscine/terms/project#visibility"); + public static readonly Uri CoscineTermsResource = new("https://purl.org/coscine/terms/resource#"); + public static readonly Uri CoscineTermsResourceArchived = new("https://purl.org/coscine/terms/resource#archived"); + public static readonly Uri CoscineTermsResourceDeleted = new("https://purl.org/coscine/terms/resource#deleted"); + public static readonly Uri CoscineTermsResourceFixedValues = new("https://purl.org/coscine/terms/resource#fixedValues"); + public static readonly Uri CoscineTermsResourceVisibility = new("https://purl.org/coscine/terms/resource#visibility"); + public static readonly Uri CoscineTermsTypes = new("https://purl.org/coscine/terms/types#"); + public static readonly Uri CoscineTermsMetadataExtractionVersion = new("https://purl.org/coscine/terms/metatadataextraction#version"); + public static readonly Uri CoscineTermsUserAgent = new("https://purl.org/coscine/terms/user#Agent"); + public static readonly Uri CoscineTermsVisibility = new("https://purl.org/coscine/terms/visibility#"); + public static readonly Uri CoscineTermsVisibilityPublic = new("https://purl.org/coscine/terms/visibility#public"); + public static readonly Uri CoscineTermsVisibilityProjectMember = new("https://purl.org/coscine/terms/visibility#projectMember"); + public static readonly Uri CoscineTermsRole = new("https://purl.org/coscine/terms/role#"); + public static readonly Uri CoscineTermsOrganizations = new("https://purl.org/coscine/terms/organization#"); + public static readonly Uri CoscineTermsDeployedVersion = new("https://purl.org/coscine/terms/deployed#version"); + + // CSMD + public static readonly Uri CsmdPrefix = new("http://www.purl.org/net/CSMD/4.0#"); + + // DCAT + public static readonly Uri DcatPrefix = new("http://www.w3.org/ns/dcat#"); + + public static readonly Uri DcatCatalog = new("http://www.w3.org/ns/dcat#catalog"); + public static readonly Uri DcatDataset = new("http://www.w3.org/ns/dcat#dataset"); + public static readonly Uri DcatDistribution = new("http://www.w3.org/ns/dcat#distribution"); + public static readonly Uri DcatService = new("http://www.w3.org/ns/dcat#service"); + + public static readonly Uri DcatCatalogClass = new("http://www.w3.org/ns/dcat#Catalog"); + public static readonly Uri DcatDataServiceClass = new("http://www.w3.org/ns/dcat#DataService"); + public static readonly Uri DcatDatasetClass = new("http://www.w3.org/ns/dcat#Dataset"); + + // DCMI Type + public static readonly Uri DcmiTypePrefix = new("http://purl.org/dc/dcmitype/"); + + // DC + public static readonly Uri DcPrefix = new("http://purl.org/dc/elements/1.1/"); + + // DC Terms + public static readonly Uri DcTermsPrefix = new("http://purl.org/dc/terms/"); + + public static readonly Uri DcTermsAlternative = new("http://purl.org/dc/terms/alternative"); + public static readonly Uri DcTermsConformsTo = new("http://purl.org/dc/terms/conformsTo"); + public static readonly Uri DcTermsCreator = new("http://purl.org/dc/terms/creator"); + public static readonly Uri DcTermsCreated = new("http://purl.org/dc/terms/created"); + public static readonly Uri DcTermsDescription = new("http://purl.org/dc/terms/description"); + public static readonly Uri DcTermsEndDate = new("http://purl.org/dc/terms/endDate"); + public static readonly Uri DcTermsIdentifier = new("http://purl.org/dc/terms/identifier"); + public static readonly Uri DcTermsIsPartOf = new("http://purl.org/dc/terms/isPartOf"); + public static readonly Uri DcTermsLicense = new("http://purl.org/dc/terms/license"); + public static readonly Uri DcTermsModified = new("http://purl.org/dc/terms/modified"); + public static readonly Uri DcTermsRights = new("http://purl.org/dc/terms/rights"); + public static readonly Uri DcTermsRightsHolder = new("http://purl.org/dc/terms/rightsHolder"); + public static readonly Uri DcTermsStartDate = new("http://purl.org/dc/terms/startDate"); + public static readonly Uri DcTermsSubject = new("http://purl.org/dc/terms/subject"); + public static readonly Uri DcTermsTitle = new("http://purl.org/dc/terms/title"); + + // EBUCORE + public static readonly Uri EbocorePrefix = new("http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#"); + + public static readonly Uri EbocoreHash = new("http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#hash"); + public static readonly Uri EbocoreHashFunction = new("http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#hashFunction"); + public static readonly Uri EbocoreHashType = new("http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#hashType"); + public static readonly Uri EbocoreHashValue = new("http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#hashValue"); + + // FDP + public static readonly Uri FdpPrefix = new("http://purl.org/fdp/fdp-o#"); + + public static readonly Uri FdpHasMetadata = new("http://purl.org/fdp/fdp-o#hasMetadata"); + public static readonly Uri FdpIsMetadataOf = new("http://purl.org/fdp/fdp-o#isMetadataOf"); + + public static readonly Uri FdpMetadataServiceClass = new("http://purl.org/fdp/fdp-o#MetadataService"); + + // FOAF + public static readonly Uri FoafPrefix = new("http://xmlns.com/foaf/0.1/"); + + public static readonly Uri FoafHomepage = new("http://xmlns.com/foaf/0.1/homepage"); + public static readonly Uri FoafName = new("http://xmlns.com/foaf/0.1/name"); + + public static readonly Uri FoafPersonClass = new("http://xmlns.com/foaf/0.1/Person"); + + // Handle + public static readonly Uri HandlePrefix = new("https://hdl.handle.net/"); + + // LDP + public static readonly Uri LdpPrefix = new("http://www.w3.org/ns/ldp#"); + + public static readonly Uri LdpDescribedBy = new("http://www.w3.org/ns/ldp#describedBy"); + + public static readonly Uri LdpBasicContainerClass = new("http://www.w3.org/ns/ldp#BasicContainer"); + public static readonly Uri LdpNonRDFSourceClass = new("http://www.w3.org/ns/ldp#NonRDFSource"); + public static readonly Uri LdpRDFSourceClass = new("http://www.w3.org/ns/ldp#RDFSource"); + + // ORG + public static readonly Uri OrgPrefix = new("http://www.w3.org/ns/org#"); + + public static readonly Uri OrgMember = new("http://www.w3.org/ns/org#member"); + public static readonly Uri OrgOrganization = new("http://www.w3.org/ns/org#organization"); + public static readonly Uri OrgRole = new("http://www.w3.org/ns/org#role"); + + public static readonly Uri OrgMembershipClass = new("http://www.w3.org/ns/org#Membership"); + public static readonly Uri OrgOrganizationalCollaborationClass = new("http://www.w3.org/ns/org#OrganizationalCollaboration"); + public static readonly Uri OrgRoleClass = new("http://www.w3.org/ns/org#Role"); + + // OWL + public static readonly Uri OwlPrefix = new("http://www.w3.org/2002/07/owl#"); + + public static readonly Uri OwlImports = new("http://www.w3.org/2002/07/owl#imports"); + + // PIM + public static readonly Uri PimPrefix = new("http://www.w3.org/ns/pim/space#"); + + public static readonly Uri PimStorageClass = new("http://www.w3.org/ns/pim/space#Storage"); + + // PROV + public static readonly Uri ProvPrefix = new("http://www.w3.org/ns/prov#"); + + public static readonly Uri ProvEntityClass = new("http://www.w3.org/ns/prov#Entity"); + + public static readonly Uri ProvGeneratedAtTime = new("http://www.w3.org/ns/prov#generatedAtTime"); + public static readonly Uri ProvWasInvalidatedBy = new("http://www.w3.org/ns/prov#wasInvalidatedBy"); + public static readonly Uri ProvWasRevisionOf = new("http://www.w3.org/ns/prov#wasRevisionOf"); + + // RDF + public static readonly Uri RdfUrlPrefix = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + + public static readonly Uri A = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + + // RDFS + public static readonly Uri RdfsUrlPrefix = new("http://www.w3.org/2000/01/rdf-schema#"); + + public static readonly Uri SubClassOf = new("http://www.w3.org/2000/01/rdf-schema#subClassOf"); + + // ROR IDs + /// <summary> + /// Represents the RWTH Aachen's ROR (Research Organization Registry) ID. + /// </summary> + public static readonly Uri RwthRorId = new("https://ror.org/04xfq0f34"); + + // SCHEMA + public static readonly Uri SchemaPrefix = new("http://schema.org/"); + + public static readonly Uri SchemaFunding = new("http://schema.org/funding"); + + // SHACL + public static readonly Uri ShaclPrefix = new("http://www.w3.org/ns/shacl#"); + + public static readonly Uri ShaclDatatype = new("http://www.w3.org/ns/shacl#datatype"); + public static readonly Uri ShaclDeactivated = new("http://www.w3.org/ns/shacl#deactivated"); + public static readonly Uri ShaclPath = new("http://www.w3.org/ns/shacl#path"); + public static readonly Uri ShaclProperty = new("http://www.w3.org/ns/shacl#property"); + public static readonly Uri ShaclTargetClass = new("http://www.w3.org/ns/shacl#targetClass"); + public static readonly Uri Class = new("http://www.w3.org/ns/shacl#class"); + + // Trellis + public static readonly Uri TrellisPrefix = new("http://www.trellisldp.org/ns/trellis#"); + + public static readonly Uri TrellisGraph = new("http://www.trellisldp.org/ns/trellis#PreferServerManaged"); + + // Vcard + public static readonly Uri VcardPrefix = new("http://www.w3.org/2006/vcard/ns#"); + + public static readonly Uri VcardHasMember = new("http://www.w3.org/2006/vcard/ns#hasMember"); + + public static readonly Uri VcardGroupClass = new("http://www.w3.org/2006/vcard/ns#Group"); + + // XSD + public static readonly Uri XsdPrefix = new("http://www.w3.org/2001/XMLSchema#"); + + public static readonly Uri XsdDateTime = new("http://www.w3.org/2001/XMLSchema#dateTime"); + public static readonly Uri XsdDecimal = new("http://www.w3.org/2001/XMLSchema#decimal"); + public static readonly Uri XsdDouble = new("http://www.w3.org/2001/XMLSchema#double"); + public static readonly Uri XsdDuration = new("http://www.w3.org/2001/XMLSchema#duration"); + public static readonly Uri XsdBoolean = new("http://www.w3.org/2001/XMLSchema#boolean"); + public static readonly Uri XsdHexBinary = new("http://www.w3.org/2001/XMLSchema#hexBinary"); +} \ No newline at end of file diff --git a/src/GraphDeployer/Utils/UriHelper.cs b/src/GraphDeployer/Utils/UriHelper.cs new file mode 100644 index 0000000..3c4bc52 --- /dev/null +++ b/src/GraphDeployer/Utils/UriHelper.cs @@ -0,0 +1,52 @@ +namespace Coscine.GraphDeployer; + +public class UriHelper +{ + /// <summary> + /// + /// </summary> + /// <param name="baseUri"></param> + /// <param name="relativePath"></param> + /// <returns></returns> + public static Uri? TryCombinePath(Uri baseUri, string relativePath) + { + Uri.TryCreate(baseUri, relativePath + "/", out Uri? result); + return result; + } + + /// <summary> + /// + /// </summary> + /// <param name="baseUri"></param> + /// <param name="relativePath"></param> + /// <returns></returns> + public static Uri? TryCombinePath(Uri baseUri, Guid relativePath) + { + Uri.TryCreate(baseUri, relativePath.ToString() + "/", out Uri? result); + return result; + } + + /// <summary> + /// + /// </summary> + /// <param name="baseUri"></param> + /// <param name="relativePath"></param> + /// <returns></returns> + public static Uri? TryCombineUri(Uri baseUri, string relativePath) + { + Uri.TryCreate(baseUri, relativePath, out Uri? result); + return result; + } + + /// <summary> + /// + /// </summary> + /// <param name="baseUri"></param> + /// <param name="relativePath"></param> + /// <returns></returns> + public static Uri? TryCombineUri(Uri baseUri, Guid relativePath) + { + Uri.TryCreate(baseUri, relativePath.ToString(), out Uri? result); + return result; + } +} \ No newline at end of file -- GitLab