Inheritance: IDisposable
示例#1
0
 internal static void PopulateObjectValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
     var cache = structure.CachedReads;
     var valueInfo = descriptor.ValueInfo;
     var text = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
                                              read ? reader.ReadAsString() : (string)reader.Value;
     descriptor.Info.SetValue(structure.Instance, ConvertUtils.ConvertOrCast(text, reader.Culture, descriptor.Info.PropertyType));
 }
示例#2
0
 internal static void PopulateDateTimeValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
     var cache = structure.CachedReads;
     var valueInfo = descriptor.ValueInfo;
     var dateString = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
                                                    read ? reader.ReadAsString() : (string)reader.Value;
     if (dateString != null) {
         dateString = dateString.Substring(0, valueInfo.Picture.Scale);
         var date = default(DateTime);
         if (dateString.TryParseEdiDate(valueInfo.Format, CultureInfo.InvariantCulture, out date)) {
             var existingDateObject = descriptor.Info.GetValue(structure.Instance);
             var existingDate = default(DateTime);
             if (existingDateObject != null && !existingDateObject.Equals(default(DateTime))) {
                 if (existingDateObject is DateTime?) {
                     existingDate = ((DateTime?)existingDateObject).Value;
                 } else {
                     existingDate = ((DateTime)existingDateObject);
                 }
                 if (date - date.Date == default(TimeSpan)) {
                     date = date.Date.Add(existingDate - existingDate.Date);
                 } else {
                     date = existingDate.Add(date - date.Date);
                 }
             }
             descriptor.Info.SetValue(structure.Instance, date);
         }
     }
 }
示例#3
0
        /// <summary>
        /// Conditionals the match.
        /// </summary>
        /// <returns>The match.</returns>
        /// <param name="reader">Reader.</param>
        /// <param name="currentStructure">Current structure.</param>
        /// <param name="newContainerType">New container type.</param>
        /// <param name="matches">Matches.</param>
        private static EdiPropertyDescriptor ConditionalMatch(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType, EdiPropertyDescriptor[] matches)
        {
            if (!matches.All(p => p.ConditionInfo != null))
            {
                throw new EdiException(
                          "More than one properties on type '{0}' have the '{1}' attribute. Please add a 'Condition' attribute to all properties in order to discriminate where each {2} will go."
                          .FormatWith(CultureInfo.InvariantCulture, currentStructure.Descriptor.ClrType.Name, newContainerType, newContainerType));
            }
            if (matches.Select(p => p.Path).Distinct().Count() != 1)
            {
                throw new EdiException("More than one properties on type '{0}' have the '{1}' attribute but the 'Condition' attribute has a different search path declared."
                                       .FormatWith(CultureInfo.InvariantCulture, currentStructure.Descriptor.ClrType.Name, newContainerType));
            }

            var readCache = currentStructure.CachedReads;
            var path      = string.Empty;

            do
            {
                reader.Read();
                path = reader.Path;
                readCache.Enqueue(new EdiEntry(path, reader.TokenType, reader.Value as string));
            } while (reader.TokenType != EdiToken.SegmentStart && matches[0].Path != path);

            var discriminator = reader.ReadAsString();
            var property      = matches.SingleOrDefault(p => p.ConditionInfo.MatchValue == discriminator);

            readCache.Enqueue(new EdiEntry(path, reader.TokenType, discriminator));
            return(property);
        }
示例#4
0
        /// <summary>
        /// Finds for current element.
        /// </summary>
        /// <returns>The for current element.</returns>
        /// <param name="reader">Reader.</param>
        /// <param name="currentStructure">Current structure.</param>
        /// <param name="newContainerType">New container type.</param>
        private EdiPropertyDescriptor FindForCurrentElement(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType)
        {
            var candidates = currentStructure.GetMatchingProperties(newContainerType);

            if (candidates.Length == 0)
            {
                return(null);
            }
            var property = default(EdiPropertyDescriptor);

            if (reader.TokenType == EdiToken.ElementStart)
            {
                var matches = candidates.Where(p => p.PathInfo.PathInternal.ToString("E").Equals(reader.Path)).ToArray();
                if (matches.Length == 0)
                {
                    property = null;
                }
                else if (matches.Length == 1 && matches[0].ConditionInfo == null)
                {
                    property = matches[0];
                }
                else
                {
                    property = ConditionalMatch(reader, currentStructure, newContainerType, matches);
                }
            }
            return(property);
        }
示例#5
0
        internal static void PopulateInt32Value(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read)
        {
            var cache     = structure.CachedReads;
            var valueInfo = descriptor.ValueInfo;

            if (!descriptor.Info.PropertyType.IsEnum())
            {
                var integer = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsInt32(valueInfo.Path, reader.Culture) :
                              read?reader.ReadAsInt32() : (int?)reader.Value;

                if (integer.HasValue)
                {
                    descriptor.Info.SetValue(structure.Instance, ConvertUtils.ConvertOrCast(integer.Value, CultureInfo.InvariantCulture, descriptor.Info.PropertyType));
                }
            }
            else
            {
                var enumValueString = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
                                      read?reader.ReadAsString() : (string)reader.Value;

                if (!string.IsNullOrEmpty(enumValueString))
                {
                    descriptor.Info.SetValue(structure.Instance, ConvertUtils.ConvertOrCast(enumValueString, CultureInfo.InvariantCulture, descriptor.Info.PropertyType));
                }
            }
        }
