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