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 }