示例#6
0
        internal static void PopulateBooleanValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read)
        {
            var cache     = structure.CachedReads;
            var valueInfo = descriptor.ValueInfo;
            var text      = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
                            read?reader.ReadAsString() : (string)reader.Value;

            if (!string.IsNullOrEmpty(text))
            {
                var integerValue = default(int);
                var booleanValue = default(bool);
                if (int.TryParse(text, NumberStyles.Integer, reader.Culture, out integerValue))
                {
                    booleanValue = integerValue == 1;
                }
                else if (bool.TryParse(text, out booleanValue))
                {
                }
                else
                {
                    throw new EdiException("Unable to convert string '{0}' to boolean.".FormatWith(reader.Culture, text));
                }
                descriptor.Info.SetValue(structure.Instance, booleanValue);
            }
        }
示例#7
0
        private EdiPropertyDescriptor FindForCurrentSegment(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType)
        {
            var candidates = currentStructure.GetMatchingProperties(newContainerType);

            if (candidates.Length == 0)
            {
                return(null);
            }
            var property = default(EdiPropertyDescriptor);

            if (reader.TokenType == EdiToken.SegmentName || currentStructure.CachedReads.Count > 0)
            {
                var segmentName = reader.TokenType == EdiToken.SegmentName ? reader.Value : ((EdiPath)currentStructure.CachedReads.Peek().Path).Segment;
                var matches     = candidates.Where(p => segmentName.Equals(p.Segment)).ToArray();
                if (matches.Length == 0)
                {
                    property = null;
                }
                else if (matches.Length == 1 && matches[0].Conditions == null)
                {
                    property = matches[0];
                }
                else
                {
                    property = ConditionalMatch(reader, currentStructure, newContainerType, matches);
                }
            }
            return(property);
        }
示例#8
0
 internal static void PopulateStringValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
     var cache = structure.CachedReads;
     var valueInfo = descriptor.ValueInfo;
     var text = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
                                              read ? reader.ReadAsString() : (string)reader.Value;
     descriptor.Info.SetValue(structure.Instance, text);
 }
示例#9
0
        private static EdiPropertyDescriptor ConditionalMatch(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType, EdiPropertyDescriptor[] candidates)
        {
            if (!candidates.All(p => p.Conditions != null))
            {
                throw new EdiException(
                          "More than one properties on type '{0}' have the '{1}' attribute. Please add a 'Condition' attribute to all properties in order to discriminate where each {2} will go."
                          .FormatWith(CultureInfo.InvariantCulture, currentStructure.Descriptor.ClrType.Name, newContainerType, newContainerType));
            }
            var conditionPaths = candidates.SelectMany(p => p.Conditions.Select(c => c.Path)).Distinct().ToArray();
            //if (conditionPaths.Length != 1) {
            //    throw new EdiException("More than one properties on type '{0}' have the '{1}' attribute but the 'Condition' attribute has a different search path declared."
            //        .FormatWith(CultureInfo.InvariantCulture, currentStructure.Descriptor.ClrType.Name, newContainerType));
            //}
            var cache           = currentStructure.CachedReads;
            var findingsPerPath = new Dictionary <string, string>();

            foreach (var path in conditionPaths)
            {
                // search the cache first.
                var value = default(string);
                var found = false;
                if (cache.Count > 0)
                {
                    var entry = cache.Where(r => r.Path == path).SingleOrDefault();
                    found = !default(EdiEntry).Equals(entry);
                }
                if (!found)
                {
                    // if nothing found search the reader (arvance forward).
                    do
                    {
                        if (reader.Path == path)
                        {
                            value = reader.ReadAsString();
                            cache.Enqueue(new EdiEntry(reader.Path, reader.TokenType, value));
                            found = true;
                            value = reader.Value as string; // if found break;
                            break;
                        }
                        else
                        {
                            reader.Read();
                            cache.Enqueue(new EdiEntry(reader.Path, reader.TokenType, reader.Value as string));
                        }
                    } while (!found || reader.TokenType != EdiToken.SegmentStart);
                }

                if (found)
                {
                    var property = candidates.SingleOrDefault(p => p.PathInfo.PathInternal == path && p.Conditions.Any(c => c.SatisfiedBy(value)));
                    if (property != null)
                    {
                        return(property);
                    }
                }
            }

            return(null);
        }
