Coverage Summary for Class: ModelWrapper (it.polimi.ingsw.Model)
Class |
Method, %
|
Branch, %
|
Line, %
|
ModelWrapper |
83,3%
(5/6)
|
75%
(3/4)
|
81,8%
(18/22)
|
ModelWrapper$ModelModifier |
Total |
83,3%
(5/6)
|
75%
(3/4)
|
81,8%
(18/22)
|
1 package it.polimi.ingsw.Model;
2
3 import it.polimi.ingsw.Misc.OptionalValue;
4 import it.polimi.ingsw.Server.Lobby;
5 import it.polimi.ingsw.Server.Messages.Events.Internal.GameOverEvent;
6 import it.polimi.ingsw.Server.Messages.Events.Internal.ModelUpdateEvent;
7
8 import java.util.Objects;
9
10 /**
11 * This class is used by the controller to enact the game logic and (optionally) notifies the view (ie the server)
12 * whenever a meaningful change to the underlying data is carried out.
13 */
14 public class ModelWrapper {
15 private final OptionalValue<Lobby> toNotify;
16 private Model model;
17
18 /**
19 * Wraps a {@link Model} along with a {@link OptionalValue}<{@link Lobby}> object to allow for easy notification
20 * to the view (ie the lobby component) of any and all changes to the model that are carried through this object's method:
21 * {@link #editModel(ModelModifier, boolean)}
22 *
23 * @param model a non null reference to the Model
24 * @param lobby a non null optional value (can obviously be empty, but not null)
25 */
26 public ModelWrapper(Model model, OptionalValue<Lobby> lobby) {
27 Objects.requireNonNull(model);
28 Objects.requireNonNull(lobby);
29
30 this.model = model;
31 this.toNotify = lobby;
32 notifyLobby();
33 }
34
35 /**
36 * When called, notifies all clients connected to the lobby of a {@link ModelUpdateEvent} and also (if necessary)
37 * of a {@link GameOverEvent}
38 */
39 private void notifyLobby() {
40 this.toNotify.ifPresent(lobby -> {
41 lobby.notifyPlayers(new ModelUpdateEvent(this.modelCopy(true)));
42 this.model.getWinners().ifPresent(winners ->
43 lobby.notifyPlayers(new GameOverEvent(winners.stream()
44 .map(PlayerBoard::getNickname)
45 .toList())));
46 });
47 }
48
49 /**
50 * When called, returns a copy of the Model object
51 *
52 * @param sanitize if set to true, tells the method to remove the {@link StudentBag} reference to prevent
53 * peeking at the contents of the bag
54 * @return an optionally sanitized clone of the wrapped {@link Model} object
55 */
56 public Model modelCopy(boolean sanitize) {
57 Model copy = model.copy();
58 if (sanitize) {
59 copy.getMutableStudentBag().removeContentReference();
60 }
61 return copy;
62 }
63
64 /**
65 * When called, allows a {@link ModelModifier} type of function to carry out changes to the {@link Model}, then notifies
66 * the lobby of such changes
67 *
68 * @param modelModifier a function or method that can be linked to the {@link ModelModifier} interface
69 * @param keepUnsafeReference if set to true, the model reference is kept unaltered after a successful edit action, allowing for
70 * debugging introspection of the model. If unsure, set it to false for best security.
71 * @throws Exception the modelModifier can optionally throw Exceptions, which will be escalated to the caller.
72 */
73 public void editModel(ModelModifier modelModifier, boolean keepUnsafeReference) throws Exception {
74 Model toModify;
75 if (keepUnsafeReference) {
76 toModify = this.model;
77 } else {
78 toModify = modelCopy(false);
79 }
80 modelModifier.modifyModel(toModify);
81 this.model = toModify;
82 notifyLobby();
83 }
84
85 /**
86 * An interface that covers methods trying to access the Model. Read {@link #modifyModel(Model)} for more information
87 */
88 public interface ModelModifier {
89 /**
90 * The function responsible for changes to the {@link Model}
91 *
92 * @param model a reference to the {@link Model} object. In order to grant safe access to the model, the reference ceases to hold
93 * meaning once this function terminates
94 * @throws Exception the modelModifier can optionally throw Exceptions, which will be escalated to the caller.
95 */
96 void modifyModel(Model model) throws Exception;
97 }
98 }