Only allow this language: ((n|s)!(w|e)!(u|d)!;)+ for directions.
[UnsignedByte.git] / src / Core / Editors / ChunkImporter.cpp
blob02e36f1ed2496db196cbff99caee6eb11b8ada8c
1 /***************************************************************************
2 * Copyright (C) 2008 by Sverre Rabbelier *
3 * sverre@rabbelier.nl *
4 * *
5 * This program 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. *
9 * *
10 * This program 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. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "ChunkImporter.h"
22 #include "Chunk.h"
23 #include "FieldImpls.h"
24 #include "TableImpls.h"
25 #include "StringUtilities.h"
26 #include "Detail.h"
27 #include "DetailManager.h"
28 #include "Managers.h"
30 std::string ChunkImporter::MyDetail::toString()
32 std::string result;
33 result.append("[\n");
34 result.append(String::Get()->unlines(m_description , "\n", 0));
35 for(MyDetailVector::iterator it = m_details.begin(); it != m_details.end(); it++)
37 result.append((*it)->toString());
39 result.append("]\n");
40 return result;
43 void ChunkImporter::MyDetail::apply(mud::DetailPtr detail)
45 Assert(detail);
47 MyDetailVector details = getDetails();
48 for(MyDetailVector::iterator it = details.begin(); it != details.end(); it++)
50 MyDetailPtr onedetail = *it;
52 KeysPtr newdetailkeys = mud::Managers::Get()->Detail->Add();
53 mud::DetailPtr newdetail = mud::Managers::Get()->Detail->GetByKey(newdetailkeys->first()->getIntegerValue());
54 newdetail->setDescription(String::Get()->unlines(onedetail->getDescription() , " ", 0));
55 newdetail->Save();
57 /**
58 * Connect the detail to the chunk
59 */
60 RelationPtr relation(new Relation(db::TableImpls::Get()->DETAILDETAIL));
61 relation->addKey(db::TableImpls::Get()->DETAILDETAIL->FKDETAILSPRIMARY, newdetail->getID());
62 relation->addKey(db::TableImpls::Get()->DETAILDETAIL->FKDETAILSSECONDARY, detail->getID());
63 relation->save();
65 onedetail->apply(newdetail);
69 ChunkImporter::ChunkImporter(
70 const std::string& input) :
71 m_input(input)
73 Parse();
76 ChunkImporter::~ChunkImporter()
81 /**
83 The format is as follows:
84 [format description]
86 Chunk Description
87 This may span several lines
88 * Detail of Chunk
89 ** Detail of Detail of Chunk
90 Continuation of detail
91 Further continued
92 ** Another Detail of Detail of Chunk
93 *** Detail of above detail
94 ** Yet Another Detail of Detail of Chunk
95 * Detail of the chunk
96 * Some more detail of the chunk
98 [/format description]
99 [formal format description]
101 TEXT: {^*\n\t}
104 import: description
105 | details
106 | description '\n' details
108 description: description '\n' TEXT
109 | TEXT
111 details: detail
112 | details '\n' detail
114 detail: '*' TEXT
115 | '*' TEXT '\n' lines
116 | subdetail
118 lines: lines tabs TEXT '\n'
119 | tabs TEXT '\n'
121 tabs: tabs '\t'
122 | '\t'
124 subdetail: '*' detail
126 [/formal format description]
127 [call graph]
128 bovenaan [current = topDetail, details.top() = NULL]
129 * klein [ current = newDetail, details.top() = topDetail] // details.push(current), current = new Detail()
130 ** heel erg [ current = notherNewDetail, details.top() = newDetail] // details.push(current), current = new Detail()
131 * blauw [ current = newDetail, details.top() = topDetail] // details.top()->addDetail(current), current = details.pop(), detail.top()->addDetail(current), current = new Detail()
132 en groen [ current = newDetail, details.top() = topDetail] // current.append(line)
133 * dinges [ current = YoNewDetail, details.top() = topDetail] // details.top()->addDetail(current), current = new Detail()
134 [/call graph]
136 void ChunkImporter::Parse()
138 bool inDescr = true;
139 size_t i = 0;
140 int lastDepth = 0;
142 std::stack<MyDetailPtr> details;
143 MyDetailPtr current(new ChunkImporter::MyDetail());
145 Strings lines = String::Get()->lines(m_input, "\n");
147 for(Strings::iterator it = lines.begin(); it != lines.end(); it++)
149 std::string line = *it;
150 int depth = 0;
152 if(!line.size())
153 continue;
156 * If we're still in the description of the chunk, just append.
158 if(inDescr)
161 * This is the first detail, so stop appending
163 if(line[0] == '*')
165 inDescr = false;
167 else
169 current->append(line);
170 continue;
175 * Find out how deep the rabbit hole goes
177 for(i = 0; i < line.size(); i++)
179 if(line[i] != '*')
181 depth = i;
182 break;
187 * Apparently not that deep, just append this line to the current detail
189 if(depth == 0)
192 * Find out how deep the tabbification is
194 int tabDepth = 0;
195 for(i = 0; i < line.size(); i++)
197 if(line[i] != '\t')
199 tabDepth = i;
200 break;
205 * The format dictates that there is at least one tab before each continuation
207 if(!tabDepth)
209 Global::Get()->bugf("Malformed import line.\n");
210 m_result.reset();
211 return;
214 /**
215 * Erase the tabs and append it to the current detail
217 line.erase(0, tabDepth);
218 current->append(line);
219 continue;
220 } // if(depth == 0)
222 line.erase(0, depth);
224 if(depth < lastDepth)
226 details.top()->addDetail(current);
227 current = details.top();
228 details.pop();
231 if(depth > lastDepth)
233 details.push(current);
234 current.reset(new MyDetail());
238 * This needs to be done not only when depth==lastDepth, but also when we just went down a detail level
240 if(lastDepth >= depth && details.size())
242 details.top()->addDetail(current);
243 current.reset(new MyDetail());
246 current->append(line);
247 lastDepth = depth;
250 while(details.size() > 0)
252 details.top()->addDetail(current);
253 current = details.top();
254 details.pop();
257 m_result = current;
258 m_resultstring = current->toString();
261 void ChunkImporter::Apply(mud::ChunkPtr chunk)
263 Assert(chunk);
266 * Set description to that of the top node
268 chunk->setDescription(String::Get()->unlines(m_result->getDescription() , " ", 0));
271 * Add all the details as details of the chunk
273 MyDetailVector details = m_result->getDetails();
274 for(MyDetailVector::iterator it = details.begin(); it != details.end(); it++)
276 MyDetailPtr onedetail = *it;
278 KeysPtr detailkeys = mud::Managers::Get()->Detail->Add();
279 mud::DetailPtr detail = mud::Managers::Get()->Detail->GetByKey(detailkeys ->first()->getIntegerValue());
280 detail->setDescription(String::Get()->unlines(onedetail->getDescription() , " ", 0));
281 detail->Save();
284 * Connect the new detail to the chunk
286 RelationPtr relation(new Relation(db::TableImpls::Get()->DETAILS));
287 relation->addKey(db::TableImpls::Get()->DETAILS->DETAILID, chunk->getID());
288 relation->addKey(db::TableImpls::Get()->CHUNKS->CHUNKID, detail->getID());
289 relation->save();
291 onedetail->apply(detail);
295 const std::string& ChunkImporter::getResult()
297 return m_resultstring;