Copy operator not working in Quick Fast C++ - c++

Now currently I am working on copy operator. What I understand from all the document and other material available on net is that Quickfast maintains a dictionary which is used by multiples entries within a UDP message to check the previous value.
eg: Lets say in the below given template we can have multiple MDEntries depending upon NoMDEntries tag value. Lets say we have 2 as the value .
What I did was , I put the value of MDEntryType (with copy oprerator ) as 1 (some random value) in the first entry, but for the second entry I did not put any value.
After I decode the message the value of MDEntryType should be 1 for both the entries.
Is my understanding correct ?
<template dictionary="1" id="1" name="MDIncRefreshSample_1">
<string id="35" name="MessageType">
<constant value="X"></constant>
</string> <string id="49" name="SenderCompID">
<constant value="Client"></constant>
</string> <string id="56" name="TargetCompID">
<constant value="Server"></constant>
</string> <uint32 id="34" name="MsgSeqNum"></uint32>
<uint64 id="52" name="SendingTime"></uint64>
<sequence name="MDEntries">
<length id="268" name="NoMDEntries"></length>
<uint32 id="279" name="MDUpdateAction">
<copy value="1"></copy>
</uint32>
<string id="269" name="MDEntryType">
<copy value="0"></copy>
</string>
<uint32 id="278" name="MDEntryID"></uint32>
<uint32 id="48" name="SecurityID">
<delta></delta>
</uint32>
<decimal id="270" name="MDEntryPx">
<exponent>
<default value="-2"></default>
</exponent>
<mantissa>
<delta></delta>
</mantissa>
</decimal>
<int32 id="271" name="MDEntrySize">
<delta></delta>
</int32>
<string id="37" name="OrderID"></string>
<uint32 id="273" name="MDEntryTime">
<copy></copy>
</uint32>
</sequence>
</template>
Now when I try to implement the above in my code, I am not able to copy the value in the second entry.
Here is the snippet of the code I used (help taken from testRoundTrip.cpp)
Template Created :
<templates>
<template dictionary="InstrumentReferenceData"
name="InstrumentReferenceData" id="3">
<typeRef name="instrumentreferencedata"/>
<uInt32 name="timestamp" id="52"> <delta/> </uInt32>
<uInt32 name="srcId" id="50"> <copy/> </uInt32>
<uInt32 name="seqNum" id="34"> <increment value="1"/> </uInt32>
<uInt32 name="isix" id="48"> <delta/> </uInt32>
<string name="isin" id="455"> <delta/> </string>
<string name="exchId" id="207"> <copy/> </string>
<string name="instGrp" id="1151"> <copy/> </string>
<string name="instTypCod" id="461"> <copy/> </string>
<string name="currCode" id="15"> <copy/> </string>
<decimal name="ticSiz" id="969"> <delta/> </decimal>
<uInt32 name="setId" id="TBD"> <copy/> </uInt32>
<sequence name="MDFeedTypes">
<length name="noOfStreams" id="1141"/>
<string name="streamType" id="1022"> <copy dictionary="template" />
</string>
<string name="streamService"> <copy/> </string>
<string name="inetAddr"> <delta/> </string>
<uInt32 name="port" id="TBD"> <delta/> </uInt32>
<uInt32 name="mktDepth" id="264" presence="optional"/> </uInt32>
<uInt32 name="mdBookType" id="1021" presence="optional"/> </uInt32>
</sequence>
</template>
</templates>
Message creation plus encoding and decoding: (I have poulated the value in streamtype field only once)
Messages::MessagePtr msg(new Messages::Message(templateRegistry->maxFieldCount()));
msg->addField(identity_timestamp, Messages::FieldUInt32::create(1));
msg->addField(identity_srcId, Messages::FieldUInt32::create(2));
msg->addField(identity_seqNum, Messages::FieldUInt32::create(3));
msg->addField(identity_isix, Messages::FieldUInt32::create(4));
msg->addField(identity_isin, Messages::FieldAscii::create("isin"));
msg->addField(identity_exchId, Messages::FieldAscii::create("exchId"));
msg->addField(identity_instGrp, Messages::FieldAscii::create("instGrp"));
msg->addField(identity_instTypCod, Messages::FieldAscii::create("instTypCod"));
msg->addField(identity_currCode, Messages::FieldAscii::create("currCode"));
msg->addField(identity_ticSiz, Messages::FieldDecimal::create(Decimal(123, -1)));
msg->addField(identity_setId, Messages::FieldUInt32::create(5));
lengthIdentity.setId("1141");
Messages::SequencePtr sequence_MDFeedTypes(new Messages::Sequence(lengthIdentity, 2));
Messages::FieldSetPtr entry(new Messages::FieldSet(6)); // todo Hardcoded 6?
entry->addField(identity_streamType, Messages::FieldAscii::create("streamType")); // Populated the value 1st time
entry->addField(identity_streamService, Messages::FieldAscii::create("streamService"));
entry->addField(identity_inetAddr, Messages::FieldAscii::create("inetAddr.com"));
entry->addField(identity_port, Messages::FieldUInt32::create(2222));
entry->addField(identity_mktDepth, Messages::FieldUInt32::create(10));
sequence_MDFeedTypes->addEntry(Messages::FieldSetCPtr(entry));
entry.reset(new Messages::FieldSet(6));
entry->addField(identity_streamType, Messages::FieldAscii::create("")); // Did not Populate the value 2nd time
entry->addField(identity_streamService, Messages::FieldAscii::create(""));
entry->addField(identity_inetAddr, Messages::FieldAscii::create("inetAddr.org"));
entry->addField(identity_port, Messages::FieldUInt32::create(2224));
entry->addField(identity_mdBookType, Messages::FieldUInt32::create(3));
sequence_MDFeedTypes->addEntry(Messages::FieldSetCPtr(entry));
msg->addField(identity_MDFeedTypes, Messages::FieldSequence::create(sequence_MDFeedTypes));
Codecs::Encoder encoder(templateRegistry);
Codecs::DataDestination destination;
template_id_t templId = 3; // from the XML above
encoder.encodeMessage(destination, templId, *msg);
std::string fastString;
destination.toString(fastString);
std::cout<<"fastString is "<<fastString<<std::endl;
destination.clear();
Codecs::Decoder decoder(templateRegistry);
Codecs::DataSourceString source(fastString);
Codecs::SingleMessageConsumer consumer;
Codecs::GenericMessageBuilder builder(consumer);
decoder.decodeMessage(source, builder);
Messages::Message & msgOut(consumer.message());
Messages::MessageFormatter formatter(std::cout);
formatter.formatMessage(msgOut); // I have made some printing changes to print the ouptut per tag
validateMessage1(msgOut);
encoder.reset();
encoder.encodeMessage(destination, templId, msgOut);
std::string reencoded;
destination.toString(reencoded);
destination.clear();
I am able to encode and successfully decode the message, but the value is not getting copied in the second entry (streamType tag).
Here is my decoded ouput:
1st entry:
streamType[1022]=streamType
streamService[]=streamService
inetAddr[]=inetAddr.com
port[TBD]= 2045
2nd entry:
streamType[1022]= //value not copied
streamService[]=
inetAddr[]=inetAddr.org
port[TBD]= 2046
Could you please let us know, if we are making a mistake somewhere. I am very new to this :)
I have following queries too :
1/ Do we need to explicitly need to enable/disable dictionary in quickfast ? (In FIX we could do that with flag, DataDictionary = Y/N).
Also in the template created above , I found this line:
<string name="streamType" id="1022"> <copy dictionary="template" /> </string>
Is it neccesary to give dictionary name while using operators and how are they related?
2/ Do we also need to explicitly mention that PMAP bits are required?
Codecs::PresenceMap pmap(1); // I came across this function, so I got this doubt whether we need to explicitly mention about pmap.