示例#10
0
        internal virtual object DeserializeInternal(EdiReader reader, Type objectType)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            // set serialization options onto reader
            object value = null;

            var stack = new Stack <EdiStructure>();

            // If this is not a collection type asume this type is the interchange.
            if (!objectType.IsCollectionType())
            {
                while (reader.Read())
                {
                    if (reader.IsStartInterchange)
                    {
                        stack.Push(new EdiStructure(EdiStructureType.Interchange, Activator.CreateInstance(objectType)));
                    }
                    if (reader.IsEndInterchange)
                    {
                        while (stack.Peek().Container != EdiStructureType.Interchange)
                        {
                            stack.Pop();
                        }
                        value = stack.Peek().Instance;
                    }
                    else if (reader.IsStartGroup)
                    {
                        TryCreateContainer(reader, stack, EdiStructureType.Group);
                    }
                    else if (reader.IsStartMessage)
                    {
                        TryCreateContainer(reader, stack, EdiStructureType.Message);
                    }
                    else if (reader.TokenType == EdiToken.SegmentName)
                    {
                        TryCreateContainer(reader, stack, EdiStructureType.Segment);
                    }
                    else if (reader.TokenType == EdiToken.ElementStart)
                    {
                        TryCreateContainer(reader, stack, EdiStructureType.Element);
                    }
                    if (reader.TokenType == EdiToken.ComponentStart)
                    {
                        PopulateValue(reader, stack);
                    }
                }
            }
            // else if this is indeed a collection type this must be a collection of messages.
            else
            {
                throw new NotImplementedException("Collection types are not supported as the root Type. Try to wrap List of Messages inside a container type.");
            }

            return(value);
        }
示例#11
0
 internal static void PopulateDecimalValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
     var cache = structure.CachedReads;
     var valueInfo = descriptor.ValueInfo;
     var numberFloat = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsDecimal(valueInfo.Path, descriptor.ValueInfo.Picture, reader.Grammar.DecimalMark) :
                                                     read ? reader.ReadAsDecimal(descriptor.ValueInfo.Picture) : (decimal?)reader.Value;
     if (numberFloat != null) {
         descriptor.Info.SetValue(structure.Instance, numberFloat);
     }
 }
示例#12
0
        internal static void PopulateCharValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
            var cache = structure.CachedReads;
            var valueInfo = descriptor.ValueInfo;
            var text = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
                                                     read ? reader.ReadAsString() : (string)reader.Value;

            if (!string.IsNullOrEmpty(text)) {
                if (text.Length > 1)
                    throw new EdiException("Unable to convert string '{0}' to char. It is more than 1 character long.".FormatWith(reader.Culture, text));
                descriptor.Info.SetValue(structure.Instance, text[0]);
            }
        }
示例#13
0
 private EdiPropertyDescriptor FindForCurrentLogicalStructure(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType) {
     var candidates = currentStructure.GetMatchingProperties(newContainerType);
     var property = default(EdiPropertyDescriptor);
     if (candidates.Length == 0) {
         return null;
     }
     if (candidates.Length == 1 && candidates[0].Conditions == null) {
         property = candidates[0];
     } else {
         property = ConditionalMatch(reader, currentStructure, newContainerType, candidates);
     }
     return property;
 }
示例#14
0
        private static Dictionary <string, string> SearchForward(EdiReader reader, Queue <EdiEntry> cache, IEnumerable <string> pathsToSeekForValues)
        {
            var searchResults = pathsToSeekForValues.Distinct().ToDictionary(x => x, x => (string)null);

            foreach (var path in searchResults.Keys.ToArray())
            {
                // search the cache first.
                var value = default(string);
                var found = false;
                if (cache.Count > 0)
                {
                    var entry = cache.Where(r => r.Path == path && r.Token.IsPrimitiveToken()).SingleOrDefault();
                    if (!default(EdiEntry).Equals(entry))
                    {
                        found = true;
                        value = entry.Value;
                    }
                }
                if (!found)
                {
                    // if nothing found search the reader (arvance forward).
                    do
                    {
                        if (reader.Path == path)
                        {
                            value = reader.ReadAsString();
                            cache.Enqueue(new EdiEntry(reader.Path, reader.TokenType, value));
                            found = true;
                            value = reader.Value as string; // if found break;
                            break;
                        }
                        else
                        {
                            reader.Read();
                            cache.Enqueue(new EdiEntry(reader.Path, reader.TokenType, reader.Value as string));
                        }
                    } while (!found || reader.TokenType != EdiToken.SegmentStart);
                }

                if (found)
                {
                    searchResults[path] = value;
                }
            }
            return(searchResults);
        }
