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