Related

Parsing XML and taking values from the file

I need to get exact answer from my whole .xml file.
Let's say we have part of my .xml:
<trace>
<string key="concept:name" value="1"/>
<string key="description" value="Simulated process instance"/>
<event>
<string key="org:resource" value="System"/>
<date key="time:timestamp" value="1970-01-02T12:23:00.000+01:00"/>
<string key="concept:name" value="Register"/>
<string key="lifecycle:transition" value="complete"/>
</event>
<event>
<string key="org:resource" value="Tester3"/>
<date key="time:timestamp" value="1970-01-02T12:23:00.000+01:00"/>
<string key="concept:name" value="Analyze Defect"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="defectType" value="6"/>
<string key="org:resource" value="Tester3"/>
<string key="lifecycle:transition" value="complete"/>
<string key="phoneType" value="T2"/>
<date key="time:timestamp" value="1970-01-02T12:30:00.000+01:00"/>
<string key="concept:name" value="Analyze Defect"/>
</event>
<event>
<string key="org:resource" value="SolverC1"/>
<date key="time:timestamp" value="1970-01-02T12:31:00.000+01:00"/>
<string key="concept:name" value="Repair (Complex)"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="SolverC1"/>
<date key="time:timestamp" value="1970-01-02T12:49:00.000+01:00"/>
<string key="concept:name" value="Repair (Complex)"/>
<string key="lifecycle:transition" value="complete"/>
</event>
<event>
<string key="org:resource" value="Tester3"/>
<date key="time:timestamp" value="1970-01-02T12:49:00.000+01:00"/>
<string key="concept:name" value="Test Repair"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="numberRepairs" value="0"/>
<string key="org:resource" value="Tester3"/>
<string key="lifecycle:transition" value="complete"/>
<date key="time:timestamp" value="1970-01-02T12:55:00.000+01:00"/>
<string key="concept:name" value="Test Repair"/>
<string key="defectFixed" value="true"/>
</event>
<event>
<string key=" " value="System"/>
<date key="time:timestamp" value="1970-01-02T13:10:00.000+01:00"/>
<string key="concept:name" value="Inform User"/>
<string key="lifecycle:transition" value="complete"/>
</event>
<event>
<string key="numberRepairs" value="0"/>
<string key="org:resource" value="System"/>
<string key="lifecycle:transition" value="complete"/>
<date key="time:timestamp" value="1970-01-02T13:10:00.000+01:00"/>
<string key="concept:name" value="Archive Repair"/>
<string key="defectFixed" value="true"/>
</event>
</trace>
From here I need to find two exact "events". Event name is written in trace -> event -> string key="concept:name" value="EVENT NAME"
One of these events should have lifecycle:transition value="start", second one - "complete".
From "complete" event I need to take time:timestamp value="time" and subtract "start" event time:timestamp value="time".
So as you see the formula is time = time_complete - time_start
The problem is that time (time-date) format is not useful so from, e.g. 1970-01-02T12:30:00.000+01:00 I need to get only 12:30:00 and make it subtractable to find exact time how much the process took.
My idea it to get all event names in trace, all lifecycle transition values, and all "times" in this trace but I see that it's too difficult and I can find the proper way to do it. Here is some code from what I did:
NodeList nodeList = document.getElementsByTagName("trace");
Element element = (Element) nodeList.item(0);
NodeList stringList = element.getElementsByTagName("string");
NodeList dateList = element.getElementsByTagName("date");
//--- Get all events names ---//
for (int x = 1, size = stringList.getLength(); x < size; x++) {
if (stringList.item(x).getAttributes().getNamedItem("key").getNodeValue().contains("concept:name")) {
eventName.add(stringList.item(x).getAttributes().getNamedItem("value").getNodeValue());
}
}
//--- Get all times of every event in trace ---//
for (int y = 0, size = dateList.getLength(); y < size; y++) {
if (dateList.item(y).getAttributes().getNamedItem("key").getNodeValue().contains("time:timestamp")) {
time.add(dateList.item(y).getAttributes().getNamedItem("value").getNodeValue());
}
}
//--- Get all lifecycle transitions of events ---//
for (int x = 0, size = stringList.getLength(); x < size; x++) {
if (stringList.item(x).getAttributes().getNamedItem("key").getNodeValue().contains("lifecycle:transition")) {
status.add(stringList.item(x).getAttributes().getNamedItem("value").getNodeValue());
}
}
I think, that I solved my problem using the code:
SimpleDateFormat str = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'+'SS:SS");
Date data;
for (int i = 0; i < time.size(); i++) {
data = str.parse(time.get(i));
minutes.add(data.getHours() * 60 + data.getMinutes());
}
Anyway, thank you for your help :)

