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