/// <summary>
        /// Agrega un formateador de campo a la colección.
        /// </summary>
        /// <param name="fieldFormatter">Es el formateador de campo a agregar.
        /// </param>
        /// <remarks>Si existe es reemplazado.</remarks>
        public void Add(FieldFormatter fieldFormatter)
        {
            if (_fieldsFormatters.Contains(fieldFormatter.FieldNumber))
            {
                Remove(fieldFormatter.FieldNumber);
            }

            _fieldsFormatters[fieldFormatter.FieldNumber] = fieldFormatter;

            if (Added != null)
            {
                Added(this, new FieldFormatterEventArgs(fieldFormatter));
            }

            if (_maxField < fieldFormatter.FieldNumber)
            {
                _maxField = fieldFormatter.FieldNumber;
            }
        }
        /// <summary>
        /// Elimina el formateador de campo cuyo número coincida con el
        /// especificado.
        /// </summary>
        /// <param name="fieldNumber">
        /// Es el número de campo del formateador de campo que se desea
        /// eliminar de la colección.
        /// </param>
        public void Remove(int fieldNumber)
        {
            FieldFormatter fieldFormatter = null;

            if (Removed != null)
            {
                if (_fieldsFormatters.Contains(fieldNumber))
                {
                    fieldFormatter = this[fieldNumber];
                }
            }

            _fieldsFormatters.Remove(fieldNumber);

            if (fieldFormatter != null)
            {
                Removed(this, new FieldFormatterEventArgs(fieldFormatter));
            }

            if (fieldNumber == _maxField)
            {
                _maxFieldDirty = true;
            }
        }
        /// <summary>
        /// Asigna los campos del mensaje en base a las propiedades del
        /// objeto dado.
        /// </summary>
        /// <param name="message">
        /// Es el mensaje al que se asignan sus campos.
        /// </param>
        /// <param name="fieldsContainer">
        /// Es el objeto del que se obtienen los valores para los campos.
        /// </param>
        /// <remarks>
        /// Este método recorre todas las propiedades visibles de
        /// fieldsContainer, buscando aquellas a las que se le aplico el
        /// atributo <see cref="FieldAttribute"/>. El valor de las
        /// propiedades que encuentra, es asignado al valor del campo
        /// cuyo número corresponde con el indicado en el atributo
        /// mencionado.
        /// El valor es formateado empleando el formateador de valor
        /// indicado en el formateador de campo que corresponde al número
        /// del campo. Si el formateador de campo no tiene un formateador
        /// de valor, se emplea el método ToString sobre el valor de la
        /// propiedad.
        /// Para invocar este método, es necesario que el mensaje conozca
        /// su fomateador, pues de éste se obtienen los formateadores de los
        /// valores de los campos.
        /// </remarks>
        /// <exception cref="NullReferenceException">
        /// El parámetro indicado es nulo.
        /// </exception>
        public void AssignFields(Message message, object fieldsContainer)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (fieldsContainer == null)
            {
                throw new ArgumentNullException("fieldsContainer");
            }

            foreach (PropertyInfo propertyInfo in
                     fieldsContainer.GetType().GetProperties(
                         BindingFlags.Public | BindingFlags.Instance))
            {
                // Property must be readable and not indexed.
                if ((propertyInfo.CanRead) &&
                    (propertyInfo.GetIndexParameters().Length == 0))
                {
                    // Get FieldAttribute.
                    FieldAttribute fieldAttribute =
                        GetFieldAttribute(propertyInfo);

                    if (fieldAttribute != null)
                    {
                        if (_fieldsFormatters.Contains(
                                fieldAttribute.FieldNumber))
                        {
                            FieldFormatter fieldFormatter =
                                _fieldsFormatters[fieldAttribute.FieldNumber];

                            if (fieldFormatter is StringFieldFormatter)
                            {
                                if ((( StringFieldFormatter)
                                     (fieldFormatter)).ValueFormatter == null)
                                {
                                    // Field formatter doesn't provide a valid value
                                    // formatter, default is ToString method.
                                    message.Fields.Add(fieldAttribute.FieldNumber,
                                                       propertyInfo.GetValue(fieldsContainer,
                                                                             null).ToString());
                                }
                                else
                                {
                                    // Format property value with value formatter.
                                    message.Fields.Add(fieldAttribute.FieldNumber,
                                                       (( StringFieldFormatter)
                                                        (fieldFormatter)).ValueFormatter.Format(
                                                           propertyInfo.GetValue(fieldsContainer,
                                                                                 null)));
                                }
                            }
                            else
                            {
                                // Field formatter isn't a StringFieldFormatter,
                                // default is ToString method.
                                message.Fields.Add(fieldAttribute.FieldNumber,
                                                   propertyInfo.GetValue(fieldsContainer,
                                                                         null).ToString());
                            }
                        }
                        else
                        {
                            // Field formatter doesn't include a valid field
                            // value formatter, default is ToString method.
                            message.Fields.Add(fieldAttribute.FieldNumber,
                                               propertyInfo.GetValue(fieldsContainer,
                                                                     null).ToString());
                        }
                    }
                }
            }
        }
        /// <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>
        /// Asigna a las propiedades del objeto dado, valores tomados de los
        /// valores de los campos del mensaje.
        /// </summary>
        /// <param name="message">
        /// Es el mensaje al que se asignan sus campos.
        /// </param>
        /// <param name="fieldsContainer">
        /// Es el objeto al que se asignan sus propiedades con los valores
        /// de los campos del mensaje.
        /// </param>
        /// <remarks>
        /// Este método recorre todas las propiedades visibles de
        /// fieldsContainer, buscando aquellas a las que se le aplico el
        /// atributo <see cref="FieldAttribute"/>. El valor de las
        /// propiedades que encuentra, es asignado con el valor del campo
        /// cuyo número corresponde con el indicado en el atributo
        /// mencionado.
        /// El valor es convertido empleando el formateador de valor
        /// indicado en el formateador de campo que corresponde al número
        /// del campo.
        /// Para invocar este método, es necesario que el mensaje conozca
        /// su fomateador, pues de éste se obtienen los formateadores de los
        /// valores de los campos.
        /// </remarks>
        /// <exception cref="NullReferenceException">
        /// El mensaje no tiene asignado un formateador de mensajes.
        /// </exception>
        /// <exception cref="MessagingException">
        /// No se ha podido convertir el valor del campo, para asignarlo
        /// a la propiedad indicada.
        /// </exception>
        public void RetrieveFields(Message message, object fieldsContainer)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (fieldsContainer == null)
            {
                throw new ArgumentNullException("fieldsContainer");
            }

            foreach (PropertyInfo propertyInfo in
                     fieldsContainer.GetType().GetProperties(
                         BindingFlags.Public | BindingFlags.Instance))
            {
                // Property must be writable and not indexed.
                if ((propertyInfo.CanWrite) &&
                    (propertyInfo.GetIndexParameters().Length == 0))
                {
                    // Get FieldAttribute.
                    FieldAttribute fieldAttribute =
                        GetFieldAttribute(propertyInfo);

                    if (fieldAttribute != null)
                    {
                        if (message.Fields.Contains(fieldAttribute.FieldNumber) &&
                            _fieldsFormatters.Contains(fieldAttribute.FieldNumber))
                        {
                            FieldFormatter fieldFormatter =
                                _fieldsFormatters[fieldAttribute.FieldNumber];

                            if (fieldFormatter is StringFieldFormatter)
                            {
                                if ((( StringFieldFormatter)
                                     (fieldFormatter)).ValueFormatter == null)
                                {
                                    // Field formatter doesn't provide a valid value
                                    // formatter, try default convertion.
                                    ApplyDefaultConvertion(fieldsContainer,
                                                           propertyInfo, fieldAttribute,
                                                           message[fieldAttribute.FieldNumber].Value);
                                }
                                else
                                {
                                    propertyInfo.SetValue(fieldsContainer,
                                                          (( StringFieldFormatter)
                                                           (fieldFormatter)).ValueFormatter.Parse(
                                                              propertyInfo.PropertyType,
                                                              message[fieldAttribute.FieldNumber].ToString()), null);
                                }
                            }
                            else
                            {
                                // Field formatter isn't a StringFieldFormatter,
                                // try default convertion.
                                ApplyDefaultConvertion(fieldsContainer,
                                                       propertyInfo, fieldAttribute,
                                                       message[fieldAttribute.FieldNumber].Value);
                            }
                        }
                        else
                        {
                            // Field formatter doesn't include a valid field
                            // value formatter, try default convertion.
                            ApplyDefaultConvertion(fieldsContainer,
                                                   propertyInfo, fieldAttribute,
                                                   message[fieldAttribute.FieldNumber].Value);
                        }
                    }
                }
            }
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Construye una nueva instancia de los argumentos a emplear
 /// en algunos eventos de las colecciones de formateadores de
 /// mensajes.
 /// </summary>
 /// <param name="fieldFormatter">
 /// Es el formateador de campo asociado al evento.
 /// </param>
 public FieldFormatterEventArgs(FieldFormatter fieldFormatter)
 {
     _fieldFormatter = fieldFormatter;
 }