/// <summary>
        ///     Loads the archive plan context.
        /// </summary>
        /// <param name="recordId">The record identifier.</param>
        /// <param name="metadata">The metadata.</param>
        /// <returns>List&lt;ArchiveplanContextItem&gt;.</returns>
        private List <ArchiveplanContextItem> LoadArchivePlanContext(long recordId, ArchiveRecordMetadata metadata)
        {
            var retVal = new List <ArchiveplanContextItem>();

            try
            {
                var path = metadata.NodeInfo.Path;
                // in scopeArchiv the path consists of the concatenated id's all all id's where
                // each id is padded to 10 digits
                var elements = Enumerable.Range(0, path.Length / 10).Select(i => Convert.ToInt64(path.Substring(i * 10, 10))).ToArray();

                var ds = dataProvider.LoadArchivePlanInfo(elements);

                foreach (var elementId in elements)
                {
                    var row = ds.ArchivePlanItem.FirstOrDefault(e => e.VRZNG_ENHT_ID == elementId);
                    if (row != null)
                    {
                        retVal.Add(new ArchiveplanContextItem
                        {
                            ArchiveRecordId = ((int)row.VRZNG_ENHT_ID).ToString(),
                            Level           = row.ENTRG_TYP_NM,
                            DateRangeText   = row.ZT_RAUM_TXT,
                            IconId          = (int)row.ICON_ID,
                            RefCode         = row.SGNTR_CD,
                            Title           = row.VRZNG_ENHT_TITEL
                        });
                    }
                    else
                    // Code should never run here. But during tests we had the situation where the archive plan path contained
                    // ids to records that were not in the database. These items we flag simply as unknown.
                    {
                        retVal.Add(new ArchiveplanContextItem
                        {
                            ArchiveRecordId = "-1",
                            Level           = "?",
                            DateRangeText   = "?",
                            IconId          = -1,
                            RefCode         = "?",
                            Title           = "?"
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to load the archive plan context for record {RecordId}", recordId);
                throw;
            }

            return(retVal);
        }
        /// <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);
        }
        /// <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);
        }