示例#15
0
        private EdiPropertyDescriptor FindForCurrentElement(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType, out Queue <EdiEntry> elementReads)
        {
            elementReads = null;
            var candidates = currentStructure.GetMatchingProperties(newContainerType);

            if (candidates.Length == 0)
            {
                return(null);
            }
            var property = default(EdiPropertyDescriptor);

            if (reader.TokenType == EdiToken.ElementStart || currentStructure.CachedReads.Count > 0)
            {
                var elementPath = reader.TokenType == EdiToken.ElementStart ? reader.Path : ((EdiPath)currentStructure.CachedReads.Peek().Path).ToString("E");
                var matches     = candidates.Where(p => p.PathInfo.PathInternal.Equals(elementPath)).ToArray();
                if (matches.Length == 0)
                {
                    property = null;
                }
                else if (matches.Length == 1 && matches[0].Conditions == null)
                {
                    property = matches[0];
                }
                else
                {
                    property = ConditionalMatch(reader, currentStructure, newContainerType, matches);
                }
                if (property != null)
                {
                    elementReads = new Queue <EdiEntry>();
                    var parentCache = currentStructure.CachedReads;
                    while (parentCache.Count > 0 && elementPath == ((EdiPath)parentCache.Peek().Path).ToString("E"))
                    {
                        elementReads.Enqueue(parentCache.Dequeue());
                    }
                    //foreach (var item in currentStructure.CachedReads) {
                    //    if (elementPath == ((EdiPath)item.Path).ToString("E")) {
                    //        elementReads.Enqueue(item);
                    //    }
                    //}
                }
            }
            return(property);
        }
示例#16
0
 private EdiPropertyDescriptor FindForCurrentSegment(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType) {
     currentStructure.CachedReads.Clear();
     var candidates = currentStructure.GetMatchingProperties(newContainerType);
     if (candidates.Length == 0) {
         return null;
     }
     var property = default(EdiPropertyDescriptor);
     if (reader.TokenType == EdiToken.SegmentName) {
         var matches = candidates.Where(p => p.Segment.Equals(reader.Value)).ToArray();
         if (matches.Length == 0) {
             property = null;
         } else if (matches.Length == 1 && matches[0].Conditions == null) {
             property = matches[0];
         } else {
             property = ConditionalMatch(reader, currentStructure, newContainerType, matches);
         }
     }
     return property;
 }
示例#17
0
        private static bool PositionMatchesStructure(EdiReader reader, EdiStructure structure, string segmentName)
        {
            if (structure.Conditions == null || structure.Conditions.Length == 0)
            {
                return(true); // cannot determine.
            }
            var searchResults = SearchForward(reader, structure.CachedReads, structure.Conditions.Select(c => c.Path));

            var result = structure.ConditionStackMode == EdiConditionStackMode.All ? structure.Conditions.All(c => c.SatisfiedBy(searchResults[c.PathInternal]))
                                                                                   : structure.Conditions.Any(c => c.SatisfiedBy(searchResults[c.PathInternal]));

            if (result)
            {
                return(true);
            }

            // search siblings on the same level before returning.
            var matchingProperties = structure.Container.GetMatchingProperties(segmentName);

            if (matchingProperties == null || matchingProperties.Length == 0)
            {
                return(false);
            }
            foreach (var prop in matchingProperties)
            {
                // if there is simply a matching sibling with no conditions return ok.
                if (prop.Conditions == null)
                {
                    return(true);
                }
                searchResults = SearchForward(reader, structure.Container.CachedReads, prop.Conditions.Select(c => c.Path));

                var check = prop.ConditionStackMode == EdiConditionStackMode.All ? prop.Conditions.All(c => c.SatisfiedBy(searchResults[c.PathInternal]))
                                                                                 : prop.Conditions.Any(c => c.SatisfiedBy(searchResults[c.PathInternal]));
                if (check)
                {
                    return(true);
                }
            }
            return(false);
        }
示例#18
0
        private static EdiPropertyDescriptor ConditionalMatch(EdiReader reader, EdiStructure currentStructure, EdiStructureType newContainerType, params EdiPropertyDescriptor[] candidates)
        {
            if (!candidates.All(p => p.Conditions != null))
            {
                throw new EdiException(
                          "More than one properties on type '{0}' have the '{1}' attribute. Please add a 'Condition' attribute to all properties in order to discriminate where each {2} will go."
                          .FormatWith(CultureInfo.InvariantCulture, currentStructure.Descriptor.ClrType.Name, newContainerType, newContainerType));
            }

            var searchResults = SearchForward(reader, currentStructure.CachedReads, candidates.SelectMany(p => p.Conditions.Select(c => c.Path)));
            //if (searchResults.Length != 1) {
            //    throw new EdiException("More than one properties on type '{0}' have the '{1}' attribute but the 'Condition' attribute has a different search path declared."
            //        .FormatWith(CultureInfo.InvariantCulture, currentStructure.Descriptor.ClrType.Name, newContainerType));
            //}
            var property = candidates.SingleOrDefault(p => p.ConditionStackMode == EdiConditionStackMode.All ? p.Conditions.All(c => c.SatisfiedBy(searchResults[c.PathInternal]))
                                                                                                             : p.Conditions.Any(c => c.SatisfiedBy(searchResults[c.PathInternal])));

            if (property != null)
            {
                return(property);
            }
            return(null);
        }
示例#19
0
 internal virtual void WriteTokenInternal(EdiReader reader, bool writeChildren)
 {
     // TODO: Write using an open EDI reader (Copy).
     throw new NotImplementedException();
 }
示例#20
0
 /// <summary>
 /// Deserializes the EDI structure contained by the specified <see cref="EdiReader"/>.
 /// </summary>
 /// <param name="reader">The <see cref="EdiReader"/> that contains the EDI structure to deserialize.</param>
 /// <returns>The <see cref="object"/> being deserialized.</returns>
 public object Deserialize(EdiReader reader)
 {
     return(Deserialize(reader, null));
 }
