/// <summary> /// It parses the information in the parser context and builds the field. /// </summary> /// <param name="parserContext"> /// It's the parser context. /// </param> /// <returns> /// The new field built with the information found in the parser context. /// </returns> public override Field Parse(ref ParserContext parserContext) { // If MinValue, at this moment the length hasn't been decoded. if (parserContext.DecodedLength == int.MinValue) { if (!_lengthManager.EnoughData(ref parserContext)) { // Insufficient data to parse length, return null. return(null); } // Save length in parser context just in case field value // can't be parsed at this time (more data needed). parserContext.DecodedLength = _lengthManager.ReadLength(ref parserContext); } if (parserContext.DataLength < _encoder.GetEncodedLength( parserContext.DecodedLength)) { // Insufficient data to parse field value, return null. return(null); } Message message = null; if (parserContext.DecodedLength > 0) { ParserContext innerMsgParserContext = new ParserContext(parserContext.DecodedLength); innerMsgParserContext.Write( _encoder.Decode(ref parserContext, parserContext.DecodedLength)); message = _messageFormatter.Parse(ref innerMsgParserContext); if (message == null) { throw new MessagingException(SR.CantParseInnerMessage); } } // Create the new messaging component with parsing context data. InnerMessageField field = new InnerMessageField(FieldNumber, message); _lengthManager.ReadLengthTrailer(ref parserContext); return(field); }
/// <summary> /// It parses the data contained in the parser context. /// </summary> /// <param name="parserContext"> /// It's the context holding the information to produce a new message instance. /// </param> /// <returns> /// The parsed message, or a null reference if the data contained in the context /// is insufficient to produce a new message. /// </returns> public virtual Message Parse(ref ParserContext parserContext) { // Create a new message if we are parsing a new one. if (parserContext.CurrentMessage == null) { parserContext.CurrentMessage = NewMessage(); // The message must known its formatter for message.ToString() parserContext.CurrentMessage.Formatter = this; } // Remove packet header data. if ((_packetHeader != null) && !parserContext.PacketHeaderDataStripped) { parserContext.Consumed(_packetHeader.Length); parserContext.PacketHeaderDataStripped = true; } // Parse header if we have a header formatter. if (_headerFormatter != null) { // Check if the header hasn't been parsed yet. if (parserContext.CurrentMessage.Header == null) { try { parserContext.CurrentMessage.Header = _headerFormatter.Parse(ref parserContext); } catch (Exception e) { throw new MessagingException(SR.CantParseMessageHeader, e); } // If null, more data is needed. if (parserContext.CurrentMessage.Header == null) { return(null); } parserContext.ResetDecodedLength(); } } // Allow subclasses to get information between header data and // fields data. if (!parserContext.Signaled) { if (!BeforeFieldsParsing(parserContext.CurrentMessage, ref parserContext)) { return(null); } parserContext.Signaled = true; } for (int i = parserContext.CurrentField; i <= _fieldsFormatters.MaximumFieldFormatterNumber; i++) { // If we have a bitmap use it to detect present fields, // otherwise parse known message formatter fields. if (parserContext.CurrentBitMap != null) { // Check if field number is out of bitmap bounds. if (i > parserContext.CurrentBitMap.UpperFieldNumber) { // Locate another bitmap. bool found = false; for (int j = parserContext.CurrentBitMap.FieldNumber + 1; j < i; j++) { if (parserContext.CurrentMessage.Fields.Contains(j)) { Field field = parserContext.CurrentMessage.Fields[j]; if (field is BitMapField) { // Another bitmap found. parserContext.CurrentBitMap = ( BitMapField)field; found = true; break; } } } if (!found) { parserContext.CurrentBitMap = null; // No more bitmaps, continue with posible mandatory fields // (start from last field covered by known bitmaps, plus one). i = ((BitMapFieldFormatter) (_fieldsFormatters[_bitmaps[_bitmaps.Length - 1]])).UpperFieldNumber + 1; continue; } } if (!parserContext.CurrentBitMap[i]) { // Save current field number in context. parserContext.CurrentField = i; // Bit is not set, field is not present in the received data. continue; } } // Save current field number in context. parserContext.CurrentField = i; if (_fieldsFormatters.Contains(i)) { // Get field formatter. FieldFormatter fieldFormatter = _fieldsFormatters[i]; Field field; try { // to parse field. field = fieldFormatter.Parse(ref parserContext); } catch (Exception e) { throw new MessagingException(SR.CantParseField(i), e); } if (field == null) { if (Logger.IsDebugEnabled) { Logger.Debug(SR.MoreDataNeeded); } // More data needed to parse message. return(null); } else { parserContext.CurrentMessage.Fields.Add(field); // Set parent message. if (field is InnerMessageField) { InnerMessageField innerMessageField = field as InnerMessageField; Message innerMessage = innerMessageField.Value as Message; if (innerMessage != null) { innerMessage.Parent = parserContext.CurrentMessage; } } if (Logger.IsDebugEnabled) { if (field is BitMapField) { Logger.Debug(SR.DecodedBitmap(field.FieldNumber, field.ToString())); } else { Logger.Debug(SR.DecodedField(field.FieldNumber, field.ToString())); } } parserContext.ResetDecodedLength(); // If this is the first located bitmap, save it. if ((parserContext.CurrentBitMap == null) && (field is BitMapField)) { parserContext.CurrentBitMap = ( BitMapField)field; } } } else { if (parserContext.CurrentBitMap != null) { // A field is present in current bitmap, but message formatter // can't parse it because field formatter isn't present. throw new MessagingException(SR.UnknownFormatter(i)); } } } // We have a new message, get it and initialize parsing context. Message parsedMessage = parserContext.CurrentMessage; // Reset parser context. parserContext.MessageHasBeenConsumed(); return(parsedMessage); }
/// <summary> /// It formats a message. /// </summary> /// <param name="message"> /// It's the message to be formatted. /// </param> /// <param name="formatterContext"> /// It's the formatter context to be used in the format. /// </param> public virtual void Format(Message message, ref FormatterContext formatterContext) { formatterContext.CurrentMessage = message; // Write header. if (_packetHeader != null) { formatterContext.Write(_packetHeader); } // Format header if we have one header formatter. if (_headerFormatter != null) { try { _headerFormatter.Format(message.Header, ref formatterContext); } catch (Exception e) { throw new MessagingException(SR.CantFormatMessageHeader, e); } } // Allow subclasses to put information between header data and // fields data. BeforeFieldsFormatting(message, ref formatterContext); // If bitmaps are present in the message formatter, check if we // must add them to the message. bool atLeastOne = false; int firstBitmap = -1; for (int i = _bitmaps.Length - 1; (i >= 0) && (_bitmaps[i] >= 0); i--) { firstBitmap = i; if (message.Fields.Contains(_bitmaps[i])) { // Check if present field is a bitmap. if (!(message[_bitmaps[i]] is BitMapField)) { throw new MessagingException(SR.FieldMustBeBitmap(_bitmaps[i])); } atLeastOne = true; } else { // Get bitmap from field formatters collection. BitMapFieldFormatter bitmap = ( BitMapFieldFormatter)_fieldsFormatters[_bitmaps[i]]; // Add bitmap to message if required. if (message.Fields.ContainsAtLeastOne(bitmap.LowerFieldNumber, bitmap.UpperFieldNumber)) { message.Fields.Add(new BitMapField(bitmap.FieldNumber, bitmap.LowerFieldNumber, bitmap.UpperFieldNumber)); atLeastOne = true; } } } if (!atLeastOne && firstBitmap > -1) { // In a bitmaped message, at least the first bitmap must be present. BitMapFieldFormatter bitmap = ( BitMapFieldFormatter )_fieldsFormatters[_bitmaps[firstBitmap]]; message.Fields.Add(new BitMapField(bitmap.FieldNumber, bitmap.LowerFieldNumber, bitmap.UpperFieldNumber)); } // Correct bitmap values. message.CorrectBitMapsValues(); // Format fields. for (int i = 0; i <= message.Fields.MaximumFieldNumber; i++) { if (message.Fields.Contains(i)) { // If we haven't the field formatter, throw an exception. if (!_fieldsFormatters.Contains(i)) { throw new MessagingException(SR.UnknownFieldFormatter(i)); } // Set parent message. if (message.Fields[i] is InnerMessageField) { InnerMessageField innerMessageField = message.Fields[i] as InnerMessageField; if (innerMessageField != null) { Message innerMessage = innerMessageField.Value as Message; if (innerMessage != null) { innerMessage.Parent = message; } } } try { _fieldsFormatters[i].Format(message.Fields[i], ref formatterContext); } catch (Exception e) { throw new MessagingException(SR.CantFormatField(i), e); } } } }