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