示例#21
0
 /// <summary>
 /// Writes the current <see cref="EdiReader"/> token and its children.
 /// </summary>
 /// <param name="reader">The <see cref="EdiReader"/> to read the token from.</param>
 public void WriteToken(EdiReader reader) {
     WriteToken(reader, true);
 }
示例#22
0
        /// <summary>
        /// Tries the create container.
        /// </summary>
        /// <returns><c>true</c>, if create container was tryed, <c>false</c> otherwise.</returns>
        /// <param name="reader">Reader.</param>
        /// <param name="stack">Stack.</param>
        /// <param name="newContainer">New container.</param>
        internal bool TryCreateContainer(EdiReader reader, Stack <EdiStructure> stack, EdiStructureType newContainer)
        {
            var index = 0;

            if (stack.Count == 0)
            {
                return(false);
            }

            if (newContainer == EdiStructureType.SegmentGroup &&
                stack.Peek().Container >= EdiStructureType.SegmentGroup)
            {
                // strict hierarchy
                while (stack.Peek().Container > newContainer)
                {
                    var previous = stack.Pop(); // close this level
                }
                // nested hierarchy
                foreach (var level in stack)
                {
                    if (!level.IsGroup)
                    {
                        continue;
                    }
                    var groupStart  = level.Descriptor.SegmentGroupInfo.StartInternal;
                    var sequenceEnd = level.Descriptor.SegmentGroupInfo.SequenceEndInternal;
                    if (reader.Value.Equals(groupStart.Segment))
                    {
                        level.Close(); // Close this level
                        index = level.Index + 1;
                        break;
                    }
                    else if (reader.Value.Equals(sequenceEnd.Segment))
                    {
                        level.Close(); // Close this level
                        break;
                    }
                }
                if (stack.Any(s => s.IsClosed))
                {
                    var previous = stack.Peek();
                    do
                    {
                        previous = stack.Pop();
                    }while (!previous.IsClosed);
                }
            }
            else
            {
                // strict hierarchy
                while (stack.Peek().Container >= newContainer)
                {
                    var previous = stack.Pop(); // close this level
                    if (previous.Container == newContainer)
                    {
                        index = previous.Index + 1; // seed collection index
                    }
                }
            }

            var current  = stack.Peek();
            var property = default(EdiPropertyDescriptor);

            switch (newContainer)
            {
            case EdiStructureType.SegmentGroup:
                property = FindForCurrentSegment(reader, current, newContainer);
                break;

            case EdiStructureType.Segment:
                property = FindForCurrentSegment(reader, current, newContainer);
                break;

            case EdiStructureType.Element:
                property = FindForCurrentElement(reader, current, newContainer);
                break;

            default:
                property = FindForCurrentLogicalStructure(reader, current, newContainer);
                break;
            }
            if (property == null)
            {
                return(false);
            }
            object propValue = property.Info.GetValue(current.Instance, null);

            if (propValue == null)
            {
                if (property.Info.PropertyType.IsCollectionType())
                {
                    if (property.Info.PropertyType.IsArray)
                    {
                        var initalLength = 0;
                        propValue = Activator.CreateInstance(property.Info.PropertyType, initalLength);
                    }
                    else
                    {
                        var baseType    = typeof(List <>);
                        var genericType = baseType.MakeGenericType(property.Info.PropertyType.GetGenericArguments().First());
                        propValue = Activator.CreateInstance(genericType);
                    }
                }
                else
                {
                    propValue = Activator.CreateInstance(property.Info.PropertyType);
                }
                property.Info.SetValue(current.Instance, propValue);
            }
            if (propValue is IList)
            {
                var itemType = default(Type);
                var item     = default(object);
                if (property.Info.PropertyType.IsArray)
                {
                    itemType = property.Info.PropertyType.GetElementType();
                    item     = Activator.CreateInstance(itemType);
                    var newArray = Array.CreateInstance(itemType, ((IList)propValue).Count + 1);
                    var oldArray = ((Array)propValue);
                    Array.Copy(oldArray, newArray, oldArray.Length);
                    newArray.SetValue(item, newArray.Length - 1);
                    property.Info.SetValue(current.Instance, newArray);
                }
                else
                {
                    itemType = property.Info.PropertyType.GetGenericArguments().First();
                    item     = Activator.CreateInstance(itemType);
                    ((IList)propValue).Add(item);
                }
                propValue = item;
            }
            stack.Push(new EdiStructure(newContainer, propValue, index, current.CachedReads));
            return(true);
        }
示例#23
0
 /// <summary>
 /// Writes the current <see cref="EdiReader"/> token and its children.
 /// </summary>
 /// <param name="reader">The <see cref="EdiReader"/> to read the token from.</param>
 public void WriteToken(EdiReader reader)
 {
     WriteToken(reader, true);
 }
示例#24
0
 internal static EdiReaderException Create(EdiReader reader, string message)
 {
     return(Create(reader, message, null));
 }
