Exemple #1
0
        /// <summary>
        /// Move/traverse up hierarchy for the item and confirm alignment with the hierarchy attribute configuration(s) and update the values accordingly.
        /// </summary>
        private FileRecordHierarchyLinker MoveUpHierarchy(FileRecordHierarchyLinker linker, FileRecordHierarchyItem from, FileRecordHierarchyItem to, FileRecord record, bool final = false)
        {
            if (from == null)
            {
                return(null);
            }

            if (!final && from == to)
            {
                return(linker);
            }

            foreach (var child in from.Children)
            {
                var fhr   = child.Value.HierarchyReflector;
                var fha   = child.Value.HierarchyReflector.FileHierarchy;
                var count = linker.GetChildCount(fhr.RecordIdentifier);

                // Validate alignment to configuration.
                if (fha.IsMandatory && count == 0)
                {
                    fhr.CreateErrorMessage(record, "{0} is required; no record found.");
                    continue;
                }

                // Minimum count check only honoured where at least one record found; otherwise, use IsMandatory to catch.
                if (fhr.IsCollection && count > 0 && fha.MinCount > 0 && count < fha.MinCount)
                {
                    fhr.CreateErrorMessage(record, "{0} must have at least {2} records(s); additional required.", fha.MinCount);
                }

                // Update the values as we move up the hierarchy.
                var vals = linker.GetChildValues(fhr.RecordIdentifier);
                fhr.SetValue(linker.Value, vals);
            }

            return(MoveUpHierarchy(linker.Parent, from.Parent, to, record, final));
        }
Exemple #2
0
        /// <summary>
        /// Internal read logic.
        /// </summary>
        private FileOperationResult ReadInternal()
        {
            // Check and see if we are already at the end of the file.
            if (IsEndOfFile)
            {
                throw new InvalidOperationException("Attempt made to read past the end of the file.");
            }

            // Make sure the configuration is valid.
            if (!_startedReading)
            {
                InitialConfiguration();
            }

            // Read the next record(s) group.
            _startedReading = true;
            var records = new List <FileRecord>();
            FileRecordHierarchyLinker linker = null;

            while (true)
            {
                ReadRecord();

                // When end of file is reached, check corresponding file validations.
                if (IsEndOfFile)
                {
                    return(ProcessEndOfFile());
                }

                // Grab the current record.
                var record = _currentRecord;

                // Check and see if the first record is a header.
                if (record.LineNumber == 1)
                {
                    var header = ProcessHeaderRecord(record);
                    if (header != null)
                    {
                        return(header);
                    }
                }

                // Check and see if the last record is a trailer.
                if (_nextRecord == null)
                {
                    var trailer = ProcessTrailerRecord(record);
                    if (trailer != null)
                    {
                        return(trailer);
                    }
                }

                // Where no hierarchy each record is processed as-is; or where hierarchy is in place and top-level is unknown.
                if (!_hasHierarchy || (records.Count == 0 && record.RecordIdentifier != _fileFormat.ContentRecordIdentifier))
                {
                    return(ProcessNonHierarchicalContent(record));
                }

                // We are all hierarchy all of the time from here on in...
                if (records.Count == 0)
                {
                    record.Level = 0;
                    record.Value = _fileFormat.ReadCreateRecordValueInternal(record, _fileFormat.ContentRowType);
                    _contentReflector.Validate(record);
                    linker = new FileRecordHierarchyLinker(_hierarchy[_fileFormat.ContentRecordIdentifier], null, 0)
                    {
                        Value = record.Value
                    };
                }
                else
                {
                    linker = ProcessHierarchicalContent(linker, records, record);
                }

                records.Add(record);
                _readContent = true;

                // Check and see if the record is the last for the result set; if so, then exit.
                if (CheckCurrentIsLast())
                {
                    var curr = _hierarchy[linker.RecordIdentifier];
                    var root = _hierarchy[_fileFormat.ContentRecordIdentifier];
                    MoveUpHierarchy(linker, curr, root, record, true);
                    break;
                }
            }

            return(new FileOperationResult <TContent>(FileContentStatus.Content, records.ToArray()));
        }
Exemple #3
0
        /// <summary>
        /// Process a hierarchical Content record.
        /// </summary>
        private FileRecordHierarchyLinker ProcessHierarchicalContent(FileRecordHierarchyLinker linker, List <FileRecord> records, FileRecord record)
        {
            if (!CheckNotHeaderOrTrailer(record))
            {
                return(linker);
            }

            // Make sure we know what the record is.
            if (!_hierarchy.ContainsKey(record.RecordIdentifier))
            {
                record.Messages.Add(MessageType.Error, "Record identifier is unknown.");
                return(linker);
            }

            // Ensure that the record is valid from a hierarchy position perspective.
            var isValid = true;
            var curr    = _hierarchy[record.RecordIdentifier];
            var prev    = _hierarchy[records.Last(x => x.Level >= 0).RecordIdentifier];

            if (curr.Level == prev.Level)
            {
                if (prev.Parent.Children.ContainsKey(record.RecordIdentifier))
                {
                    linker = linker.Parent;
                }
                else
                {
                    isValid = record.Messages.Add(MessageType.Error, "Record identifier is not a valid peer of the previous record.") == null;
                }
            }
            else if (curr.Level < prev.Level)
            {
                if (FindUpHierachy(prev, record))
                {
                    linker = MoveUpHierarchy(linker, prev, curr.Parent, record);
                }
                else
                {
                    isValid = record.Messages.Add(MessageType.Error, "Record identifier is not valid within current traversed hierarchy.") == null;
                }
            }
            else
            {
                if (!prev.Children.ContainsKey(record.RecordIdentifier))
                {
                    isValid = record.Messages.Add(MessageType.Error, "Record identifier is not a direct descendent of the previous record.") == null;
                }
            }

            // Check that record is in alignment with the hierarchy attribute configuration.
            var parentValue = linker.Value;

            if (isValid)
            {
                linker = linker.AddChild(curr, record);
                if (linker.Index > 0 && !curr.HierarchyReflector.IsCollection)
                {
                    isValid = false;
                    curr.HierarchyReflector.CreateErrorMessage(record, "{0} does not support multiple records; too many provided.");
                }

                if (curr.HierarchyReflector.IsCollection && curr.HierarchyReflector.FileHierarchy.MaxCount > 0 && linker.Index >= curr.HierarchyReflector.FileHierarchy.MaxCount)
                {
                    curr.HierarchyReflector.CreateErrorMessage(record, "{0} must not exceed {2} records(s); too many provided.", curr.HierarchyReflector.FileHierarchy.MaxCount);
                }

                record.Level = curr.Level;
            }
            else
            {
                record.Level = -1;
            }

            // Parse the record to get the value and only update the linker where valid.
            record.Value = _fileFormat.ReadCreateRecordValueInternal(record, curr.HierarchyReflector.FileHierarchy.ChildType ?? curr.RecordReflector.Type);
            curr.RecordReflector.Validate(record);
            if (isValid)
            {
                linker.Value = record.Value;
            }

            RecordProcess(record);

            return(linker);
        }