2
* misc.cpp is part of Brewtarget, and is Copyright Philip G. Lee
3
* (rocketman768@gmail.com), 2009.
5
* Brewtarget is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* (at your option) any later version.
10
* Brewtarget is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#include "brewtarget.h"
24
#include "stringparsing.h"
26
#include "brewtarget.h"
27
#include <QDomElement>
30
bool operator<(Misc &m1, Misc &m2)
32
return m1.name < m2.name;
35
bool operator==(Misc &m1, Misc &m2)
37
return m1.name == m2.name;
41
std::string Misc::toXml()
43
std::string ret = "<MISC>\n";
45
ret += "<NAME>"+name+"</NAME>\n";
46
ret += "<VERSION>"+intToString(version)+"</VERSION>\n";
47
ret += "<TYPE>"+type+"</TYPE>\n";
48
ret += "<USE>"+use+"</USE>\n";
49
ret += "<TIME>"+doubleToString(time)+"</TIME>\n";
50
ret += "<AMOUNT>"+doubleToString(amount)+"</AMOUNT>\n";
51
ret += "<AMOUNT_IS_WEIGHT>"+boolToString(amountIsWeight)+"</AMOUNT_IS_WEIGHT>\n";
52
ret += "<USE_FOR>"+useFor+"</USE_FOR>\n";
53
ret += "<NOTES>"+notes+"</NOTES>\n";
60
void Misc::toXml(QDomDocument& doc, QDomNode& parent)
66
miscNode = doc.createElement("MISC");
68
tmpNode = doc.createElement("NAME");
69
tmpText = doc.createTextNode(name.c_str());
70
tmpNode.appendChild(tmpText);
71
miscNode.appendChild(tmpNode);
73
tmpNode = doc.createElement("VERSION");
74
tmpText = doc.createTextNode(text(version));
75
tmpNode.appendChild(tmpText);
76
miscNode.appendChild(tmpNode);
78
tmpNode = doc.createElement("TYPE");
79
tmpText = doc.createTextNode(type.c_str());
80
tmpNode.appendChild(tmpText);
81
miscNode.appendChild(tmpNode);
83
tmpNode = doc.createElement("USE");
84
tmpText = doc.createTextNode(use.c_str());
85
tmpNode.appendChild(tmpText);
86
miscNode.appendChild(tmpNode);
88
tmpNode = doc.createElement("TIME");
89
tmpText = doc.createTextNode(text(time));
90
tmpNode.appendChild(tmpText);
91
miscNode.appendChild(tmpNode);
93
tmpNode = doc.createElement("AMOUNT");
94
tmpText = doc.createTextNode(text(amount));
95
tmpNode.appendChild(tmpText);
96
miscNode.appendChild(tmpNode);
98
tmpNode = doc.createElement("AMOUNT_IS_WEIGHT");
99
tmpText = doc.createTextNode(text(amountIsWeight));
100
tmpNode.appendChild(tmpText);
101
miscNode.appendChild(tmpNode);
103
tmpNode = doc.createElement("USE_FOR");
104
tmpText = doc.createTextNode(useFor.c_str());
105
tmpNode.appendChild(tmpText);
106
miscNode.appendChild(tmpNode);
108
tmpNode = doc.createElement("NOTES");
109
tmpText = doc.createTextNode(notes.c_str());
110
tmpNode.appendChild(tmpText);
111
miscNode.appendChild(tmpNode);
113
parent.appendChild(miscNode);
116
//============================CONSTRUCTORS======================================
117
void Misc::setDefaults()
125
amountIsWeight=false;
130
Misc::Misc() : Observable()
135
Misc::Misc(Misc& other)
142
amount = other.amount;
144
amountIsWeight = other.amountIsWeight;
145
useFor = other.useFor;
149
Misc::Misc( const XmlNode * node ) : Observable()
151
std::vector<XmlNode *> children;
152
std::vector<XmlNode *> tmpVec;
154
std::string leafText;
156
unsigned int i, childrenSize;
157
bool hasName=false, hasVersion=false, hasType=false, hasUse=false, hasAmount=false, hasTime=false;
161
if( node->getTag() != "MISC" )
162
throw MiscException("initializer not passed a MISC node.");
164
node->getChildren( children );
165
childrenSize = children.size();
167
for( i = 0; i < childrenSize; ++i )
169
tag = children[i]->getTag();
170
children[i]->getChildren( tmpVec );
172
// All valid children of MISC only have zero or one child.
173
if( tmpVec.size() > 1 )
174
throw MiscException("Tag \""+tag+"\" has more than one child.");
176
// Have to deal with the fact that this node might not have
177
// and children at all.
178
if( tmpVec.size() == 1 )
183
// It must be a leaf if it is a valid BeerXML entry.
184
if( ! leaf->isLeaf() )
185
throw MiscException("Should have been a leaf but is not.");
187
leafText = leaf->getLeafText();
194
else if( tag == "VERSION" )
197
if( parseInt(leafText) != version )
198
std::cerr << "Warning: XML MISC version is not " << version << std::endl;
200
else if( tag == "TYPE" )
205
else if( tag == "USE" )
210
else if( tag == "TIME" )
212
setTime(parseDouble(leafText));
215
else if( tag == "AMOUNT" )
217
setAmount(parseDouble(leafText));
220
else if( tag == "AMOUNT_IS_WEIGHT" )
221
setAmountIsWeight(parseBool(leafText));
222
else if( tag == "USE_FOR" )
224
else if( tag == "NOTES" )
227
std::cerr << "Warning: MISC tag \"" << tag << "\" is not recognized." << std::endl;
230
if( !hasName || !hasVersion || !hasType || !hasUse || !hasAmount || !hasTime )
231
throw MiscException("one of the required fields is missing.");
234
Misc::Misc(const QDomNode& miscNode)
236
QDomNode node, child;
238
QString property, value;
242
for( node = miscNode.firstChild(); ! node.isNull(); node = node.nextSibling() )
244
if( ! node.isElement() )
246
Brewtarget::log(Brewtarget::WARNING, QString("Node at line %1 is not an element.").arg(textNode.lineNumber()) );
250
child = node.firstChild();
251
if( child.isNull() || ! child.isText() )
254
property = node.nodeName();
255
textNode = child.toText();
256
value = textNode.nodeValue();
258
if( property == "NAME" )
260
name = value.toStdString();
262
else if( property == "VERSION" )
264
if( version != getInt(textNode) )
265
Brewtarget::log(Brewtarget::ERROR, QString("MISC says it is not version %1. Line %2").arg(version).arg(textNode.lineNumber()) );
267
else if( property == "TYPE" )
269
if( isValidType(value.toStdString()) )
270
type = value.toStdString();
272
Brewtarget::log(Brewtarget::ERROR, QString("%1 is not a valid type for MISC. Line %2").arg(value).arg(textNode.lineNumber()) );
274
else if( property == "USE" )
276
if( isValidUse(value.toStdString()) )
277
use = value.toStdString();
279
Brewtarget::log(Brewtarget::ERROR, QString("%1 is not a valid use for MISC. Line %2").arg(value).arg(textNode.lineNumber()) );
281
else if( property == "TIME" )
283
setTime(getDouble(textNode));
285
else if( property == "AMOUNT" )
287
setAmount(getDouble(textNode));
289
else if( property == "AMOUNT_IS_WEIGHT" )
291
setAmountIsWeight(getBool(textNode));
293
else if( property == "USE_FOR" )
295
setUseFor(value.toStdString());
297
else if( property == "NOTES" )
299
setNotes(value.toStdString());
303
Brewtarget::log(Brewtarget::WARNING, QString("Unsupported MISC property: %1. Line %2").arg(property).arg(node.lineNumber()) );
310
//============================"GET" METHODS=====================================
311
std::string Misc::getName() const
316
std::string Misc::getType() const
321
std::string Misc::getUse() const
326
double Misc::getAmount() const
331
double Misc::getTime() const
336
bool Misc::getAmountIsWeight() const
338
return amountIsWeight;
341
std::string Misc::getUseFor() const
346
std::string Misc::getNotes() const
351
//============================"SET" METHODS=====================================
352
void Misc::setName( const std::string &var )
354
name = std::string(var);
358
void Misc::setType( const std::string &var )
360
if( ! isValidType(var) )
361
throw MiscException("\""+var+"\" is not a valid type.");
364
type = std::string(var);
369
void Misc::setUse( const std::string &var )
371
if( ! isValidUse(var) )
372
throw MiscException("\""+var+"\" is not a valid use.");
375
use = std::string(var);
380
void Misc::setAmount( double var )
383
throw MiscException("amount cannot be negative: " + doubleToString(var) );
391
void Misc::setTime( double var )
394
throw MiscException("time cannot be negative: " + doubleToString(var) );
402
void Misc::setAmountIsWeight( bool var )
404
amountIsWeight = var;
408
void Misc::setUseFor( const std::string &var )
410
useFor = std::string(var);
414
void Misc::setNotes( const std::string &var )
416
notes = std::string(var);
420
//========================OTHER METHODS=========================================
422
bool Misc::isValidUse( const std::string &var )
424
static const std::string uses[] = {"Boil", "Mash", "Primary", "Secondary", "Bottling"};
425
static const unsigned int size = 5;
428
for( i = 0; i < size; ++i )
435
bool Misc::isValidType( const std::string &var )
437
static const std::string types[] = {"Spice", "Fining", "Water Agent", "Herb", "Flavor", "Other"};
438
static const unsigned int size = 6;
441
for( i = 0; i < size; ++i )
442
if( var == types[i] )