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