1 /***************************************************************************
2 datareader.cpp
3 -------------------
4 XML stream reader for QBrew data
5 -------------------
6 Copyright 2008, David Johnson
7 Please see the header file for copyright and license information
8 ***************************************************************************/
9
10 #include "data.h"
11 #include "resource.h"
12
13 #include "datareader.h"
14
15 using namespace Resource;
16
17 // DataReader ///////////////////////////////////////////////////////////////
18
19 /////////////////////////////////////////////////////////////////////////////
20 // DataReader()
21 // ------------
22 // Constructor
23
DataReader(QIODevice * device)24 DataReader::DataReader(QIODevice *device)
25 : QXmlStreamReader(device)
26 {
27 }
28
29 /////////////////////////////////////////////////////////////////////////////
30 // readData()
31 // ----------
32 // Read in data
33
readData(Data * data)34 bool DataReader::readData(Data *data)
35 {
36 QString buf;
37 bool grainsflag=false, hopsflag=false, miscsflag=false;
38 bool stylesflag=false, utilflag=false;
39
40 data->grainmap_.clear();
41 data->hopmap_.clear();
42 data->miscmap_.clear();
43 data->stylemap_.clear();
44 data->utable_.clear();
45
46 // parse file
47 while (!atEnd()) {
48 readNext();
49 if (isStartElement()) {
50 // qbrewdata tag
51 if (name() == tagDoc) {
52 // check version
53 buf = attributes().value(attrVersion).toString();
54 if (buf < DATA_PREVIOUS) {
55 // too old of a version
56 qWarning() << "Error: Unsupported data version";
57 raiseError("Unsupported data version");
58 return false;
59 }
60 }
61
62 // styles
63 else if (name() == tagStyles) {
64 stylesflag = true;
65 }
66 // style
67 else if (name() == tagStyle) {
68 if (!stylesflag) qWarning("Warning: mislocated style tag");
69 Style style;
70 buf = attributes().value(attrOGLow).toString();
71 style.setOGLow(buf.toDouble());
72 buf = attributes().value(attrOGHigh).toString();
73 style.setOGHi(buf.toDouble());
74 buf = attributes().value(attrFGLow).toString();
75 style.setFGLow(buf.toDouble());
76 buf = attributes().value(attrFGHigh).toString();
77 style.setFGHi(buf.toDouble());
78 buf = attributes().value(attrIBULow).toString();
79 style.setIBULow(buf.toInt());
80 buf = attributes().value(attrIBUHigh).toString();
81 style.setIBUHi(buf.toInt());
82 buf = attributes().value(attrSRMLow).toString();
83 style.setSRMLow(buf.toInt());
84 buf = attributes().value(attrSRMHigh).toString();
85 style.setSRMHi(buf.toInt());
86 style.setName(readElementText());
87 data->insertStyle(style);
88 }
89
90 // grains
91 else if (name() == tagGrains) {
92 grainsflag = true;
93 }
94 // grain
95 else if (name() == tagGrain) {
96 if (!grainsflag) qWarning("Warning: mislocated grain tag");
97 Grain grain;
98 grain.setWeight(Weight(1.0, data->defaultGrainUnit()));
99 buf = attributes().value(attrExtract).toString();
100 grain.setExtract(buf.toDouble());
101 buf = attributes().value(attrColor).toString();
102 grain.setColor(buf.toDouble());
103 // TODO: grain type deprecates data file format (0.4.0)
104 grain.setType(attributes().value(attrType).toString());
105 grain.setUse(attributes().value(attrUse).toString());
106 grain.setName(readElementText());
107 data->insertGrain(grain);
108 }
109
110 // hops
111 else if (name() == tagHops) {
112 hopsflag = true;
113 }
114 // hop
115 else if (name() == tagHop) {
116 // TODO: attrForm is deprecated 0.4.0
117 if (!hopsflag) qWarning("Warning: mislocated hop tag");
118 Hop hop;
119 buf = attributes().value(attrQuantity).toString();
120 hop.setWeight(Weight(1.0, data->defaultHopUnit()));
121 buf = attributes().value(attrAlpha).toString();
122 hop.setAlpha(buf.toDouble());
123 hop.setName(readElementText());
124 data->insertHop(hop);
125 }
126
127 // miscs
128 else if (name() == tagMiscs) {
129 miscsflag = true;
130 }
131 // misc
132 else if (name() == tagMisc) {
133 if (!miscsflag) qWarning("Warning: mislocated misc tag");
134 Misc misc;
135 misc.setQuantity(Quantity(1.0, data->defaultMiscUnit()));
136 misc.setType(attributes().value(attrType).toString());
137 misc.setNotes(attributes().value(attrNotes).toString());
138 misc.setName(readElementText());
139 data->insertMisc(misc);
140 }
141
142 // utilization
143 else if (name() == tagUtilization) {
144 utilflag = true;
145 }
146 // entry
147 else if (name() == tagEntry) {
148 if (!utilflag) qWarning("Warning: mislocated entry tag");
149 UEntry entry;
150 buf = attributes().value(attrTime).toString();
151 entry.time = buf.toUInt();
152 buf = attributes().value(attrUtil).toString();
153 entry.utilization = buf.toUInt();
154 data->addUEntry(entry);
155 }
156
157 // unknown tag, skip
158 else {
159 qWarning() << "Warning: Unknown tag" << name().toString();
160 skipElement();
161 }
162 }
163
164 else if (isEndElement()) {
165 // unset flags
166 if (name() == tagStyles) stylesflag = false;
167 else if (name() == tagGrains) grainsflag = false;
168 else if (name() == tagHops) hopsflag = false;
169 else if (name() == tagMiscs) miscsflag = false;
170 else if (name() == tagUtilization) utilflag = false;
171 }
172 }
173
174 return true;
175 }
176
177 // skip over xml element
skipElement()178 void DataReader::skipElement()
179 {
180 if (isStartElement()) {
181 int level = 0;
182 while (!atEnd()) {
183 readNext();
184
185 if (isStartElement()) level++;
186 if (isEndElement()) level--;
187
188 if (level < 0) break;
189 }
190 }
191 }
192
193 // DataWriter /////////////////////////////////////////////////////////////////
194
195 ///////////////////////////////////////////////////////////////////////////////
196 // DataWriter()
197 // ------------
198 // Constructor
199
DataWriter(QIODevice * device)200 DataWriter::DataWriter(QIODevice *device)
201 : QXmlStreamWriter(device)
202 {
203 #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
204 setAutoFormatting(true);
205 setAutoFormattingIndent(2);
206 #endif
207 }
208
209 ///////////////////////////////////////////////////////////////////////////////
210 // writeData()
211 // -----------
212 // Write out data
213
writeData(Data * data)214 bool DataWriter::writeData(Data *data)
215 {
216 writeStartDocument();
217 writeDTD(QString("<!DOCTYPE %1>").arg(tagDoc));
218
219 // write root element
220 writeStartElement(tagDoc);
221 writeAttribute(attrVersion, VERSION);
222
223 // write styles
224 writeStartElement(tagStyles);
225 foreach(Style style, data->stylemap_) {
226 // iterate through grain list
227 writeStartElement(tagStyle);
228 writeAttribute(attrOGLow, QString::number(style.OGLow()));
229 writeAttribute(attrOGHigh, QString::number(style.OGHi()));
230 writeAttribute(attrFGLow, QString::number(style.FGLow()));
231 writeAttribute(attrFGHigh, QString::number(style.FGHi()));
232 writeAttribute(attrIBULow, QString::number(style.IBULow()));
233 writeAttribute(attrIBUHigh, QString::number(style.IBUHi()));
234 writeAttribute(attrSRMLow, QString::number(style.SRMLow()));
235 writeAttribute(attrSRMHigh, QString::number(style.SRMHi()));
236 writeCharacters(style.name());
237 writeEndElement();
238 }
239 writeEndElement(); // tagStyles
240
241 // write grains
242 writeStartElement(tagGrains);
243 foreach(Grain grain, data->grainmap_) {
244 // iterate through grain list
245 writeStartElement(tagGrain);
246 writeAttribute(attrExtract, QString::number(grain.extract()));
247 writeAttribute(attrColor, QString::number(grain.color()));
248 writeAttribute(attrType, grain.type());
249 writeAttribute(attrUse, grain.use());
250 writeCharacters(grain.name());
251 writeEndElement();
252 }
253 writeEndElement(); // tagGrains
254
255 // write hops
256 writeStartElement(tagHops);
257 foreach(Hop hop, data->hopmap_) {
258 // iterate through hop list
259 writeStartElement(tagHop);
260 writeAttribute(attrAlpha, QString::number(hop.alpha()));
261 writeCharacters(hop.name());
262 writeEndElement();
263 }
264 writeEndElement(); // tagHops
265
266
267 // write misc ingredients
268 writeStartElement(tagMiscs);
269 foreach(Misc misc, data->miscmap_) {
270 // iterate through misc list
271 writeStartElement(tagMisc);
272 writeAttribute(attrType, misc.type());
273 writeAttribute(attrNotes, misc.notes());
274 writeCharacters(misc.name());
275 writeEndElement();
276 }
277 writeEndElement(); // tagMiscs
278
279 // write utilization table
280 writeStartElement(tagUtilization);
281 foreach(UEntry uentry, data->utable_) {
282 // iterate through entries
283 writeStartElement(tagEntry);
284 writeAttribute(attrTime, QString::number(uentry.time));
285 writeAttribute(attrUtil, QString::number(uentry.utilization));
286 writeEndElement();
287 }
288 writeEndElement(); // tagMiscs
289
290 writeEndElement(); // tagDoc
291 writeEndDocument();
292
293 return true;
294 }
295