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