1 ///////////////////////////////////////////////////////////
2 // Softwarebauelemente II, Aufgabe O3.5
3 //
4 // author: Stephan Brumme
5 // last changes: June 27, 2001
6
7
8 #include "House.h"
9 #include "Exception.h"
10
11 // needed for std::find
12 #include <algorithm>
13
14
15
16 CHouse::CHouse()
17 {
18 m_Set.empty();
19 m_itCursor = m_Set.begin();
20 }
21
22 CHouse::CHouse(const CHouse& house)
23 {
24 operator=(house);
25 }
26
27 // constructs a new house using its date of foundation (default: today)
28 CHouse::CHouse(const CDate& dtDateOfFoundation)
29 {
30 m_dtDateOfFoundation = dtDateOfFoundation;
31 m_Set.empty();
32 m_itCursor = m_Set.begin();
33 }
34
35
36 // show attributes
37 string CHouse::Show() const
{
38 // check invariance
39 if (!ClassInvariant())
40 return "";
41
42 ostringstream strOutput;
43
44 // some general information
45 strOutput << "The house was founded on " << m_dtDateOfFoundation.Show()
46 << " and consists of "
47 << m_Set.size() << " rooms: " << endl;
48
49 // stream all rooms
50 TSetConstCursor itCursor;
51
52 for (itCursor = m_Set.begin(); itCursor != m_Set.end(); itCursor++)
53 strOutput << " " << itCursor->Show() << endl;
54
55 return strOutput.str();
56 }
57
58
59 // shows all internal attributes
60 string CHouse::ShowDebug() const
{
61 ostringstream strOutput;
62
63 // print any information about this class
64 strOutput << "DEBUG info for 'CHouse'" << endl
65 << " m_dtDateOfFoundation=" << m_dtDateOfFoundation.Show() << endl
<< " m_nCount=" << m_Set.size() << endl;
66
67 // stream all rooms
68 // this iterator needs to be const ...
69 TSetConstCursor itCursor;
70
71 strOutput << " m_vecSet=" << endl;
72 for (itCursor = m_Set.begin(); itCursor != m_Set.end(); itCursor++)
73 strOutput << " " << itCursor->Show() << endl;
74
75 return strOutput.str();
76 }
77
78
79 // validate a house
80 bool CHouse::ClassInvariant() const
{
81 // check date of foundation
82 if (!m_dtDateOfFoundation.ClassInvariant())
83 return false;
84
85 // no room should be held twice in the array
86 TSetConstCursor itCursor;
87 itCursor = m_Set.begin();
88
89 while (itCursor != m_Set.end())
90 {
91 // verify invariance of each stored room
92 if (!itCursor->ClassInvariant())
93 return false;
94
95 // next room
96 itCursor++;
97
98 // look for exact copy
99 TSetConstCursor itFind;
100 itFind = std::find(itCursor, m_Set.end(), *itCursor);
101
102 // copy found ?
103 // if (itFind != m_Set.end())
104 // return false;
105 }
106
107 return true;
108 }
109
110
111 // copy constructor
112 CHouse& CHouse::operator =(const CHouse &house)
113 {
114 m_dtDateOfFoundation = house.m_dtDateOfFoundation;
115 m_itCursor = house.m_itCursor;
116 // container performs the whole copy internally
117 m_Set = house.m_Set;
118
119 return *this;
120 }
121
122
123 // virtual, see operator=
124 bool CHouse::Copy(const CBasicClass* pClass)
125 {
126 // cast to CHouse
127 const CHouse *house = dynamic_cast<const CHouse*>(pClass);
128
129 // invalid class (is NULL when pClass is not a CHouse)
130 if (house == NULL || house == this)
131 return false;
132
133 // use non virtual reference based copy
134 // return value isn't needed
135 operator=(*house);
136
137 // we're done
138 return true;
139 }
140
141
142 // compare two houses
143 bool CHouse::operator ==(const CHouse &house) const
{
144 // compare date of foundation
145 if (!(m_dtDateOfFoundation == house.m_dtDateOfFoundation))
146 return false;
147
148 // find each room of the given house in our house
149 TSetConstCursor itCursor;
150 for (itCursor = house.m_Set.begin(); itCursor != house.m_Set.end(); itCursor++)
151 // I re-implement the find method because of keeping this method const
152 if (std::find(m_Set.begin(), m_Set.end(), *itCursor) == m_Set.end())
153 return false;
154
155 // all rooms were found
156 return true;
157 }
158
159
160 // virtual, see operator==
161 bool CHouse::EqualValue(const CBasicClass* pClass) const
{
162 // cast to CHouse
163 const CHouse *house = dynamic_cast<const CHouse*>(pClass);
164
165 // invalid class (is NULL when pClass is not a CHouse)
166 if (house == NULL || house == this)
167 return false;
168
169 // use non virtual reference based copy
170 return operator==(*house);
171 }
172
173
174 // return date of foundation
175 CDate CHouse::GetDateOfFoundation() const
{
176 return m_dtDateOfFoundation;
177 }
178
179
180 // return number of stored rooms
181 int CHouse::Card() const
{
182 return m_Set.size();
183 }
184
185
186 // insert a new room into the set, TRUE if successful
187 // will fail if room already exists
188 bool CHouse::Insert(const CRoom &room)
189 {
190 // room should be valid
191 if (!room.ClassInvariant())
192 // throw CException("CHouse::Insert: invalid room", this);
193 return false;
194
195 // there must be some memory to grow the set
196 if (m_Set.size() > m_Set.max_size())
197 throw CException("CHouse::Insert: out of memory", this);
198
199 // and the room must not be part of the list
200 if (Find(room))
201 return false;
202
203 // insert at the tail of the list
204 m_Set.push_back(room);
205
206 return true;
207 }
208
209
210 // return first stored room, TRUE if successful
211 bool CHouse::GetFirst(CRoom &room)
212 {
213 // set must not be empty
214 if (m_Set.empty())
215 // throw CException("CHouse::GetFirst: empty set", this);
216 return false;
217
218 // set cursor to first room
219 m_itCursor = m_Set.begin();
220 // get this room
221 room = *m_itCursor;
222
223 return true;
224 }
225
226
227 // return next room, TRUE if successful
228 bool CHouse::GetNext(CRoom &room)
229 {
230 // set must not be empty, end must not be reached
231 if (m_Set.empty())
232 // throw CException("CHouse::GetNext: empty set", this);
233 return false;
234
235 if (m_itCursor != m_Set.end())
236 // throw CException("CHouse::GetNext: reached end", this);
237 return false;
238
239 // iterate to next object
240 m_itCursor++;
241 // get this object
242 room = *m_itCursor;
243
244 return true;
245 }
246
247
248 // look for a room and set cursor, TRUE if successful
249 bool CHouse::Find(const CRoom &room)
250 {
251 // set must not be empty
252 if (m_Set.empty())
253 // throw CException("CHouse::Find: empty set", this);
254 return false;
255
256 // create new iterator
257 TSetCursor itCursor;
258
259 // use STL's find
260 itCursor = std::find(m_Set.begin(), m_Set.end(), room);
261
262 // change m_itCursor if room was found
263 if (itCursor != m_Set.end())
264 {
265 m_itCursor = itCursor;
266 return true;
267 }
268 else
return false;
269 }
270
271
272 // return the room the cursor points to, TRUE if successful
273 bool CHouse::GetCurrent(CRoom &room) const
{
274 // set must not be empty
275 if (m_Set.empty())
276 throw CException("CHouse::GetCurrent: empty set", this);
277
278 // return current room
279 room = *m_itCursor;
280 return true;
281 }
282
283
284 // erase current room, TRUE if successful
285 bool CHouse::Scratch()
286 {
287 // set must not be empty
288 if (m_Set.empty())
289 throw CException("CHouse::Scratch: empty set", this);
290
291 // erase room, set cursor to next room
292 m_itCursor = m_Set.erase(m_itCursor);
293 return true;
294 }
295
296
297 // emulates basic iterator independent of those from STL
298 void CHouse::ForEachDo(const TIteratorFunc iteratorProc)
299 {
300 // save current cursor
301 TSetCursor itCursor = m_itCursor;
302
303 m_itCursor = m_Set.begin();
304 while (m_itCursor != m_Set.end())
305 {
306 CRoom* room = &(*m_itCursor);
307 iteratorProc(room);
308 m_itCursor++;
309 }
310
311 // restore cursor
312 m_itCursor = itCursor;
313 }
314
315
316 // helper
317 static ostringstream _strShow;
318 static void _ShowProc(CRoom* room)
319 {
320 _strShow << room->Show();
321 }
322
323
324 // same functionality as Show, I just use ForEachDo this time
325 string CHouse::ShowUsingForEachDo() const
{
326 CHouse* house = const_cast<CHouse*>(this);
327 house->ForEachDo(_ShowProc);
328
329 return _strShow.str();
330 }
331
332