/// <summary> /// Validate Iso Field Content or Throws an Invalid Format Exception /// </summary> /// <param name="fieldProperties">iso field properties</param> public virtual void EnsureContent(IIsoFieldProperties fieldProperties) { if (fieldProperties.Value != null) { switch (fieldProperties.ContentType) { case ContentType.N: if (!_regexNumeric.IsMatch(fieldProperties.Value)) { throw new FormatException($"{fieldProperties.Position} = {fieldProperties.Value} does not have a numeric value"); } break; case ContentType.ANS: case ContentType.AN: if (!_regexAlphaNumeric.IsMatch(fieldProperties.Value)) { throw new FormatException($"{fieldProperties.Position} = {fieldProperties.Value} does not have a alpha numeric values"); } break; default: break; } } }
/// <summary> /// Gets Custom Field Len according to Len Bytes /// </summary> /// <param name="isoFieldProperties">IIsoFieldProperties implementation</param> /// <param name="isoMessageBytes">iso message bytes</param> /// <param name="currentPos">current parsing position</param> /// <returns>length of Custom Field parsed</returns> internal static int TagFieldLength(this IIsoFieldProperties isoFieldProperties, byte[] isoMessageBytes, ref int currentPos) { var fieldLen = 0; var lengthBytes = (int)isoFieldProperties.LengthType; if (isoFieldProperties.LenDataType == DataType.ASCII) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldProperties.Encoding); fieldLen = int.Parse(lenValue); } else if (isoFieldProperties.LenDataType == DataType.HEX) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldProperties.Encoding); fieldLen = lenValue.HexValueToInt(); } else if (isoFieldProperties.LenDataType == DataType.BCD) { lengthBytes = lengthBytes - 1; var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToArray().BDCToString(); fieldLen = int.Parse(lenValue); } currentPos = currentPos + lengthBytes; return(fieldLen); }
/// <summary> /// Adds message bytes the rest of the Fields /// </summary> /// <param name="orderedFieldPositions">fields that need to be builded</param> /// <param name="message">message instance</param> /// <param name="messageBytes">message bytes as Ref</param> private void BuildFields(IEnumerable <int> orderedFieldPositions, IIsoMessage message, ref List <byte> messageBytes) { foreach (var fieldPosition in orderedFieldPositions) { IIsoFieldProperties fieldProperties = message.GetFieldByPosition(fieldPosition); if (fieldProperties != null) { var valueForMessage = fieldProperties.Value; _validator?.EnsureContent(fieldProperties); _validator?.EnsureLength(fieldProperties); if (fieldProperties is IsoField isoField && isoField.Tags != null) { IEnumerable <byte> customFieldBytes = BuildTagFields(isoField); messageBytes.AddRange(fieldProperties.BuildCustomFieldLentgh(customFieldBytes.Count().ToString())); messageBytes.AddRange(customFieldBytes); } else { messageBytes.AddRange(fieldProperties.BuildFieldValue(valueForMessage.ToString())); } } }
/// <summary> /// Updates Iso Field Value /// </summary> /// <param name="position">field position</param> /// <param name="value">value of field to set</param> public virtual void SetFieldValue(int position, string value) { IIsoFieldProperties fieldForUpdate = GetFieldByPosition(position); if (fieldForUpdate != null) { fieldForUpdate.Value = value; } }
/// <summary> /// Parse BitMap of Message to be Parsed /// </summary> /// <param name="bitMapProperties">bit map field properties</param> /// <param name="isoMessageBytes">messageBytes</param> /// <param name="currentPos">position to Read</param> /// <returns>BitMap Value</returns> private string ParseBitMap(IIsoFieldProperties bitMapProperties, byte[] isoMessageBytes, ref int currentPos) { var bitMap = bitMapProperties.GetFieldValue(isoMessageBytes, ref currentPos); //Second BitMap Exists Read More Data if (bitMap.ToBinaryStringFromHex().First() == '1') { return(bitMap + bitMapProperties.GetFieldValue(isoMessageBytes, ref currentPos)); } return(bitMap); }
/// <summary> /// Gets Iso Field Tag Value /// </summary> /// <param name="position">field position</param> /// <param name="tagName">tag name of Tag field</param> public virtual string GetTagValue(int position, string tagName) { IIsoFieldProperties fieldProperties = GetFieldByPosition(position); if (fieldProperties != null) { if (fieldProperties is IsoField isoField && isoField.Tags != null) { Tag tag = isoField.Tags.FirstOrDefault(p => p.TagName == tagName); return(tag?.Value); } } return(null); }
/// <summary> /// Updates Iso Field Tag Value /// </summary> /// <param name="position">field position</param> /// <param name="tagName">tag name of Tag field</param> /// <param name="value">value of tag to set</param> public virtual void SetTagValue(int position, string tagName, string value) { IIsoFieldProperties fieldProperties = GetFieldByPosition(position); if (fieldProperties != null) { if (fieldProperties is IsoField isoField && isoField.Tags != null) { Tag tagField = isoField.Tags.FirstOrDefault(p => p.TagName == tagName); if (tagField != null) { tagField.Value = value; } } } }
/// <summary> /// Validates Iso Field Len according to properties of Field or Throws an Invalid Format Exception /// </summary> /// <param name="fieldProperties">iso field properties</param> public virtual void EnsureLength(IIsoFieldProperties fieldProperties) { if (fieldProperties.LengthType == LengthType.FIXED) { if (fieldProperties.Value?.Length != fieldProperties.MaxLen) { throw new FormatException($"{fieldProperties.Position} has to be exactly {fieldProperties.MaxLen} chars <> {fieldProperties.Value}"); } } else { if (fieldProperties.Value?.Length <= fieldProperties.MaxLen) { throw new FormatException($"{fieldProperties.Position} can be at maximum {fieldProperties.MaxLen} chars < {fieldProperties.Value}"); } } }
internal static byte[] BuildCustomFieldLentgh(this IIsoFieldProperties isoFieldAttribute, string lenValue) { lenValue = lenValue.PadLeft((int)isoFieldAttribute.LengthType, '0'); switch (isoFieldAttribute.LenDataType) { case DataType.ASCII: return(lenValue.FromASCIIToBytes(isoFieldAttribute.Encoding)); case DataType.HEX: var intLen = int.Parse(lenValue); return(intLen.IntToHexValue((int)isoFieldAttribute.LengthType).FromASCIIToBytes(isoFieldAttribute.Encoding)); case DataType.BCD: return(lenValue.ConvertToBinaryCodedDecimal(false, (int)isoFieldAttribute.LengthType - 1)); default: throw new BuildFieldException(isoFieldAttribute, $"Cannot Parse Length value for {isoFieldAttribute?.Position} and Len Type {isoFieldAttribute?.LenDataType}"); } }
/// <summary> /// Builds BitMap value of Message to Send /// </summary> /// <param name="bitMapField">bitmap field properties</param> /// <param name="orderedFields">ordered fields positions</param> /// <returns>byte array bitMap value</returns> private byte[] BuildBitMap(IIsoFieldProperties bitMapField, IEnumerable <int> orderedFields) { var secondBitRequired = orderedFields.Any(pos => pos > 65 && pos < 128); char[] bitmapBinaryArray = null; if (secondBitRequired) { bitmapBinaryArray = new char[129]; bitmapBinaryArray[1] = '1'; } else { bitmapBinaryArray = new char[65]; bitmapBinaryArray[1] = '0'; } //Building BitMap for (var i = 2; i < bitmapBinaryArray.Length; i++) { if (orderedFields.Contains(i)) { bitmapBinaryArray[i] = '1'; } else { bitmapBinaryArray[i] = '0'; } } var bitmapString = new string(bitmapBinaryArray); var bitMap = Convert.ToInt64(bitmapString.Substring(1, 64), 2).ToString("X").PadLeft(16, '0'); if (secondBitRequired) { bitMap = bitMap + Convert.ToInt64(bitmapString.Substring(65, 64), 2).ToString("X").PadLeft(16, '0'); } return(bitMapField.BuildFieldValue(bitMap)); }
/// <summary> /// Contructor of Exception /// </summary> /// <param name="isoFieldAttr">iso field Attribute</param> /// <param name="innerEx">Inner exception details</param> /// <param name="exMessage">error message</param> public BuildFieldException(IIsoFieldProperties isoFieldAttr, string exMessage, Exception innerEx) : base(exMessage, innerEx) { IsoFieldData = isoFieldAttr; }
/// <summary> /// Build Bytes from Field Value /// </summary> /// <param name="isoFieldProperties">IIsoFieldProperties implementation</param> /// <param name="fieldValue">field value</param> /// <returns>byte array value of Field</returns> internal static byte[] BuildFieldValue(this IIsoFieldProperties isoFieldProperties, string fieldValue) { var fieldBytes = new List <byte>(); try { switch (isoFieldProperties.LengthType) { case LengthType.FIXED: if (fieldValue.Length < isoFieldProperties.MaxLen) { fieldValue = fieldValue?.PadRight(isoFieldProperties.MaxLen); } break; case LengthType.LVAR: case LengthType.LLVAR: case LengthType.LLLVAR: if (isoFieldProperties.LenDataType == DataType.ASCII) { var valueLen = fieldValue?.Length.ToString().PadLeft((int)isoFieldProperties.LengthType, '0'); fieldBytes.AddRange(valueLen.FromASCIIToBytes(isoFieldProperties.Encoding)); } else if (isoFieldProperties.LenDataType == DataType.HEX) { var valueLen = fieldValue?.Length.IntToHexValue((int)isoFieldProperties.LengthType); fieldBytes.AddRange(valueLen.FromASCIIToBytes(isoFieldProperties.Encoding)); } else if (isoFieldProperties.LenDataType == DataType.BCD) { var valueLen = fieldValue?.Length.ToString().ConvertToBinaryCodedDecimal(false); fieldBytes.AddRange(valueLen); } break; default: throw new BuildFieldException(isoFieldProperties, $"Cannot Parse Length value for {isoFieldProperties?.Position} and Len Type {isoFieldProperties?.LenDataType}"); } switch (isoFieldProperties.DataType) { case DataType.BIN: fieldBytes.AddRange(fieldValue.ToBinaryStringFromHex().ToBytesFromBinaryString()); break; case DataType.BCD: if (fieldValue.Length % 2 == 1) { fieldValue += '0'; } var bcdValue = fieldValue.ConvertToBinaryCodedDecimal(false); fieldBytes.AddRange(bcdValue); break; case DataType.ASCII: case DataType.HEX: fieldBytes.AddRange(fieldValue.FromASCIIToBytes(isoFieldProperties.Encoding)); break; default: throw new BuildFieldException(isoFieldProperties, $"Cannot Parse value for {isoFieldProperties?.Position} and Type {isoFieldProperties?.DataType}"); } } catch (Exception ex) { throw new BuildFieldException(isoFieldProperties, $"Cannot Parse value for {isoFieldProperties?.Position} and Type {isoFieldProperties?.DataType}", ex); } return(fieldBytes.ToArray()); }
/// <summary> /// Parses bytes value to an object value /// </summary> /// <param name="isoFieldProperties">IIsoFieldProperties implementation</param> /// <param name="isoMessageBytes">whole Message bytes</param> /// <param name="currentPos">current Position of Parsed Message bytes, passed as a Reference</param> /// <returns>field object value</returns> internal static string GetFieldValue(this IIsoFieldProperties isoFieldProperties, byte[] isoMessageBytes, ref int currentPos) { var fieldLen = 0; var fieldValue = string.Empty; var lengthBytes = (int)isoFieldProperties.LengthType; try { switch (isoFieldProperties.LengthType) { case LengthType.FIXED: case LengthType.LVAR: fieldLen = isoFieldProperties.MaxLen; break; case LengthType.LLVAR: case LengthType.LLLVAR: if (isoFieldProperties.LenDataType == DataType.ASCII) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldProperties.Encoding); fieldLen = int.Parse(lenValue); } else if (isoFieldProperties.LenDataType == DataType.HEX) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldProperties.Encoding); fieldLen = lenValue.HexValueToInt(); } else if (isoFieldProperties.LenDataType == DataType.BCD) { lengthBytes = lengthBytes - 1; //BCD Always one byte less for Lentgh var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToArray().BDCToString(); fieldLen = int.Parse(lenValue); } break; default: throw new ParseFieldException(isoFieldProperties, $"Cannot Parse Length value for {isoFieldProperties?.Position} and Len Type {isoFieldProperties?.LenDataType}"); } currentPos = currentPos + lengthBytes; switch (isoFieldProperties.DataType) { case DataType.BIN: fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen).ToStringFromBinary(); currentPos = currentPos + fieldLen; break; case DataType.BCD: if (isoFieldProperties.ContentType != ContentType.B) { fieldLen = fieldLen % 2 == 1 ? (fieldLen / 2 + 1) : fieldLen / 2; } fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen).ToArray().BDCToString(); currentPos = currentPos + fieldLen; break; case DataType.ASCII: fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen).ToASCIIString(isoFieldProperties.Encoding); currentPos = currentPos + fieldLen; break; case DataType.HEX: fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen * 2).HexBytesToString(); currentPos = currentPos + (fieldLen * 2); break; default: throw new ParseFieldException(isoFieldProperties, $"Cannot Parse value for {isoFieldProperties?.Position} and Type {isoFieldProperties?.DataType}"); } } catch (Exception ex) { throw new ParseFieldException(isoFieldProperties, $"Cannot Parse value for {isoFieldProperties?.Position} and Type {isoFieldProperties?.DataType}", ex); } return(fieldValue); }
/// <summary> /// Contructor of Exception /// </summary> /// <param name="isoFieldAttr">iso field Attribute</param> /// <param name="exMessage">error message</param> public ParseFieldException(IIsoFieldProperties isoFieldAttr, string exMessage) : base(exMessage) { IsoFieldData = isoFieldAttr; }
/// <summary> /// Updates Iso Field Value /// </summary> /// <param name="position">field position</param> /// <returns>Field Value</returns> public virtual string GetFieldValue(int position) { IIsoFieldProperties field = GetFieldByPosition(position); return(field?.Value); }