Design Pattern Examples
Overview of object-oriented design patterns
Mediator_Exercise.c
Go to the documentation of this file.
1
5
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "helpers/stringlist.h"
13
14#include "Mediator_Functions.h"
15#include "Mediator_Exercise.h"
16
17//=============================================================================
18//=============================================================================
19
30static bool _ListToString(StringList* items, DynamicString* output)
31{
32 bool success = false;
33
34 if (items != NULL && output != NULL)
35 {
36 success = true;
37 for (size_t index = 0; index < items->strings_count; ++index)
38 {
39 if (index != 0)
40 {
41 success = DynamicString_Append(output, ", ");
42 }
43 if (success)
44 {
45 success = DynamicString_Append(output, items->strings[index]);
46 }
47
48 if (!success)
49 {
50 printf(" Error! Out of memory condition converting a list of strings to a comma-delimited string in _ListToString()!\n");
51 break;
52 }
53 }
54 }
55
56 return success;
57}
58
65static const char* _GetMediatorErrorMessage(MediatorErrorCode errorCode)
66{
67 const char* msg = "";
68
69 switch (errorCode)
70 {
72 msg = "Group does not exist";
73 break;
74
76 msg = "User does not exist";
77 break;
78
80 msg = "Null argument";
81 break;
82
84 msg = "Out of memory";
85 break;
86
88 msg = "No error";
89 break;
90
91 default:
92 msg = "Unknown error";
93 break;
94 }
95
96 return msg;
97}
98
110static void _ReportAnyMediatorError(const char *prompt, MediatorErrorCode errorCode)
111{
112 if (errorCode != MediatorErrorCode_No_Error)
113 {
114 const char* msg = _GetMediatorErrorMessage(errorCode);
115 if (prompt == NULL)
116 {
117 prompt = "Unknown operation";
118 }
119 printf(" Error! %s: %s!\n", prompt, msg);
120 }
121}
122
123
130static bool Mediator_SetupUsers(void)
131{
132 MediatorErrorCode errorCode;
133 // Operation 12: Add a user
134 errorCode = Mediator_AddUser("Stephen");
135 _ReportAnyMediatorError("Adding user \"Stephen\"", errorCode);
136 if (errorCode == MediatorErrorCode_No_Error)
137 {
138 errorCode = Mediator_AddUser("Gladys");
139 _ReportAnyMediatorError("Adding user \"Gladys\"", errorCode);
140 }
141 if (errorCode == MediatorErrorCode_No_Error)
142 {
143 errorCode = Mediator_AddUser("Marvin");
144 _ReportAnyMediatorError("Adding user \"Marvin\"", errorCode);
145 }
146 if (errorCode == MediatorErrorCode_No_Error)
147 {
148 errorCode = Mediator_AddUser("Arthur");
149 _ReportAnyMediatorError("Adding user \"Arthur\"", errorCode);
150 }
151
152 return errorCode == MediatorErrorCode_No_Error;
153}
154
163static bool Mediator_SetupGroups(void)
164{
165 MediatorErrorCode errorCode;
166 // Operation 10: Add a group
167 errorCode = Mediator_AddGroup("admins");
168 _ReportAnyMediatorError("Adding group \"admin\"", errorCode);
169 if (errorCode == MediatorErrorCode_No_Error)
170 {
171 errorCode = Mediator_AddGroup("Users");
172 _ReportAnyMediatorError("Adding group \"Users\"", errorCode);
173 }
174 if (errorCode == MediatorErrorCode_No_Error)
175 {
176 errorCode = Mediator_AddGroup("Power Users");
177 _ReportAnyMediatorError("Adding group \"Power Users\"", errorCode);
178 }
179
180 // Operation 7: Add user to a group
181 if (errorCode == MediatorErrorCode_No_Error)
182 {
183 errorCode = Mediator_AddUserToGroup("Marvin", "admins");
184 _ReportAnyMediatorError("Adding \"Marvin\" to \"admin\"", errorCode);
185 }
186 if (errorCode == MediatorErrorCode_No_Error)
187 {
188 errorCode = Mediator_AddUserToGroup("Arthur", "admins");
189 _ReportAnyMediatorError("Adding \"Arthur\" to \"admin\"", errorCode);
190 }
191 if (errorCode == MediatorErrorCode_No_Error)
192 {
193 errorCode = Mediator_AddUserToGroup("Stephen", "Users");
194 _ReportAnyMediatorError("Adding \"Stephen\" to \"Users\"", errorCode);
195 }
196 if (errorCode == MediatorErrorCode_No_Error)
197 {
198 errorCode = Mediator_AddUserToGroup("Gladys", "Users");
199 _ReportAnyMediatorError("Adding \"Gladys\" to \"Users\"", errorCode);
200 }
201 if (errorCode == MediatorErrorCode_No_Error)
202 {
203 errorCode = Mediator_AddUserToGroup("Arthur", "Power Users");
204 _ReportAnyMediatorError("Adding \"Arthur\" to \"Power Users\"", errorCode);
205 }
206 if (errorCode == MediatorErrorCode_No_Error)
207 {
208 errorCode = Mediator_AddUserToGroup("Marvin", "Power Users");
209 _ReportAnyMediatorError("Adding \"Marvin\" to \"Power Users\"", errorCode);
210 }
211
212 return errorCode == MediatorErrorCode_No_Error;
213}
214
222{
223 bool canContinue = false;
224 DynamicString output = { 0 };
225 StringList groupNames = { 0 };
226 MediatorErrorCode errorCode;
227 //-----------------------------------------------------------------
228 // Operation 1: Determine all groups
229 errorCode = Mediator_GetAllGroups(&groupNames);
230 _ReportAnyMediatorError("Getting all groups", errorCode);
231 if (errorCode == MediatorErrorCode_No_Error)
232 {
233 canContinue = _ListToString(&groupNames, &output);
234 if (canContinue)
235 {
236 printf(" Operation 1: Show all groups\n");
237 printf(" All groups: %s\n", output.string);
238 }
239 DynamicString_Clear(&output);
240 StringList_Clear(&groupNames);
241 }
242
243 return canContinue;
244}
245
253{
254 bool canContinue = false;
255 DynamicString output = { 0 };
256 StringList userNames = { 0 };
257 MediatorErrorCode errorCode;
258 //-----------------------------------------------------------------
259 // Operation 2: Determine all users
260 errorCode = Mediator_GetAllUsers(&userNames);
261 _ReportAnyMediatorError("Getting all users", errorCode);
262 if (errorCode == MediatorErrorCode_No_Error)
263 {
264 canContinue = _ListToString(&userNames, &output);
265 if (canContinue)
266 {
267 printf(" Operation 2: Show all users\n");
268 printf(" All users : %s\n", output.string);
269 }
270 DynamicString_Clear(&output);
271 StringList_Clear(&userNames);
272 }
273
274 return canContinue;
275}
276
284{
285 bool canContinue = true;
286 const char* userName = "Arthur";
287 const char* groupName = "admins";
288 // Operation 3: Does a user belong to a group
289 printf(" Operation 3: Determine if a user is a member of a specific group.\n");
290 printf(" Is user '%s' in the '%s' group?", userName, groupName);
291 printf(" %s\n", Mediator_IsUserInGroup(userName, groupName) ? "Yes" : "No");
292
293 return canContinue;
294}
295
303{
304 bool canContinue = false;
305 DynamicString output = { 0 };
306 StringList userNames = { 0 };
307 const char* groupName = "Users";
308 MediatorErrorCode errorCode;
309 // Operation 4: Show all users in a group
310 printf(" Operation 4: Show all users in a specific group.\n");
311 errorCode = Mediator_GetUsersInGroup(groupName, &userNames);
312 _ReportAnyMediatorError("Getting all users in a group", errorCode);
313 if (errorCode == MediatorErrorCode_No_Error)
314 {
315 canContinue = _ListToString(&userNames, &output);
316 if (canContinue)
317 {
318 printf(" All users in '%s' group: %s\n", groupName, output.string);
319 }
320 DynamicString_Clear(&output);
321 StringList_Clear(&userNames);
322 }
323
324 return canContinue;
325}
326
334{
335 bool canContinue = false;
336 DynamicString output = { 0 };
337 StringList groupNames = { 0 };
338 const char* userName = "Marvin";
339 MediatorErrorCode errorCode;
340 // Operation 5: Show all groups with a user
341 printf(" Operation 5: Show all groups containing a specific user.\n");
342 errorCode = Mediator_GetGroupsWithUser(userName, &groupNames);
343 _ReportAnyMediatorError("Getting all groups containing a user", errorCode);
344 if (errorCode == MediatorErrorCode_No_Error)
345 {
346 canContinue = _ListToString(&groupNames, &output);
347 if (canContinue)
348 {
349 printf(" All groups with user '%s': %s\n", userName, output.string);
350 }
351 DynamicString_Clear(&output);
352 StringList_Clear(&groupNames);
353 }
354
355 return canContinue;
356}
357
358
366{
367 bool canContinue = false;
368 DynamicString output = { 0 };
369 StringList groupNames = { 0 };
370 const char* userName = "Marvin";
371 const char* groupName = "Power Users";
372 MediatorErrorCode errorCode;
373 // Operation 6: Show Remove a user from a group
374 printf(" Operation 6: Remove a user from a group.\n");
375 errorCode = Mediator_RemoveUserFromGroup(userName, groupName);
376 _ReportAnyMediatorError("Removing user from a group", errorCode);
377 if (errorCode == MediatorErrorCode_No_Error)
378 {
379 printf(" Removed user '%s' from group '%s'\n", userName, groupName);
380 errorCode = Mediator_GetGroupsWithUser(userName, &groupNames);
381 _ReportAnyMediatorError("Getting groups with a user", errorCode);
382 if (errorCode == MediatorErrorCode_No_Error)
383 {
384 canContinue = _ListToString(&groupNames, &output);
385 if (canContinue)
386 {
387 printf(" All groups with user '%s': %s\n", userName, output.string);
388 }
389 DynamicString_Clear(&output);
390 StringList_Clear(&groupNames);
391 }
392 }
393
394 return canContinue;
395}
396
404{
405 bool canContinue = false;
406 DynamicString output = { 0 };
407 StringList groupNames = { 0 };
408 const char* userName = "Marvin";
409 const char* groupName = "Users";
410 MediatorErrorCode errorCode;
411 // Operation 7: Add a user to a group
412 printf(" Operation 7: Add a user to a group.\n");
413 printf(" Adding user '%s' to group '%s'.\n", userName, groupName);
414 errorCode = Mediator_AddUserToGroup(userName, groupName);
415 _ReportAnyMediatorError("Adding user to a group", errorCode);
416 if (errorCode == MediatorErrorCode_No_Error)
417 {
418 errorCode = Mediator_GetGroupsWithUser(userName, &groupNames);
419 _ReportAnyMediatorError("Getting groups with a user", errorCode);
420 if (errorCode == MediatorErrorCode_No_Error)
421 {
422 canContinue = _ListToString(&groupNames, &output);
423 if (canContinue)
424 {
425 printf(" All groups with user '%s': %s\n", userName, output.string);
426 }
427 DynamicString_Clear(&output);
428 StringList_Clear(&groupNames);
429 }
430 }
431
432 return canContinue;
433}
434
442{
443 bool canContinue = false;
444 DynamicString output = { 0 };
445 StringList groupNames = { 0 };
446 const char* userName = "Arthur";
447 MediatorErrorCode errorCode;
448 // Operation 8: Remove a user from all groups
449 printf(" Operation 8: Remove a user from all groups.\n");
450 errorCode = Mediator_GetGroupsWithUser(userName, &groupNames);
451 _ReportAnyMediatorError("Getting groups with a user before removing user", errorCode);
452 if (errorCode == MediatorErrorCode_No_Error)
453 {
454 canContinue = _ListToString(&groupNames, &output);
455 if (canContinue)
456 {
457 printf(" Removing user '%s' from all groups.\n", userName);
458 printf(" Start: all groups with user '%s': %s\n", userName, output.string);
459 DynamicString_Clear(&output);
460 StringList_Clear(&groupNames);
461 printf(" Removing...\n");
462 errorCode = Mediator_RemoveUserFromAllGroups(userName);
463 _ReportAnyMediatorError("Removing user from all groups", errorCode);
464 if (errorCode == MediatorErrorCode_No_Error)
465 {
466 errorCode = Mediator_GetGroupsWithUser(userName, &groupNames);
467 _ReportAnyMediatorError("Getting groups with a user after removing user", errorCode);
468 if (errorCode == MediatorErrorCode_No_Error)
469 {
470 canContinue = _ListToString(&groupNames, &output);
471 if (canContinue)
472 {
473 printf(" End: all groups with user '%s': %s\n", userName, output.string);
474 }
475 DynamicString_Clear(&output);
476 StringList_Clear(&groupNames);
477 }
478 }
479 }
480 }
481
482 return canContinue;
483}
484
492{
493 bool canContinue = false;
494 DynamicString output = { 0 };
495 StringList groupNames = { 0 };
496 StringList userNames = { 0 };
497 const char* userName = "Marvin";
498 MediatorErrorCode errorCode;
499 // Operation 9: Remove a user (which also removes user from all groups)
500 printf(" Operation 9: Remove a user (also removes the user from all groups).\n");
501 printf(" Removing user '%s'.\n", userName);
502 errorCode = Mediator_RemoveUser(userName);
503 _ReportAnyMediatorError("Removing a user", errorCode);
504 if (errorCode == MediatorErrorCode_No_Error)
505 {
506 errorCode = Mediator_GetAllUsers(&userNames);
507 _ReportAnyMediatorError("Getting all users after removing a user", errorCode);
508 if (errorCode == MediatorErrorCode_No_Error)
509 {
510 canContinue = _ListToString(&userNames, &output);
511 if (canContinue)
512 {
513 printf(" All users : %s\n", output.string);
514 }
515 DynamicString_Clear(&output);
516 StringList_Clear(&userNames);
517 }
518 }
519
520 if (errorCode == MediatorErrorCode_No_Error && canContinue)
521 {
522 errorCode = Mediator_GetAllGroups(&groupNames);
523 _ReportAnyMediatorError("Getting all groups after removing a user", errorCode);
524 if (errorCode == MediatorErrorCode_No_Error)
525 {
526 for (size_t index = 0; index < groupNames.strings_count; index++)
527 {
528 const char* name = groupNames.strings[index];
529 errorCode = Mediator_GetUsersInGroup(name, &userNames);
530 _ReportAnyMediatorError("Getting users in a group after removing a user", errorCode);
531 if (errorCode == MediatorErrorCode_No_Error)
532 {
533 canContinue = _ListToString(&userNames, &output);
534 if (canContinue)
535 {
536 printf(" Users in group '%s': %s\n", name, output.string);
537 }
538 DynamicString_Clear(&output);
539 StringList_Clear(&userNames);
540 if (!canContinue)
541 {
542 break;
543 }
544 }
545 else
546 {
547 canContinue = false;
548 break;
549 }
550 }
551 }
552 }
553
554 return canContinue;
555}
556
557//=============================================================================
558//=============================================================================
559
576// ! [Using Mediator in C]
578{
579 printf("\nMediator Exercise\n");
580
581 bool canContinue = Mediator_SetupUsers();
582 if (canContinue)
583 {
584 canContinue = Mediator_SetupGroups();
585 }
586
587 if (canContinue)
588 {
589 canContinue = _Mediator_Example_ShowAllGroups();
590 }
591
592 if (canContinue)
593 {
594 canContinue = _Mediator_Example_ShowAllUsers();
595 }
596
597 if (canContinue)
598 {
600 }
601
602 if (canContinue)
603 {
605 }
606
607 if (canContinue)
608 {
610 }
611
612 if (canContinue)
613 {
615 }
616
617 if (canContinue)
618 {
619 canContinue = _Mediator_Example_AddUserToGroup();
620 }
621
622 if (canContinue)
623 {
625 }
626
627 if (canContinue)
628 {
629 canContinue = _Mediator_Example_RemoveUser();
630 }
631 //-----------------------------------------------------------------
632
633 // Clean-up
635
636 printf(" Done.\n");
637}
638// ! [Using Mediator in C]
static const char * _GetMediatorErrorMessage(MediatorErrorCode errorCode)
Helper function to convert a MediatorErrorCode to a string.
static bool _Mediator_Example_RemoveUserFromAllGroups(void)
Helper function example of how to remove a user from all groups.
static bool _ListToString(StringList *items, DynamicString *output)
Helper function to convert a list of strings to a comma-delimited list in a single string.
static bool Mediator_SetupUsers(void)
Helper function to add a number of users to the Users list.
static bool Mediator_SetupGroups(void)
Helper function to add a number of groups to the Groups list and then add users to the groups....
static bool _Mediator_Example_RemoveUser(void)
Helper function example of how to remove a user.
static bool _Mediator_Example_ShowAllGroupsContainingUser(void)
Helper function example of how to show all groups containing a user.
static bool _Mediator_Example_RemoveUserFromGroup(void)
Helper function example of how to remove a user from a group.
static bool _Mediator_Example_AddUserToGroup(void)
Helper function example of how to add a user to a group.
static bool _Mediator_Example_SeeIfUserInGroup(void)
Helper function example of how to see if a user is in a group.
static bool _Mediator_Example_ShowAllUsers(void)
Helper function example of how to show all users.
static bool _Mediator_Example_ShowAllGroups(void)
Helper function example of how to show all groups.
static void _ReportAnyMediatorError(const char *prompt, MediatorErrorCode errorCode)
Helper function for reporting an error if an error has occurred. Always call this after any mediator ...
static bool _Mediator_Example_ShowUsersInGroup(void)
Helper function example of how to show all users in a group.
void Mediator_Exercise(void)
Example of using the Mediator Pattern.
MediatorErrorCode Mediator_GetGroupsWithUser(const char *userName, StringList *groupNames)
Retrieve a list of all groups that contain the specified user.
bool Mediator_IsUserInGroup(const char *userName, const char *groupName)
Determine if the specified user is in the specified group.
MediatorErrorCode Mediator_AddGroup(const char *groupName)
Add a group to the list of known groups. If the group is already in the list, the request to add is i...
void Mediator_ClearAll(void)
Clear all memory associated with groups and users.
MediatorErrorCode Mediator_RemoveUserFromGroup(const char *userName, const char *groupName)
Remove the specified user from the specified group.
MediatorErrorCode Mediator_AddUser(const char *userName)
Add a user to the list of known users. If the name is already in the list of users,...
MediatorErrorCode Mediator_GetAllUsers(StringList *userNames)
Retrieve a list of all known users.
MediatorErrorCode Mediator_AddUserToGroup(const char *userName, const char *groupName)
Add the specified user to the specified group. If the user is already in the group,...
MediatorErrorCode Mediator_RemoveUser(const char *userName)
Removes the specified user from the list of known users, if the user exists. Also removes the user fr...
MediatorErrorCode Mediator_RemoveUserFromAllGroups(const char *userName)
Remove the specified user from all existing groups. The user still exists.
MediatorErrorCode Mediator_GetUsersInGroup(const char *groupName, StringList *userNames)
Retrieve a list of users in the specified group.
MediatorErrorCode Mediator_GetAllGroups(StringList *groupNames)
Retrieve a list of all known groups.
The front end of the Mediator system that mediates between the Users and the Groups sub-systems....
MediatorErrorCode
Represents error codes that can be returned from the Mediator functions used in the Mediator Pattern.
@ MediatorErrorCode_Null_Argument
One of the arguments was null or empty.
@ MediatorErrorCode_No_Memory
Indicates an out of memory condition.
@ MediatorErrorCode_Group_Does_Not_Exist
The specified group does not exist.
@ MediatorErrorCode_No_Error
No error occurred.
@ MediatorErrorCode_User_Does_Not_Exist
The specified user does not exist.
Declaration of the Mediator_Exercise() function as used in the Mediator Pattern.
void DynamicString_Clear(DynamicString *string)
Clear a DynamicString object, releasing any allocated memory. Resets to an empty string.
Definition: dynamicstring.c:27
bool DynamicString_Append(DynamicString *string, const char *s)
Append the specified string to the DynamicString object.
Definition: dynamicstring.c:39
Declaration of the DynamicString structure and supporting functions to work with dynamic strings.
std::vector< std::string > StringList
Typedef for a vector of std::string.
void StringList_Clear(StringList *stringList)
Clear the specified string list. All strings in the list are released. The string list can then be us...
Definition: stringlist.c:30
Represents a string that can be grown dynamically.
Definition: dynamicstring.h:16
char * string
The string that can grow.
Definition: dynamicstring.h:17