diff --git a/src/SQL2Linked/Implementations/ResourceStructuralData.cs b/src/SQL2Linked/Implementations/ResourceStructuralData.cs index 7e1b030b7e5a9f4db5c23cc2599a1cae1de6aa0d..6d2a73a6c139a378af2bf1fa22f87e12508a6a32 100644 --- a/src/SQL2Linked/Implementations/ResourceStructuralData.cs +++ b/src/SQL2Linked/Implementations/ResourceStructuralData.cs @@ -1,15 +1,153 @@ using Coscine.Database.DataModel; using Coscine.Database.Models; using VDS.RDF; +using VDS.RDF.Query; namespace SQL2Linked.Implementations { public class ResourceStructuralData : StructuralData<Resource, ResourceModel> { + public readonly Uri org = new("http://www.w3.org/ns/org#"); + public readonly Uri dcat = new("http://www.w3.org/ns/dcat#"); + public readonly Uri dcterms = new("http://purl.org/dc/terms/"); + public readonly Uri acl = new("http://www.w3.org/ns/auth/acl#"); + public readonly Uri foaf = new("http://xmlns.com/foaf/0.1/"); + public readonly Uri pim = new("http://www.w3.org/ns/pim/space#"); + public readonly Uri rdf = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + public readonly Uri cosc = new("https://purl.org/coscine/"); + private VisibilityModel VisibilityModel = new VisibilityModel(); + private ProjectResourceModel ProjectResourceModel = new ProjectResourceModel(); + private LicenseModel LicenseModel = new LicenseModel(); + public override IEnumerable<IGraph> ConvertToLinkedData(IEnumerable<Resource> entries) { - // ToDo: Implement - throw new NotImplementedException(); + IEnumerable<Visibility> visibilities = VisibilityModel.GetAll(); + IEnumerable<ProjectResource> projectResources = ProjectResourceModel.GetAll(); + IEnumerable<License> licenses = LicenseModel.GetAll(); + + var graphs = new List<IGraph>(); + string resourceUrlPrefix = "https://hdl.handle.net/" + Prefix; + + foreach (var entry in entries) + { + var resourceGraphName = $"{resourceUrlPrefix}/{entry.Id}"; + + var graph = new Graph(); + graph.BaseUri = new Uri(resourceGraphName); + + AssertToGraphUriNode(graph, resourceGraphName, rdf + "type", dcat + "Catalog"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {rdf}type {dcat}Catalog'. "); + + AssertToGraphUriNode(graph, resourceGraphName, rdf + "type", pim + "Storage"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {rdf}type {pim}Storage'. "); + + AssertToGraphUriNode(graph, resourceGraphName, dcat + "service", cosc + $"resourcetype/{entry.TypeId}"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcat}service {cosc}resourcetype/{entry.TypeId}'. "); + + AssertToGraphLiteralNode(graph, resourceGraphName, dcterms + "title", entry.ResourceName); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}title {entry.ResourceName}'. "); + + AssertToGraphLiteralNode(graph, resourceGraphName, dcterms + "alternative", entry.DisplayName); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}alternative {entry.DisplayName}'. "); + + foreach (var visibility in visibilities) + { + if (entry.VisibilityId == visibility.Id && visibility.DisplayName.Contains("Public")) + { + AssertToGraphUriNode(graph, resourceGraphName, cosc + "terms/resource#visibility", cosc + $"terms/visibility#public"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {cosc}terms/resource#visibility {cosc}terms/visibility#public'. "); + break; + } + else if (entry.VisibilityId == visibility.Id && visibility.DisplayName.Contains("Project Members")) + { + AssertToGraphUriNode(graph, resourceGraphName, cosc + "terms/resource#visibility", cosc + $"terms/visibility#projectMember"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {cosc}terms/resource#visibility {cosc}terms/visibility#projectMember'. "); + break; + } + } + + foreach (var license in licenses) + { + if (entry.LicenseId == license.Id) + { + AssertToGraphLiteralNode(graph, resourceGraphName, dcterms + "license", license.DisplayName); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}license {license.DisplayName}'. "); + break; + } + } + + if (!string.IsNullOrWhiteSpace(entry.Keywords)) + { + var listKeywords = entry.Keywords.Split(';').ToList(); + foreach (var keyword in listKeywords) + { + AssertToGraphLiteralNode(graph, resourceGraphName, dcterms + "subject", keyword); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}subject {keyword}'. "); + } + } + + AssertToGraphLiteralNode(graph, resourceGraphName, dcterms + "rights", entry.UsageRights); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}rights {entry.UsageRights}'. "); + + AssertToGraphLiteralNode(graph, resourceGraphName, dcterms + "description", entry.Description); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}description {entry.Description}'. "); + + AssertToGraphUriNode(graph, resourceGraphName, dcterms + "conformsTo", entry.ApplicationProfile); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}conformsTo {entry.ApplicationProfile}'. "); + + AssertToGraphLiteralNode(graph, resourceGraphName, cosc + "terms/resource#fixedValues", entry.FixedValues); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {cosc}terms/resource#fixedValues {entry.FixedValues}'. "); + + AssertToGraphUriNode(graph, resourceGraphName, dcterms + "creator", cosc + $"users/{entry.Creator}"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcterms}creator {cosc}users/{entry.Creator}'. "); + + AssertToGraphLiteralNode(graph, resourceGraphName, cosc + "terms/resource#archived", entry.Archived.ToString(), new Uri("http://www.w3.org/2001/XMLSchema#boolean")); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {cosc}terms/resource#archived {entry.Archived}'. "); + + AssertToGraphUriNode(graph, resourceGraphName, foaf + "homepage", resourceGraphName); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {foaf}homepage {resourceGraphName}'. "); + + SparqlParameterizedString cmdString = new SparqlParameterizedString + { + CommandText = "SELECT DISTINCT ?g " + + "WHERE {" + + "GRAPH ?g { ?s ?p ?o } . " + + "FILTER(STRSTARTS(STR(?s), \"" + resourceGraphName + "@\"))" + + "}" + }; + + var resultSet = QueryEndpoint.QueryWithResultSet(cmdString.ToString()); + + foreach (var result in resultSet) + { + AssertToGraphUriNode(graph, resourceGraphName, dcat + "catalog", result[0].ToString()); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{resourceGraphName} {dcat}catalog {result[0].ToString()}'. "); + } + + foreach (var projectResource in projectResources) + { + if (entry.Id == projectResource.ResourceId) + { + var blankNode = graph.CreateBlankNode(); + + AssertToGraphBlankAndUriNode(graph, blankNode, rdf + "type", acl + "Authorization"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{blankNode} {rdf}type {acl}Authorization'. "); + + AssertToGraphBlankAndUriNode(graph, blankNode, acl + "agentGroup", $"{resourceUrlPrefix}/{projectResource.ProjectId}"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{blankNode} {acl}agentGroup {resourceUrlPrefix}/{projectResource.ProjectId}'. "); + + AssertToGraphBlankAndUriNode(graph, blankNode, acl + "accessTo", resourceGraphName); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{blankNode} {acl}accessTo {resourceGraphName}'. "); + + AssertToGraphBlankAndUriNode(graph, blankNode, acl + "mode", acl + "Control"); + Console.WriteLine($"For resource '{entry.DisplayName}' will migrate triple '{blankNode} {acl}accessTo {acl}Control'. "); + } + } + + graphs.Add(graph); + } + + return graphs; } } -} \ No newline at end of file +} diff --git a/src/SQL2Linked/Implementations/ResourceTypeStructuralData.cs b/src/SQL2Linked/Implementations/ResourceTypeStructuralData.cs index b36ec5e84d262268b174956ba77807a0d9c0fd95..d5fc3b2497a9f7a3ddc1c0e23f30faecc275cb27 100644 --- a/src/SQL2Linked/Implementations/ResourceTypeStructuralData.cs +++ b/src/SQL2Linked/Implementations/ResourceTypeStructuralData.cs @@ -7,10 +7,9 @@ namespace SQL2Linked.Implementations public class ResourceTypeStructuralData : StructuralData<ResourceType, ResourceTypeModel> { public readonly string ResourceTypeUrlPrefix = "https://purl.org/coscine/resourcetype"; - public readonly Uri RdfType = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - public readonly Uri DcatDataService = new ("http://www.w3.org/ns/dcat#DataService"); - public readonly Uri dctermsTitle = new("http://purl.org/dc/terms/title"); - + public readonly Uri rdf = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + public readonly Uri dcat = new("http://www.w3.org/ns/dcat#"); + public readonly Uri dcterms = new("http://purl.org/dc/terms/"); public override IEnumerable<IGraph> ConvertToLinkedData(IEnumerable<ResourceType> entries) { @@ -22,43 +21,29 @@ namespace SQL2Linked.Implementations var graph = RdfStoreConnector.GetGraph(resourceTypeGraphName); // check if a triple with a dcat:DataService already exists in the resourcetype graph - var getTriplesDcatDataService = graph.GetTriplesWithObject(DcatDataService); + var getTriplesDcatDataService = graph.GetTriplesWithObject(new Uri(dcat + "DataService")); if (!getTriplesDcatDataService.Any()) { - graph.Assert( - new Triple( - graph.CreateUriNode(new Uri(resourceTypeGraphName)), - graph.CreateUriNode(RdfType), - graph.CreateUriNode(DcatDataService) - ) - ); - - Console.WriteLine($"For resource type '{entry.DisplayName}' will migrate triple '{graph.BaseUri}' a dcat:DataService. "); + AssertToGraphUriNode(graph, resourceTypeGraphName, rdf + "type", dcat + "DataService"); + Console.WriteLine($"For resource type '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {rdf}type {dcat}DataService'. "); } else { - Console.WriteLine($"For resource type '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri}' a dcat:DataService. "); + Console.WriteLine($"For resource type '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {rdf}type {dcat}DataService'. "); } // check if a triple with dcterms:title '{entry.DisplayName}' already exists in the role graph - var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(dctermsTitle); + var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(new Uri(dcterms + "Title")); if (!getTriplesDctermsTitle.Any()) { - graph.Assert( - new Triple( - graph.CreateUriNode(new Uri(resourceTypeGraphName)), - graph.CreateUriNode(dctermsTitle), - graph.CreateLiteralNode(entry.DisplayName) - ) - ); - - Console.WriteLine($"For resource type '{entry.DisplayName}' will migrate triple '{graph.BaseUri}' dcterms:title '{entry.DisplayName}'. "); + AssertToGraphLiteralNode(graph, resourceTypeGraphName, dcterms + "title", entry.DisplayName); + Console.WriteLine($"For resource type '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {dcterms}title {entry.DisplayName}'. "); } else { - Console.WriteLine($"For resource type '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri}' dcterms:title '{entry.DisplayName}'. "); + Console.WriteLine($"For resource type '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {dcterms}title {entry.DisplayName}'. "); } if (!getTriplesDcatDataService.Any() || !getTriplesDctermsTitle.Any()) { diff --git a/src/SQL2Linked/Implementations/RoleStructuralData.cs b/src/SQL2Linked/Implementations/RoleStructuralData.cs index 2d9ac5bdf265aaeb113b3f040a88bc0f5409130e..04b3176b724bb25d132cb20d9b7ad4e367af14d7 100644 --- a/src/SQL2Linked/Implementations/RoleStructuralData.cs +++ b/src/SQL2Linked/Implementations/RoleStructuralData.cs @@ -7,9 +7,10 @@ namespace SQL2Linked.Implementations public class RoleStructuralData : StructuralData<Role, RoleModel> { public readonly string RoleUrlPrefix = "https://purl.org/coscine/roles"; - public readonly Uri RdfType = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - public readonly Uri orgRole = new("http://www.w3.org/ns/org#Role"); - public readonly Uri dctermsTitle = new("http://purl.org/dc/terms/title"); + public readonly Uri cosc = new("https://purl.org/coscine/"); + public readonly Uri rdf = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + public readonly Uri org = new("http://www.w3.org/ns/org#"); + public readonly Uri dcterms = new("http://purl.org/dc/terms/"); public override IEnumerable<IGraph> ConvertToLinkedData(IEnumerable<Role> entries) { @@ -21,43 +22,29 @@ namespace SQL2Linked.Implementations var graph = RdfStoreConnector.GetGraph(roleGraphName); // check if a triple with a org:role already exists in the role graph - var getTriplesOrgRole = graph.GetTriplesWithObject(orgRole); + var getTriplesOrgRole = graph.GetTriplesWithObject(new Uri(org + "Role")); if (!getTriplesOrgRole.Any()) { - graph.Assert( - new Triple( - graph.CreateUriNode(new Uri(roleGraphName)), - graph.CreateUriNode(RdfType), - graph.CreateUriNode(orgRole) - ) - ); - - Console.WriteLine($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri}' a org:Role. "); + AssertToGraphUriNode(graph, roleGraphName, rdf + "type", org + "Role"); + Console.WriteLine($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {rdf}type {org}Role'. "); } else { - Console.WriteLine($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri}' a org:Role. "); + Console.WriteLine($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {rdf}type {org}Role'. "); } // check if a triple with dcterms:title '{entry.DisplayName}' already exists in the role graph - var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(dctermsTitle); + var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(new Uri(dcterms + "title")); if (!getTriplesDctermsTitle.Any()) { - graph.Assert( - new Triple( - graph.CreateUriNode(new Uri(roleGraphName)), - graph.CreateUriNode(dctermsTitle), - graph.CreateLiteralNode(entry.DisplayName) - ) - ); - - Console.WriteLine($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri}' dcterms:title '{entry.DisplayName}'. "); + AssertToGraphLiteralNode(graph, roleGraphName, dcterms + "title", entry.DisplayName); + Console.WriteLine($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {dcterms}title {entry.DisplayName}'. "); } else { - Console.WriteLine($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri}' dcterms:title '{entry.DisplayName}'. "); + Console.WriteLine($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {dcterms}title {entry.DisplayName}'. "); } if (!getTriplesOrgRole.Any() || !getTriplesDctermsTitle.Any()) { diff --git a/src/SQL2Linked/Implementations/UserStructuralData.cs b/src/SQL2Linked/Implementations/UserStructuralData.cs index 1433f219d9a508b3b219e3982d117b313589eeb9..29f811134e4aca5bf73595e276555698fa2ed524 100644 --- a/src/SQL2Linked/Implementations/UserStructuralData.cs +++ b/src/SQL2Linked/Implementations/UserStructuralData.cs @@ -8,8 +8,8 @@ namespace SQL2Linked.Implementations public class UserStructuralData : StructuralData<User, UserModel> { public readonly string UserUrlPrefix = "https://purl.org/coscine/users"; - public readonly Uri RdfType = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - public readonly Uri FoafPerson = new("http://xmlns.com/foaf/0.1/Person"); + public readonly Uri rdf = new("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + public readonly Uri foaf = new("http://xmlns.com/foaf/0.1/"); public override IEnumerable<IGraph> ConvertToLinkedData(IEnumerable<User> entries) { @@ -21,17 +21,16 @@ namespace SQL2Linked.Implementations var graph = RdfStoreConnector.GetGraph(userGraphName); // check if a triple with a foaf:Person already exists in the user graph - var getTriples = graph.GetTriplesWithObject(FoafPerson); + var getTriples = graph.GetTriplesWithObject(new Uri(foaf + "Person")); + // check if the current display name is already applied in the user graph + var getTriplesName = graph.GetTriplesWithPredicate(new Uri(foaf + "name")); - if (!getTriples.Any()) + if (!getTriples.Any() || !getTriplesName.Any((triple) => triple.Object.ToString() == entry.DisplayName)) { - graph.Assert( - new Triple( - graph.CreateUriNode(new Uri(userGraphName)), - graph.CreateUriNode(RdfType), - graph.CreateUriNode(FoafPerson) - ) - ); + AssertToGraphUriNode(graph, userGraphName, rdf + "type", foaf + "Person"); + + graph.Retract(getTriplesName); + AssertToGraphLiteralNode(graph, userGraphName, foaf + "name", entry.DisplayName); graphs.Add(graph); @@ -40,7 +39,7 @@ namespace SQL2Linked.Implementations else { Console.WriteLine($"Will NOT migrate user '{entry.DisplayName}' with id '{entry.Id}'."); - } + } } return graphs; } diff --git a/src/SQL2Linked/StructuralData.cs b/src/SQL2Linked/StructuralData.cs index 78d70e490e2d9156cc7d5989e86bca52103a5ea7..4d2e231cd558ffd42b71463673b1b671e4a49fc3 100644 --- a/src/SQL2Linked/StructuralData.cs +++ b/src/SQL2Linked/StructuralData.cs @@ -2,6 +2,7 @@ using Coscine.Database.Models; using Coscine.Metadata; using VDS.RDF; +using VDS.RDF.Query; namespace SQL2Linked { @@ -10,12 +11,16 @@ namespace SQL2Linked public T Model { get; init; } public ConsulConfiguration Configuration { get; init; } public RdfStoreConnector RdfStoreConnector { get; init; } + public static string Prefix { get; set; } + public readonly SparqlRemoteEndpoint QueryEndpoint; public StructuralData() { Configuration = new ConsulConfiguration(); RdfStoreConnector = new RdfStoreConnector(Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")); Model = new T(); + Prefix = Configuration.GetStringAndWait("coscine/global/epic/prefix"); + QueryEndpoint = new SparqlRemoteEndpoint(new Uri(Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url"))); } public abstract IEnumerable<IGraph> ConvertToLinkedData(IEnumerable<S> entries); @@ -51,5 +56,36 @@ namespace SQL2Linked Console.WriteLine(); } } + public void AssertToGraphUriNode(IGraph graph, string graphSubject, string graphPredicate, string graphObject) + { + graph.Assert( + new Triple( + graph.CreateUriNode(new Uri(graphSubject)), + graph.CreateUriNode(new Uri(graphPredicate)), + graph.CreateUriNode(new Uri(graphObject)) + ) + ); + } + public void AssertToGraphLiteralNode(IGraph graph, string graphSubject, string graphPredicate, string graphObject, Uri? objectType = null) + { + graph.Assert( + new Triple( + graph.CreateUriNode(new Uri(graphSubject)), + graph.CreateUriNode(new Uri(graphPredicate)), + graph.CreateLiteralNode(graphObject, objectType) + ) + ); + } + + public void AssertToGraphBlankAndUriNode(IGraph graph, IBlankNode graphSubject, string graphPredicate, string graphObject) + { + graph.Assert( + new Triple( + graphSubject, + graph.CreateUriNode(new Uri(graphPredicate)), + graph.CreateUriNode(new Uri(graphObject)) + ) + ); + } } }