QT DOMXml - Change the name of a node [duplicate]

This question already has answers here:
Edit Value of a QDomElement?
(6 answers)
Closed 6 years ago.
I am working on a QT Project and part of that is a reconstruction of an XML file. I was able to make most of the needed changes with QDom but I can't find how to rename a node.
So the old XML file looks like ..
<root>
<window name="" ..>
<element x="" y=""/>
<element1 a="" b=""/>
...
</window>
..
..
<window name="">
<element x="" y=""/>
<element1 a="" b=""/>
...
</window>
</root>
How can i change the XML so that the new one will have < group > instead of < window >?
So at the end it needs to look like..
<root>
<group name="" ..>
<element x="" y=""/>
<element1 a="" b=""/>
...
</group>
..
..
<group name="">
<element x="" y=""/>
<element1 a="" b=""/>
...
</group>
</root>
Adding some more info...
Here is the code I use to read the <window> nodes, delete some based on the visibility (comes from a list) and I need to change <window> to <group> for the remaining nodes.
QFile oldXml("file.xml");
oldXml.open(QIODevice::ReadOnly);
QDomDocument doc;
doc.setContent(&oldXml);
QDomNodeList nodes = doc.elementsByTagName("window");
// Remove Window nodes based on visibility
insize = nodes.length();
for ( int i = 0; i < insize; i++ ) {
QDomNode node = nodes.at(i-dels);
if ( (list2[i] == "0") | (list2[i]=="") ) {
node.parentNode().removeChild(node);
dels=dels+1;
} else {
// Here is where i need to change the node name from <window> to e.g. <group>
}
}
You could use setTagName and maybe setAttribute if you want to set a value for the name attribute.
With the following example, myxml.xml is converted to xmlout.xml
Note#1: this is just an example: we're replacing only the first node.
Note#2: in this example, we're using two different files. Depending on your design, you could use the same or not.
myxml.xml
<root>
<window name="">
<element x="" y=""/>
<element1 a="" b=""/>
</window>
<window name="">
<element x="" y=""/>
<element1 a="" b=""/>
</window>
</root>
xmlout.xml
<root>
<group name="value">
<element y="" x=""/>
<element1 a="" b=""/>
</group>
<window name="">
<element y="" x=""/>
<element1 a="" b=""/>
</window>
</root>
main.cpp
#include <iostream>
#include <QtXml>
#include <QFile>
int main(int argc, char *argv[])
{
QDomDocument doc;
// Load xml file as raw data
QFile inFile(":myxml.xml");
if (!inFile.open(QIODevice::ReadOnly ))
{
std::cerr << "Error - inFile: " << inFile.errorString().toStdString();
return 1;
}
// Set data into the QDomDocument before processing
doc.setContent(&inFile);
// Get element in question
QDomElement root = doc.documentElement();
QDomElement nodeTag = root.firstChildElement("window");
nodeTag.setTagName("group");
nodeTag.setAttribute("name","value");
inFile.close();
// Save the modified data
QFile outFile("xmlout.xml");
if (!outFile.open(QIODevice::WriteOnly ))
{
// Error while loading file
std::cerr << "Error - outFile: " << outFile.errorString().toStdString();
return 1;
}
QTextStream stream;
stream.setDevice(&outFile);
stream.setCodec("UTF-8");
doc.save(stream,4);
outFile.close();
return 0;
}
I did not see any straight API function to rename the element. API is allowing to change value but not name.
There is another round about way.
Create an element, for example:
QDomElement group = doc.createElement("group");
use "QDomNode's replacechild" function.
QDomNode QDomNode::replaceChild(const QDomNode &newChild, const QDomNode &oldChild)
ex:
QDomNode dNode = node.replaceChild(group,oldNode);

