ValueMessageBuilder Interface
The ValueMessageBuilder interface is intended to be extremely flexible. Because it is abstract you must implement all the methods, but you can leave many of the implementations empty -- only provide implementations for the ones you need.
Here is what you can expect if you are writing your own message builder derived from ValueMessageBuilder
At the beginning each incoming message you will receive a call to * startMessage() * initialize your object to build a new message
As each field is decoded in the message, you will receive a call to: * addValue() * capture the data for this field
When a group is encountered you will receive a call to * startGroup() * prepare to receive the fields that make up the group
After the group is complete you will receive a call to * endGroup() * go back to accepting fields for the parent that contains the group
When a sequence is encountered you will receive a call to: * startSequence() * prepare to receive sequence entries
then one or more calls to * startSequenceEntry() * prepare to receive the fields that make up this sequence entry.
After a sequence entry is complete you will receive a call to: * endSequenceEntry() * get ready for the next call which will be either startSequenceEntry or endSequence * Note: it may be possible for your application to process this sequence entry at this point.
After all entries in a sequence have been decoded you will receive a call to: * endSequence() * go back to accepting fields for the parent that contains the sequence.
After the entire message is decoded you will receive EITHER a a call to * endMessage() * process the message just received and get ready for the next startMessage
or a call to * ignoreMessage()
* discard the (partial) message being received and get ready for the next startMessage
So to express this in another way, here's the sequence of calls you might expect to see:
- startMessage (once per message)
- addValue (zero or more times per message)
- startGroup (zero or more times per message)
- addValue(zero or more times per group)
- endGroup (once per startGroup)
- startSequence(zero or more times per message)
- startSequenceEntry(zero or more times per sequence)
- addValue(zero or more times per sequence entry)
- endSequenceEntry(once per startSequenceEntry)
- endSequence(once per startSequence)
- endMessage (once per message)
- addValue (zero or more times per message)
ignoreMessage might occur at any time after a startMessage.
The start... methods return a reference to a new ValueMessageBuilder -- you can simply return *this
or you can return a reference to a new ValueMessageBuilder that will handle the child data.
Logger interface
In addition to accepting decoded messages, ValueMessageBuilder is also derived from Logger. That means you need to implement the following methods as well:
virtual bool wantLog(unsigned short level);
* indicate whether messages with this logging level are wanted.
* logging level will be one of
* Logger::QF_LOG_FATAL
* Logger::QF_LOG_SERIOUS
* Logger::QF_LOG_WARNING
* Logger::QF_LOG_INFO
* Logger::QF_LOG_VERBOSE
* Returning false
for unwanted levels can improve performance.
virtual bool logMessage(unsigned short level,
const std::string & logMessage);
* capture the message in the log of your choice.
virtual bool reportDecodingError(const std::string & errorMessage);
* capture the message in the log of your choice.
* return to try to recover, or
* throw an exception to stop decoding this message
* Your application can catch the exception and try to recover by resetting the decoder and starting at the beginning of the next message (if it can find it!).
virtual bool reportCommunicationError(const std::string & errorMessage);
* capture the message in the log of your choice.
* throw an exception to stop decoding this message
* your application can catch the exception and do whatever it feels is appropriate. It probably needs to close the connection and open a new one.