示例#25
0
        internal bool TryCreateContainer(EdiReader reader, Stack <EdiStructure> stack, EdiStructureType newContainer)
        {
            var index = 0;

            if (stack.Count == 0)
            {
                return(false);
            }

            // clear once upon segment start. This is done here in order to keep any findings for future use
            if (newContainer == EdiStructureType.SegmentGroup || newContainer == EdiStructureType.Segment)
            {
                stack.Peek().CachedReads.Clear();
            }

            if (newContainer == EdiStructureType.SegmentGroup &&
                stack.Peek().StructureType >= EdiStructureType.SegmentGroup)
            {
                // strict hierarchy
                while (stack.Peek().StructureType > newContainer)
                {
                    var previous = stack.Pop(); // close this level
                }
                // nested hierarchy
                var readerSegment = reader.Value;
                foreach (var level in stack)
                {
                    if (!level.IsGroup)
                    {
                        continue;
                    }
                    var groupStart  = level.GroupStart;
                    var sequenceEnd = level.SequenceEnd;
                    if (groupStart.Segment.Equals(readerSegment))
                    {
                        if (PositionMatchesStructure(reader, level, readerSegment as string) ||          // if new occurance of my level or sibling found
                            FindForCurrentSegment(reader, level, EdiStructureType.SegmentGroup) == null) // if cannot advance either.

                        {
                            level.Close(); // Close this level
                            index = level.Index + 1;
                            continue;
                        }
                    }
                    else if (sequenceEnd.HasValue && sequenceEnd.Value.Segment.Equals(readerSegment))
                    {
                        level.Close(); // Close this level
                        continue;
                    }
                    else if (level.GroupMembers.Length > 1 && !level.GroupContains(readerSegment as string))
                    {
                        level.Close(); // Close this level
                        continue;
                    }
                }
                var clearUpTo = stack.Reverse().FirstOrDefault(x => x.IsClosed)?.Container;
                if (clearUpTo != null)
                {
                    while (stack.Peek() != clearUpTo)
                    {
                        stack.Pop();
                    }
                }
            }
            else
            {
                // strict hierarchy
                while (stack.Peek().StructureType >= newContainer)
                {
                    var previous = stack.Pop(); // close this level
                    if (previous.StructureType == newContainer)
                    {
                        index = previous.Index + 1; // seed collection index
                    }
                }
            }

            var current    = stack.Peek();
            var property   = default(EdiPropertyDescriptor);
            var childCache = default(Queue <EdiEntry>);

            switch (newContainer)
            {
            case EdiStructureType.SegmentGroup:
                property = FindForCurrentSegment(reader, current, newContainer);
                break;

            case EdiStructureType.Segment:
                property = FindForCurrentSegment(reader, current, newContainer);
                break;

            case EdiStructureType.Element:
                property = FindForCurrentElement(reader, current, newContainer, out childCache);
                break;

            default:
                property = FindForCurrentLogicalStructure(reader, current, newContainer);
                break;
            }
            if (property == null)
            {
                return(false);
            }
            var propValue = property.Info.GetValue(current.Instance, null);

            if (propValue == null)
            {
                if (property.Info.PropertyType.IsCollectionType())
                {
                    if (property.Info.PropertyType.IsArray)
                    {
                        var initalLength = 0;
                        propValue = Activator.CreateInstance(property.Info.PropertyType, initalLength);
                    }
                    else
                    {
                        var baseType    = typeof(List <>);
                        var genericType = baseType.MakeGenericType(property.Info.PropertyType.GetGenericArguments().First());
                        propValue = Activator.CreateInstance(genericType);
                    }
                }
                else
                {
                    propValue = Activator.CreateInstance(property.Info.PropertyType);
                }
                property.Info.SetValue(current.Instance, propValue);
            }
            if (propValue is IList)
            {
                var itemType = default(Type);
                var item     = default(object);
                if (property.Info.PropertyType.IsArray)
                {
                    itemType = property.Info.PropertyType.GetElementType();
                    item     = Activator.CreateInstance(itemType);
                    var newArray = Array.CreateInstance(itemType, ((IList)propValue).Count + 1);
                    var oldArray = ((Array)propValue);
                    Array.Copy(oldArray, newArray, oldArray.Length);
                    newArray.SetValue(item, newArray.Length - 1);
                    property.Info.SetValue(current.Instance, newArray);
                }
                else
                {
                    itemType = property.Info.PropertyType.GetGenericArguments().First();
                    item     = Activator.CreateInstance(itemType);
                    ((IList)propValue).Add(item);
                }
                propValue = item;
            }
            stack.Push(new EdiStructure(newContainer, current, property, propValue, index, childCache ?? current.CachedReads));
            return(true);
        }
示例#26
0
        /// <summary>
        /// Writes the current <see cref="EdiReader"/> token.
        /// </summary>
        /// <param name="reader">The <see cref="EdiReader"/> to read the token from.</param>
        /// <param name="writeChildren">A flag indicating whether the current token's children should be written.</param>
        public void WriteToken(EdiReader reader, bool writeChildren)
        {
            ValidationUtils.ArgumentNotNull(reader, nameof(reader));

            WriteTokenInternal(reader, writeChildren);
        }