Parsing XML File with Boost C++

I have to parse one xml file using boost c++, I have written one test code which is working for this xml.
a.xml
<a>
<modules>
<module>abc</module>
<module>def</module>
<module>ghi</module>
</modules>
</a>
Output is coming
abc
def
ghi
but for this a.xml file, my test code is not showing any output, 3 blank lines are coming as output.
<a>
<modules>
<module value = "abc"/>
<module value = "def"/>
<module value = "abc"/>
</modules>
</a>
here is the test code:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <iostream>
int main()
{
using boost::property_tree::ptree;
ptree pt;
read_xml("a.xml",pt);
BOOST_FOREACH(ptree::value_type &v, pt.get_child("a.modules"))
std::cout<<v.second.data()<<std::endl;
return 0;
}
My Problem is I am having a large xml file which contains the mixture of patterns from both the files and I have to parse it.
File is b.xml and I have to get message subtag from each tag.
<MultiMessage>
<Message structID="1710" msgID="0" length="50">
<structure type="AppHeader">
</structure>
</Message>
<Message structID="27057" msgID="27266" length="315">
<structure type="Container">
<productID value="166"/>
<publishTo value="xyz"/>
<templateID value="97845"/>
<sendingTime value="1421320622367060444"/>
<message value="092374NMKLA90U345N09832LJKN0A9845JHKLASDF09U8426LJAKLJDGF09845U6KLJSDGP89U45LJSDFP9GU4569078LJK"/>
</structure>
</Message>
</MultiMessage>
<MultiMessage>
<Message structID="1710" msgID="0" length="50">
<structure type="AppHeader">
</structure>
</Message>
<Message structID="27057" msgID="27266" length="315">
<structure type="Container">
<productID value="166"/>
<publishTo value="xyz"/>
<templateID value="97845"/>
<sendingTime value="1421320622367060444"/>
<message value="092374NMKLA90U345N09832LJKN0A9845JHKLASDF09U8426LJAKLJDGF09845U6KLJSDGP89U45LJSDFP9GU4569078LJK"/>
</structure>
</Message>
</MultiMessage>
<MultiMessage>
<Message structID="1710" msgID="0" length="50">
<structure type="AppHeader">
</structure>
</Message>
<Message structID="27057" msgID="27266" length="315">
<structure type="Container">
<productID value="166"/>
<publishTo value="xyz"/>
<templateID value="97845"/>
<sendingTime value="1421320622367060444"/>
<message value="092374NMKLA90U345N09832LJKN0A9845JHKLASDF09U8426LJAKLJDGF09845U6KLJSDGP89U45LJSDFP9GU4569078LJK"/>
</structure>
</Message>
</MultiMessage>
and output should be :
092374NMKLA90U345N09832LJKN0A9845JHKLASDF09U8426LJAKLJDGF09845U6KLJSDGP89U45LJSDFP9GU4569078LJK
092374NMKLA90U345N09832LJKN0A9845JHKLASDF09U8426LJAKLJDGF09845U6KLJSDGP89U45LJSDFP9GU4569078LJK
092374NMKLA90U345N09832LJKN0A9845JHKLASDF09U8426LJAKLJDGF09845U6KLJSDGP89U45LJSDFP9GU4569078LJK
Thank You
Regards
Boost Documentation:
The attributes of an XML element are stored in the subkey . There is one child node per attribute in the attribute node. Existence of the node is not guaranteed or necessary when there are no attributes.
<module value = "abc"/>
//One way would be this:
boost::get<std::string>("module.<xmlattr>.value");
One more way (untested), which appears to be better:
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("a.modules"))
{
std::cout << v.second.get_child("<xmlattr>.type").data() << std::endl;
std::cout << v.second.get_child("<xmlattr>.Reference").data() << std::endl;
}
One more taken from here.
//Parse XML...
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("a.modules"))
{
const boost::property_tree::ptree &attributes = v.second.get_child("<xmlattr>", boost::property_tree::ptree());
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, attributes)
{
std::cout << v.first.data() << std::endl;
std::cout << v.second.data() << std::endl;
}
}

