/// <summary>
        ///     Loads the metadata.
        /// </summary>
        /// <param name="recordId">The record identifier.</param>
        /// <param name="recordRow">The record row with base information about the archive record.</param>
        /// <returns>ArchiveRecordMetadata.</returns>
        public ArchiveRecordMetadata LoadMetadata(string recordId, ArchiveRecordDataSet.ArchiveRecordRow recordRow)
        {
            var retVal = new ArchiveRecordMetadata();

            try
            {
                var tDetailData = Task.Factory.StartNew(() =>
                {
                    retVal.DetailData = LoadDataElements(Convert.ToInt64(recordId));
                    // Get the accession year from the reserved data element with id 505
                    var accessionDataElement =
                        retVal.DetailData.FirstOrDefault(d => d.ElementId == ((int)ScopeArchivDatenElementId.AblieferungLink).ToString());
                    if (accessionDataElement != null && accessionDataElement.ElementValue.Any())
                    {
                        var textValue = accessionDataElement.ElementValue.First().TextValues.First().Value;
                        // the year is indicated in the first 4 digits
                        int year;
                        int.TryParse(textValue.Substring(0, 4), out year);
                        retVal.AccessionDate = year;
                    }

                    // Get the digital repository identifier
                    var repositoryDataElement =
                        retVal.DetailData.FirstOrDefault(d => d.ElementId == applicationSettings.DigitalRepositoryElementIdentifier);
                    if (repositoryDataElement != null && repositoryDataElement.ElementValue.Any())
                    {
                        var textValue          = repositoryDataElement.ElementValue.First().TextValues.First().Value;
                        retVal.PrimaryDataLink = textValue;
                    }
                });
                var tArchiveData     = Task.Factory.StartNew(() => { retVal.Usage = ExtractUsageData(recordRow); });
                var tNodeInfo        = Task.Factory.StartNew(() => { retVal.NodeInfo = LoadNodeInfo(Convert.ToInt64(recordId)); });
                var tContainer       = Task.Factory.StartNew(() => { retVal.Containers = LoadContainers(Convert.ToInt64(recordId)); });
                var tDescriptor      = Task.Factory.StartNew(() => { retVal.Descriptors = LoadDescriptors(Convert.ToInt64(recordId)); });
                var tReference       = Task.Factory.StartNew(() => { retVal.References = LoadReferences(Convert.ToInt64(recordId)); });
                var tAggregationData = Task.Factory.StartNew(() => { retVal.AggregationFields.AddRange(LoadAggregation(recordRow)); });

                Task.WaitAll(tDetailData, tArchiveData, tNodeInfo, tContainer, tDescriptor, tReference, tAggregationData);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to load the metadata for record {RecordId}", recordId);
                throw;
            }

            return(retVal);
        }
        private List <AggregationField> LoadAggregation(ArchiveRecordDataSet.ArchiveRecordRow recordRow)
        {
            var retVal = new List <AggregationField>();

            try
            {
                // Load the fonds aggregation
                var fondsAggregation = new AggregationField
                {
                    AggregationName = "FondsOverview",
                    Values          = GetFondLinkValues(recordRow.HRCH_PFAD)
                };
                retVal.Add(fondsAggregation);
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"Unexpected error while extracting aggregation values. Error message is {ex.Message}");
            }

            // Return the result
            return(retVal);
        }
        /// <summary>
        ///     Extracts the usage data from the archive record row.
        /// </summary>
        /// <param name="recordRow">The archive record row</param>
        /// <returns>ArchiveRecordMetadataUsage.</returns>
        private ArchiveRecordMetadataUsage ExtractUsageData(ArchiveRecordDataSet.ArchiveRecordRow recordRow)
        {
            var retVal = new ArchiveRecordMetadataUsage();

            try
            {
                if (recordRow != null)
                {
                    retVal.AlwaysVisibleOnline       = recordRow.SUCH_FRGB_IND != 0;
                    retVal.IsPhysicalyUsable         = recordRow.VRZNG_ENHT_BNTZB_ID == 1;
                    retVal.ContainsPersonRelatedData = recordRow.SCHTZ_PRSN_IND != 0;
                    retVal.ProtectionCategory        = recordRow.VRZNG_ENHT_INHLT_NM;
                    retVal.ProtectionBaseDate        = recordRow.VRZNG_ENHT_SCHTZ_FRIST_NM;
                    retVal.ProtectionDuration        = (int)recordRow.SCHTZ_FRIST_DAUER;
                    retVal.ProtectionEndDate         = recordRow.IsSCHTZ_FRIST_BIS_DTNull() ? (DateTime?)null : recordRow.SCHTZ_FRIST_BIS_DT;
                    retVal.CannotFallBelow           = recordRow.SCHTZ_FRIST_MIN_IND != 0;
                    retVal.AdjustedManually          = recordRow.SCHTZ_FRIST_MTTN_IND != 0;
                    retVal.ProtectionNote            = recordRow.SCHTZ_FRIST_NTZ;
                    retVal.Permission        = recordRow.VRZNG_ENHT_BWLG_TYP_NM;
                    retVal.PhysicalUsability = recordRow.VRZNG_ENHT_BNTZB_NM;
                    retVal.Accessibility     = recordRow.VRZNG_ENHT_ZGNGL_NM;
                    retVal.UsageNotes        = recordRow.BNTZG_HNWS_TXT;
                    retVal.License           = ArchiveRecordMetadataUsageLicense.Undefined; // property is eventually for later use. Just use undefined for now
                }
            }
            catch (Exception ex)
            {
                if (recordRow != null)
                {
                    Log.Error(ex, "Usage data load failed for record: {VRZNG_ENHT_ID}", recordRow.VRZNG_ENHT_ID);
                }

                throw;
            }

            return(retVal);
        }
        /// <summary>
        ///     Loads the display data.
        /// </summary>
        /// <param name="recordId">The record identifier.</param>
        /// <param name="metadata">The already existing metadata.</param>
        /// <param name="recordRow">The record row with information about the archive record.</param>
        /// <returns>ArchiveRecordDisplay.</returns>
        private ArchiveRecordDisplay LoadDisplayData(string recordId, ArchiveRecordMetadata metadata, ArchiveRecordDataSet.ArchiveRecordRow recordRow)
        {
            var display = new ArchiveRecordDisplay
            {
                ExternalDisplayTemplateName = $"{recordRow.ANST_FRMLR_ID}: {recordRow.ANST_FRMLR_NM}",
                InternalDisplayTemplateName = $"{recordRow.BRBTG_FRMLR_ID}: {recordRow.BRBTG_FRMLR_NM}"
            };

            try
            {
                var tNodeContext = Task.Factory.StartNew(() =>
                {
                    var context = dataProvider.LoadNodeContext(Convert.ToInt64(recordId));
                    display.FirstChildArchiveRecordId = context.FirstChildArchiveRecordId;
                    display.NextArchiveRecordId       = context.NextArchiveRecordId;
                    display.PreviousArchiveRecordId   = context.PreviousArchiveRecordId;
                    display.ParentArchiveRecordId     = context.ParentArchiveRecordId;
                });
                var tMetaInfo = Task.Factory.StartNew(() =>
                {
                    display.ContainsImages = metadata.DetailData.Any(d => d.ElementType == DataElementElementType.image);
                    display.ContainsMedia  = metadata.DetailData.Any(d => d.ElementType == DataElementElementType.media);
                    // In scopeArchiv the Levels (Stufen) have an attribute called "Bestellbar". We now check this on the
                    // Unit of Description (VRZNG_ENHT_BSTLG_IND) PLUS the additional rule, that there must be containers.
                    display.CanBeOrdered = metadata.Containers.NumberOfContainers > 0 && recordRow.VRZNG_ENHT_BSTLG_IND != 0;
                });
                var tArchiveplanContext = Task.Factory.StartNew(() =>
                {
                    display.ArchiveplanContext = LoadArchivePlanContext(Convert.ToInt64(recordId), metadata);
                });

                Task.WaitAll(tNodeContext, tMetaInfo, tArchiveplanContext);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to load the display information for record {RecordId}", recordId);
                throw;
            }

            return(display);
        }