diff --git a/README.md b/README.md index 50c0e113322aa09bcc636e6db0aadb4d7ba1a4db..a0ca3cd0f2e36d028bb6075401184c149ba94d44 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ -## Tree +# Tree API The TreeApi handles the retrieving or storing metadata to a certain path. Check out the [docs](https://coscine.rwth-aachen.de/coscine/api/Coscine.Api.Tree/swagger). - diff --git a/src/Tree/Controllers/TreeController.cs b/src/Tree/Controllers/TreeController.cs index b01e84cf1e9e34f19183d0b032835841b8882429..511933da1f2acd52374acd2f17826bbfed61f4ad 100644 --- a/src/Tree/Controllers/TreeController.cs +++ b/src/Tree/Controllers/TreeController.cs @@ -1,4 +1,3 @@ -using Coscine.Api.Tree.Util; using Coscine.ApiCommons; using Coscine.ApiCommons.Factories; using Coscine.Configuration; @@ -36,6 +35,7 @@ namespace Coscine.Api.Tree.Controllers private readonly Authenticator _authenticator; private readonly ResourceModel _resourceModel; private readonly RdfStoreConnector _rdfStoreConnector; + private readonly CoscineLDPHelper _coscineLDPHelper; private readonly ProjectRoleModel _projectRoleModel; private readonly ProjectResourceModel _projectResourceModel; private readonly CoscineLogger _coscineLogger; @@ -64,22 +64,7 @@ namespace Coscine.Api.Tree.Controllers var path = rule[rule.IndexOf("/")..]; _blobApiLink = $"https://{host}{path}/blob/"; _prefix = _configuration.GetStringAndWait("coscine/global/epic/prefix"); - } - - /// <summary> - /// Generates Id - /// </summary> - /// <param name="resourceId">Id of the resource</param> - /// <param name="path"> Path to file</param> - /// <returns> Uri </returns> - public Uri GenerateId(string resourceId, string path) - { - if (!path.StartsWith("/")) - { - path = "/" + path; - } - - return new CustomUri($"https://hdl.handle.net/{_prefix}/{resourceId}@path={Uri.EscapeDataString(path)}"); + _coscineLDPHelper = new CoscineLDPHelper(_rdfStoreConnector, _prefix); } /// <summary> @@ -159,10 +144,12 @@ namespace Coscine.Api.Tree.Controllers var resourceTypeInformation = resourceTypeDefinition.GetResourceTypeInformation().Result; var metadataInfos = new List<ResourceEntry>(fileInfos); + var metadataIds = _rdfStoreConnector.ListMetadata(resourceId); + // Add to metadata infos, if no "physical" file for it exists if (!metadataInfos.Any((metadataInfo) => metadataInfo.Key == path)) { - metadataInfos.Add(new ResourceEntry(path, true, 0, GenerateId(resourceId, path).AbsoluteUri, null, DateTime.Now, DateTime.Now)); + metadataInfos.Add(new ResourceEntry(path, true, 0, _coscineLDPHelper.GetId(resourceId, path, true, false, "metadata", metadataIds).AbsoluteUri, null, DateTime.Now, DateTime.Now)); } var applicationProfileGraph = _rdfStoreConnector.GetGraph(resource.ApplicationProfile); @@ -173,7 +160,7 @@ namespace Coscine.Api.Tree.Controllers int metadataCount = 0; foreach (var info in metadataInfos) { - var id = GenerateId(resourceId, info.Key); + var id = _coscineLDPHelper.GetId(resourceId, info.Key, true, false, "metadata", metadataIds); if (_rdfStoreConnector.HasGraph(id.AbsoluteUri)) { var graph = _rdfStoreConnector.GetGraph(id); @@ -297,9 +284,9 @@ namespace Coscine.Api.Tree.Controllers /// <returns>If OK status code 204, otherwise status code 400 or 401</returns> [HttpPut("[controller]/{resourceId}/{*path}")] [ApiExplorerSettings(IgnoreApi = true)] - public IActionResult StoreMetadataForFileWithPath(string resourceId, string path) + public async Task<IActionResult> StoreMetadataForFileWithPath(string resourceId, string path) { - return StoreMetadataForFile(resourceId, path); + return await StoreMetadataForFile(resourceId, path); } /// <summary> @@ -310,7 +297,7 @@ namespace Coscine.Api.Tree.Controllers /// <param name="mimeType">Requested MimeType of the metadata</param> /// <returns>If OK status code 204, otherwise status code 400 or 401</returns> [HttpPut("[controller]/{resourceId}/")] - public IActionResult StoreMetadataForFileWithParameter(string resourceId, [FromQuery] string path = "", [FromQuery] string mimeType = "application/rdf+json") + public async Task<IActionResult> StoreMetadataForFileWithParameter(string resourceId, [FromQuery] string path = "", [FromQuery] string mimeType = "application/rdf+json") { // Strip the first slash, to reuse the previous implementation. if (path.StartsWith("/")) @@ -318,7 +305,7 @@ namespace Coscine.Api.Tree.Controllers path = path[1..]; } - return StoreMetadataForFile(resourceId, path, mimeType); + return await StoreMetadataForFile(resourceId, path, mimeType); } /// <summary> @@ -328,7 +315,7 @@ namespace Coscine.Api.Tree.Controllers /// <param name="path">Path to the file</param> /// <param name="mimeType">Requested MimeType of the metadata</param> /// <returns>If OK status code 204, otherwise status code 400 or 401</returns> - public IActionResult StoreMetadataForFile(string resourceId, string path, string mimeType = "application/rdf+json") + public async Task<IActionResult> StoreMetadataForFile(string resourceId, string path, string mimeType = "application/rdf+json") { path = $"/{path}"; if (path.Contains("%2F") || path.Contains("%2f")) @@ -339,7 +326,7 @@ namespace Coscine.Api.Tree.Controllers // Ducktape solution for supporting multiple mimetypes var metadataObject = ObjectFactory<JToken>.DeserializeFromStream(Request.Body); - var graphNameUri = GenerateId(resourceId, path); + var graphNameUri = _coscineLDPHelper.GetId(resourceId, path, false, true); JObject json; @@ -443,38 +430,15 @@ namespace Coscine.Api.Tree.Controllers return BadRequest("Data has the wrong format!"); } - // store the data - if (_rdfStoreConnector.HasGraph(graphNameUri)) - { - _rdfStoreConnector.ClearGraph(graphNameUri); - - if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics)) - { - LogAnalyticsUpdateMd(_projectResourceModel.GetProjectForResource(resource.Id).Value, resource.Id, path, user, GetMetadataCompleteness(graph.Triples.Count, resource)); - } - } - else + if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics)) { - try - { - _rdfStoreConnector.CreateNamedGraph(graphNameUri); - } -#pragma warning disable RCS1075 // Avoid empty catch clause that catches System.Exception. - catch (Exception) -#pragma warning restore RCS1075 // Avoid empty catch clause that catches System.Exception. - { - // Graph creation failed because it has been created before, skip this for now - } - - if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics)) - { - LogAnalyticsUploadMd(_projectResourceModel.GetProjectForResource(resource.Id).Value, resource.Id, path, user, GetMetadataCompleteness(graph.Triples.Count, resource)); - } + LogAnalyticsUploadMd(_projectResourceModel.GetProjectForResource(resource.Id).Value, resource.Id, path, user, GetMetadataCompleteness(graph.Triples.Count, resource)); } // BaseUri must be set for the sparql query graph.BaseUri = graphNameUri; - _rdfStoreConnector.AddGraph(graph); + + await _rdfStoreConnector.AddMetadataAsync(graph); return NoContent(); } diff --git a/src/Tree/Util/CustomUri.cs b/src/Tree/Util/CustomUri.cs deleted file mode 100644 index 2eaa9416949fc9e94eab1b9db666599b7c140a98..0000000000000000000000000000000000000000 --- a/src/Tree/Util/CustomUri.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -namespace Coscine.Api.Tree.Util -{ - /// <summary> - /// Adapts the returned ToString of a Uri - /// </summary> - public class CustomUri : Uri - { - /// <summary> - /// Constructs a Custom Uri - /// </summary> - /// <param name="uri"></param> - public CustomUri(string uri) : base(uri) - { - - } - - /// <summary> - /// Overwrites the ToString for returning the AbsoluteUri (for dotNetRDF) - /// </summary> - /// <returns></returns> - public override string ToString() - { - return AbsoluteUri; - } - } -}