示例#27
0
 internal virtual void WriteTokenInternal(EdiReader reader, bool writeChildren) {
     // TODO: Write using an open EDI reader (Copy).
     throw new NotImplementedException();
 }
示例#28
0
        /// <summary>
        /// Writes the current <see cref="EdiReader"/> token.
        /// </summary>
        /// <param name="reader">The <see cref="EdiReader"/> to read the token from.</param>
        /// <param name="writeChildren">A flag indicating whether the current token's children should be written.</param>
        public void WriteToken(EdiReader reader, bool writeChildren) {
            ValidationUtils.ArgumentNotNull(reader, nameof(reader));

            WriteTokenInternal(reader, writeChildren);
        }
示例#29
0
        internal virtual object DeserializeInternal(EdiReader reader, Type objectType)
        {
            reader.SuppressBadEscapeSequenceErrors = SuppressBadEscapeSequenceErrors;

            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var implicitSegments = new[] {
                reader.Grammar.FunctionalGroupHeaderTag,
                reader.Grammar.FunctionalGroupTrailerTag,
                reader.Grammar.InterchangeHeaderTag,
                reader.Grammar.InterchangeTrailerTag,
                reader.Grammar.MessageHeaderTag,
                reader.Grammar.MessageTrailerTag
            };

            // the output value
            object value = null;

            var stack = new Stack <EdiStructure>();
            var structuralComparer = default(EdiPathComparer);

            // If this is not a collection type asume this type is the interchange.
            if (!objectType.IsCollectionType())
            {
                while (reader.Read())
                {
                    if (reader.IsStartInterchange)
                    {
                        stack.Push(new EdiStructure(EdiStructureType.Interchange, Activator.CreateInstance(objectType)));
                    }
                    else if (reader.IsEndInterchange)
                    {
                        while (stack.Peek().StructureType != EdiStructureType.Interchange)
                        {
                            stack.Pop();
                        }
                        value = stack.Peek().Instance;
                    }

                    if (reader.IsStartMessage)
                    {
                        if (stack.Count == 0)
                        {
                            stack.Push(new EdiStructure(EdiStructureType.Message, Activator.CreateInstance(objectType)));
                        }
                        else
                        {
                            TryCreateContainer(reader, stack, EdiStructureType.Message);
                        }
                    }
                    else if (reader.IsEndMessage)
                    {
                        while (stack.Peek().StructureType > EdiStructureType.Message)
                        {
                            stack.Pop();
                        }
                        value = stack.Peek().Instance;
                    }

                    if (reader.IsStartGroup)
                    {
                        TryCreateContainer(reader, stack, EdiStructureType.Group);
                    }
                    else if (reader.IsEndGroup)
                    {
                        while (stack.Peek().StructureType > EdiStructureType.Group)
                        {
                            stack.Pop();
                        }
                        value = stack.Peek().Instance;
                    }
                    if (reader.TokenType == EdiToken.SegmentName)
                    {
                        while (true)
                        {
                            if (TryCreateContainer(reader, stack, EdiStructureType.SegmentGroup) ||
                                TryCreateContainer(reader, stack, EdiStructureType.Segment) ||
                                implicitSegments.Contains(reader.Value) ||
                                !AutoEndSegmentGroups)
                            {
                                break;
                            }

                            stack.Pop();

                            if (stack.Count == 0)
                            {
                                throw new EdiException(
                                          "Unable to deserialize segment {0}. No matching property found on stack.".FormatWith(
                                              reader.Culture,
                                              reader.Value));
                            }
                        }
                    }

                    if (reader.TokenType == EdiToken.ElementStart)
                    {
                        TryCreateContainer(reader, stack, EdiStructureType.Element);
                    }
                    else if (stack.Count > 0 && stack.Peek().CachedReads.Count > 0)
                    {
                        var allCachedReads = stack.Peek().CachedReads;
                        while (allCachedReads.Count > 0 && TryCreateContainer(reader, stack, EdiStructureType.Element))
                        {
                            if (stack.Peek().CachedReads.Any(x => x.HasValue))
                            {
                                PopulateValue(reader, stack, ref structuralComparer);
                            }
                        }
                    }

                    if (reader.TokenType == EdiToken.ComponentStart || (stack.Count > 0 && stack.Peek().CachedReads.Count > 0 && reader.TokenType.IsPrimitiveToken()))
                    {
                        PopulateValue(reader, stack, ref structuralComparer);
                    }
                }
            }
            // else if this is indeed a collection type this must be a collection of messages.
            else
            {
                throw new NotImplementedException("Collection types are not supported as the root Type. Try to wrap List of Messages inside a container type.");
            }

            return(value);
        }
