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)); }
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); } } }
/// <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); }
/// <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); }
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)); } } }
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); } }
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); }
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); }
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); }
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); }
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); } }
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]); } }
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; }
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); }
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); }
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; }
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); }
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); }
internal virtual void WriteTokenInternal(EdiReader reader, bool writeChildren) { // TODO: Write using an open EDI reader (Copy). throw new NotImplementedException(); }
/// <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)); }
/// <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); }
/// <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); }
internal static EdiReaderException Create(EdiReader reader, string message) { return(Create(reader, message, null)); }
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); }
/// <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); }
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); }
/// <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))); }
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; } } } }
/// <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)); }
internal static EdiReaderException Create(EdiReader reader, string message, Exception ex) { return(Create(reader as IEdiLineInfo, reader.Path, message, ex)); }