Is it possible to generate non-blocking calls with dbusxx-xml2cpp?

I would like to generate C++ headers using dbusxx-xml2cpp where some methods are non-blocking, e.g. using invoke_method_noreply instead of invoke_method. Is this possible?
For example the following XML:
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/me/MyService">
<interface name="me.MyService">
<method name="MyMethod">
<arg direction="in" type="s" name="argument"/>
</method>
</interface>
</node>
Would generate (partly):
void MyMethod(const std::string& argument)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();
wi << argument;
call.member("MyMethod");
::DBus::Message ret = invoke_method (call);
}
But I would like to have something like:
void MyMethod(const std::string& argument)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();
wi << argument;
call.member("MyMethod");
bool ret = invoke_method_noreply (call);
}
Use the annotation org.freedesktop.DBus.Method.NoReply"
Example XML:
<node>
<interface name="org.test.example">
<method name="NoReplyMethod">
<arg name="data" direction="in" type="i"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>
Generated Code:
void NoReplyMethod(const int32_t& data)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();
wi << data;
call.member("NoReplyMethod");
assert (invoke_method_noreply (call));
}

How to edit the end of the XML document end in Qt (writeEndDocument)?

I write a small program address book, contacts stored in the xml file. Here is the part off the code
void new_engine::main_window::write_to_db(const QString& n, const QString& s)
{
QFile m_db_file(m_db_path);
QString t("User");
m_db_file.open(QIODevice::Append);
QXmlStreamWriter wxml(&m_db_file);
wxml.setAutoFormatting(true);
if(m_size == 1)
{
wxml.writeStartDocument();
wxml.writeStartElement("Persons");
}
wxml.writeStartElement(t);
QString id = QString::number(m_size);
wxml.writeAttribute("id", id);
wxml.writeTextElement("Name", n);
wxml.writeTextElement("Surname", s);
wxml.writeEndElement();
wxml.writeEndDocument();
m_db_file.close();
}
but the problem is that after the first contact of the tag file is closed. here is the result
<?xml version="1.0" encoding="UTF-8"?>
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
</Persons>
<User id="2">
<Name>eqwevxcv</Name>
<Surname>xcvxcx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>dasdasd</Surname>
</User>
but it must be so
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="2">
<Name>eqwevxcv</Name>
<Surname>xcvxcx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>dasdasd</Surname>
</User>
</Persons>
How can we do this, after each new record will have to change document end ?
This is an example:
void write_to_db(QXmlStreamWriter& writer, QString id, QString name, QString surname)
{
writer.writeStartElement("User");
writer.writeAttribute(QXmlStreamAttribute("id", id));
writer.writeTextElement("Name", name);
writer.writeTextElement("Surname", surname);
writer.writeEndElement();
}
// This can be a file, or whatever iodevice your heart desires.
QString out;
QXmlStreamWriter writer(&out);
writer.writeStartDocument();
writer.writeStartElement("Persons");
write_to_db(writer, "1", "das", "vcvx");
write_to_db(writer, "2", "das", "vcvx");
write_to_db(writer, "3", "das", "vcvx");
writer.writeEndElement(); // Close <persons> tag
writer.writeEndDocument();
The output (using QXmlStreamWriter::setAutoFormatting/Indent):
<?xml version="1.0"?>
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="2">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
</Persons>