Skip to content
Snippets Groups Projects
Select Git revision
  • 30f3afc7dc494c7f542af663786099c74b50b1b4
  • main default protected
  • gitkeep
  • dev protected
  • Issue/2914-trellisMigrator
  • Issue/2847-reporting
  • Hotfix/2776-workingNewVersion
  • Hotfix/xxxx-correctAssignments
  • Issue/2666-adminCronjobs-theSequal
  • Issue/2666-adminCronjobs
  • Issue/2518-docs
  • Hotfix/xxxx-coscineGraph
  • Issue/2304-virtuosoRoars
  • Fix/v0.1.7-dependencies
  • Hotfix/2212-fixFiles
  • Issue/2222-resourceDateCreated
  • Issue/2221-projectDateCreated
  • Hotfix/xxxx-changeUrls
  • Issue/1321-pidEnquiryOverhaul
  • Issue/1782-structualDataIntegration
  • Issue/2084-migrateResourceStructuralData
  • v0.1.24
  • v0.1.23
  • v0.1.22
  • v0.1.21
  • v0.1.20
  • v0.1.19
  • v0.1.18
  • v0.1.17
  • v0.1.16
  • v0.1.15
  • v0.1.14
  • v0.1.13
  • v0.1.12
  • v0.1.11
  • v0.1.10
  • v0.1.9
  • v0.1.7
  • v0.1.8
  • v0.1.6
  • v0.1.5
41 results

StructuralData.cs

Blame
  • Petar Hristov's avatar
    Petar Hristov authored and L. Ellenbeck committed
    d2b59b64
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    StructuralData.cs 7.12 KiB
    using Coscine.ApiClient;
    using Coscine.ApiClient.Core.Api;
    using Coscine.ApiClient.Core.Client;
    using Coscine.ApiClient.Core.Model;
    using Microsoft.Extensions.Configuration;
    using SQL2Linked.Models.ConfigurationModels;
    using VDS.RDF;
    
    namespace SQL2Linked;
    
    /// <summary>
    /// Provides an abstract base class for handling structural data transformations and migrations.
    /// </summary>
    /// <typeparam name="S">The type of data to be transformed or migrated.</typeparam>
    /// <remarks>
    /// This class is partially shared between this script and the Trellis Migrator script.
    /// </remarks>
    public abstract class StructuralData<S>
    {
        private readonly string _adminToken;
        protected readonly Configuration _apiConfiguration;
        protected readonly AdminApi _adminApi;
        protected readonly PidConfiguration _pidConfiguration; // Comes from the API Client, not from the application's own configuration
    
        /// <summary>
        /// Initializes a new instance of the <see cref="StructuralData{S}"/> class.
        /// </summary>
        public StructuralData()
        {
            // Retrieve the configuration settings for the PID ePIC API from the API Client
            var apiConfiguration = ApiConfigurationUtil.RetrieveApiConfiguration();
            _pidConfiguration = apiConfiguration.GetSection(PidConfiguration.Section).Get<PidConfiguration>() ?? new();
    
            // Ensiure that the prefix is not null or empty.
            ArgumentException.ThrowIfNullOrWhiteSpace(_pidConfiguration.Prefix, nameof(_pidConfiguration.Prefix));
    
            // Generate an admin token for the API Client
            var jwtConfiguration = ApiConfigurationUtil.RetrieveJwtConfiguration();
            _adminToken = ApiConfigurationUtil.GenerateAdminToken(jwtConfiguration);
            _apiConfiguration = new Configuration()
            {
                BasePath = "http://localhost:7206/coscine",
                ApiKeyPrefix = { { "Authorization", "Bearer" } },
                ApiKey = { { "Authorization", _adminToken } },
            };
            _adminApi = new AdminApi(_apiConfiguration);
        }
    
        /// <summary>
        /// Converts the given entries to linked data graphs.
        /// </summary>
        /// <param name="entries">The entries to convert.</param>
        /// <returns>An enumerable collection of graphs representing the linked data.</returns>
        public abstract Task<IEnumerable<IGraph>> ConvertToLinkedDataAsync(IEnumerable<S> entries);
    
        /// <summary>
        /// Retrieves all entries of type <typeparamref name="S"/>.
        /// </summary>
        /// <returns>A task that represents the asynchronous operation. The task result contains an enumerable of all entries.</returns>
        public abstract Task<IEnumerable<S>> GetAll();
    
        /// <summary>
        /// Migrates the data, optionally in a dummy mode where changes are not persisted.
        /// </summary>
        /// <param name="dummyMode">If set to <c>true</c>, the migration is simulated but not executed.</param>
        /// <returns>A task representing the asynchronous operation.</returns>
        public async Task Migrate(bool dummyMode)
        {
            var spacer = new string('-', 35);
            Console.WriteLine($"\n{spacer}\n{typeof(S).Name}\n{spacer}");
            var graphs = await ConvertToLinkedDataAsync(await GetAll());
            if (!dummyMode)
            {
                await StoreGraphs(graphs);
            }
        }
    
        /// <summary>
        /// Stores the given graphs in the underlying data store.
        /// </summary>
        /// <param name="graphs">The graphs to be stored.</param>
        /// <returns>A task representing the asynchronous operation.</returns>
        public async Task StoreGraphs(IEnumerable<IGraph> graphs)
        {
            var formatEnum = RdfFormat.TextTurtle;
            var format = "text/turtle";
    
            foreach (var graph in graphs)
            {
                Console.WriteLine($" ({graph.BaseUri})");
    
                try
                {
                    var rdfWriter = MimeTypesHelper.GetWriter(format);
                    var content = VDS.RDF.Writing.StringWriter.Write(graph, rdfWriter);
    
                    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();
                }
            }
        }
    
        /// <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)
                    )
                );
            }
        }
    }