示例#30
0
 /// <summary>
 /// Deserializes the EDI structure contained by the specified <see cref="EdiReader"/>
 /// into an instance of the specified type.
 /// </summary>
 /// <param name="reader">The <see cref="EdiReader"/> containing the object.</param>
 /// <typeparam name="T">The type of the object to deserialize.</typeparam>
 /// <returns>The instance of <typeparamref name="T"/> being deserialized.</returns>
 public T Deserialize <T>(EdiReader reader)
 {
     return((T)Deserialize(reader, typeof(T)));
 }
示例#31
0
        internal void PopulateValue(EdiReader reader, Stack <EdiStructure> stack, ref EdiPathComparer structuralComparer)
        {
            structuralComparer = new EdiPathComparer(reader.Grammar);
            var current     = stack.Peek();
            var maxLevelsUp = 0;
            var level       = 0;

            // stack always enumerates backwards so this is a search upwards :-)
            // we search only if we need to have more than one property populated with the value from the reader.
            // maxLevelsUp = zero means only the current level (quicker).
            foreach (var structure in stack)
            {
                if (level++ > maxLevelsUp)
                {
                    break;
                }
                var typeDescriptor = structure.Descriptor;
                var valueProps     = typeDescriptor.Properties
                                     .Where(p => p.ValueInfo != null &&
                                            p.Path != null &&
                                            (((EdiPath)p.Path).Equals(reader.Path) || structure.CachedReads.ContainsPath(p.Path))
                                            ).OrderBy(p => (EdiPath)p.Path, structuralComparer).ToArray();

                for (var i = 0; i < valueProps.Length; i++)
                {
                    var descriptor = valueProps[i];
                    // should I use the text reader?
                    // Values must be read only once on first pass!
                    // Otherwise the reader position moves forward
                    // and the serializer gets out of sync.
                    var useTheReader = current == structure && reader.TokenType == EdiToken.ComponentStart && ((EdiPath)descriptor.Path).Equals(reader.Path) && i == 0;
                    switch (ConvertUtils.GetTypeCode(descriptor.Info.PropertyType))
                    {
                    case PrimitiveTypeCode.Empty: break;

                    case PrimitiveTypeCode.Object:
                        PopulateObjectValue(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.Char:
                    case PrimitiveTypeCode.CharNullable:
                        PopulateCharValue(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.Boolean:
                    case PrimitiveTypeCode.BooleanNullable:
                        PopulateBooleanValue(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.SByte: break;

                    case PrimitiveTypeCode.SByteNullable: break;

                    case PrimitiveTypeCode.Int16: break;

                    case PrimitiveTypeCode.Int16Nullable: break;

                    case PrimitiveTypeCode.UInt16: break;

                    case PrimitiveTypeCode.UInt16Nullable: break;

                    case PrimitiveTypeCode.Int32:
                    case PrimitiveTypeCode.Int32Nullable:
                        PopulateInt32Value(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.Byte: break;

                    case PrimitiveTypeCode.ByteNullable: break;

                    case PrimitiveTypeCode.UInt32: break;

                    case PrimitiveTypeCode.UInt32Nullable: break;

                    case PrimitiveTypeCode.Int64: break;

                    case PrimitiveTypeCode.Int64Nullable: break;

                    case PrimitiveTypeCode.UInt64: break;

                    case PrimitiveTypeCode.UInt64Nullable: break;

                    case PrimitiveTypeCode.Single:
                    case PrimitiveTypeCode.SingleNullable:
                    case PrimitiveTypeCode.Double:
                    case PrimitiveTypeCode.DoubleNullable:
                    case PrimitiveTypeCode.Decimal:
                    case PrimitiveTypeCode.DecimalNullable:
                        PopulateDecimalValue(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.DateTime:
                    case PrimitiveTypeCode.DateTimeNullable:
                        PopulateDateTimeValue(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.DateTimeOffset: break;

                    case PrimitiveTypeCode.DateTimeOffsetNullable: break;

                    case PrimitiveTypeCode.Guid: break;

                    case PrimitiveTypeCode.GuidNullable: break;

                    case PrimitiveTypeCode.TimeSpan: break;

                    case PrimitiveTypeCode.TimeSpanNullable: break;

                    case PrimitiveTypeCode.BigInteger: break;

                    case PrimitiveTypeCode.BigIntegerNullable: break;

                    case PrimitiveTypeCode.Uri: break;

                    case PrimitiveTypeCode.String:
                        PopulateStringValue(reader, structure, descriptor, useTheReader);
                        break;

                    case PrimitiveTypeCode.Bytes: break;

                    case PrimitiveTypeCode.DBNull: break;
                    }
                }
            }
        }
示例#32
0
 /// <summary>
 /// Deserializes the EDI structure contained by the specified <see cref="EdiReader"/>
 /// into an instance of the specified type.
 /// </summary>
 /// <param name="reader">The <see cref="EdiReader"/> containing the object.</param>
 /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
 /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
 public object Deserialize(EdiReader reader, Type objectType)
 {
     return(DeserializeInternal(reader, objectType));
 }
示例#33
0
 internal static EdiReaderException Create(EdiReader reader, string message, Exception ex)
 {
     return(Create(reader as IEdiLineInfo, reader.Path, message, ex));
 }