Class RoomMapper
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected abstract voidbasicUpdateRoomFromDto(NewRoomDTO editDto, Room room) Adjusts the givenRoomto match the given data-transfer object.convertCommonEquipmentToDto(@NonNull Set<CommonEquipment> commonEquipment) protected @NonNull RoomcreateRoom(@NonNull NewRoomDTO dto) abstract RoomfromDto(NewRoomDTO newRoomDTO) Converts aNewRoomDTOto aRoom.abstract RoomDTOtoDto(ConferenceRoom room) Converts aConferenceRoomto aRoomDTO.abstract RoomDTOabstract NewRoomDTOtoEditDto(ConferenceRoom room) Converts aConferenceRoomto a data-transfer object that can be used for editing.abstract NewRoomDTOConverts aRoomto a data-transfer object that can be used for editing.abstract RoomSummaryDTOtoSummaryDto(Room room) Converts a givenRoomto aRoomSummaryDTO.voidupdateRoomFromDto(NewRoomDTO editDto, Room room) Adjusts the givenRoomto match the given data-transfer object.
-
Constructor Details
-
RoomMapper
public RoomMapper()
-
-
Method Details
-
toDto
- Parameters:
room- The Room that shall be turned into a data-transfer object. If it is aConferenceRoom, then information will be lost, because the common equipment only exists on the ConferenceRoom class, but not on the Room class.- Returns:
- The given Room as a data-transfer object.
- Implementation Note:
- The
RoomDTO.commonEquipmentis mapped bycreateRoom(NewRoomDTO).
-
basicUpdateRoomFromDto
protected abstract void basicUpdateRoomFromDto(NewRoomDTO editDto, Room room) throws de.gustavblass.commons.exceptions.IllegalArgumentException Adjusts the givenRoomto match the given data-transfer object. Does not update theRoom.id,Room.reservationsand individual equipment.- Parameters:
editDto- The DTO according to which the Room shall be updated.room- Will be updated according to the DTO.- Throws:
de.gustavblass.commons.exceptions.IllegalArgumentException- If theNewRoomDTO.capacityis smaller than one. If this happens, the object may have already been altered.- Implementation Note:
- This operation is not atomic!
-
updateRoomFromDto
public void updateRoomFromDto(NewRoomDTO editDto, Room room) throws de.gustavblass.commons.exceptions.IllegalArgumentException Adjusts the givenRoomto match the given data-transfer object. Does not update theRoom.idandRoom.reservations.- Parameters:
editDto- The DTO according to which the Room shall be updated.room- Will be updated according to the DTO.- Throws:
de.gustavblass.commons.exceptions.IllegalArgumentException- If theNewRoomDTO.capacityis smaller than one. If this happens, the object may have already been altered.- Implementation Note:
- This operation is not atomic!
-
toDto
Converts aConferenceRoomto aRoomDTO.- Parameters:
room- The Room that shall be turned into a data-transfer object.- Returns:
- The given ConferenceRoom as a data-transfer object.
-
toEditDto
public abstract NewRoomDTO toEditDto(Room room) throws de.gustavblass.commons.exceptions.IllegalArgumentException Converts aRoomto a data-transfer object that can be used for editing.- Parameters:
room- The Room to convert.- Returns:
- The data-transfer object.
- Throws:
de.gustavblass.commons.exceptions.IllegalArgumentException- If someRoomEquipmentoccurs more than once. Should never happen, because otherwise the Room is invalid.
-
toEditDto
public abstract NewRoomDTO toEditDto(ConferenceRoom room) throws de.gustavblass.commons.exceptions.IllegalArgumentException Converts aConferenceRoomto a data-transfer object that can be used for editing.- Parameters:
room- The Room to convert.- Returns:
- The data-transfer object.
- Throws:
de.gustavblass.commons.exceptions.IllegalArgumentException- If someRoomEquipmentoccurs more than once. Should never happen, because otherwise the ConferenceRoom is invalid.
-
fromDto
public abstract Room fromDto(NewRoomDTO newRoomDTO) throws de.gustavblass.commons.exceptions.IllegalArgumentException Converts aNewRoomDTOto aRoom.- Parameters:
newRoomDTO- The data-transfer object to turn into a proper model object.- Returns:
- The given DTO as a proper Room. Will not have a
Room.idand noRoom.reservations. - Throws:
de.gustavblass.commons.exceptions.IllegalArgumentException- Because ofRoom.setCapacity(int).
-
toSummaryDto
Converts a givenRoomto aRoomSummaryDTO.- Parameters:
room- The Room that shall become a summarised data-transfer object.- Returns:
- The summarised data-transfer object created from the given Room.
-
createRoom
Creates a new
QuietStudyRoomorConferenceRoom, depending on theNewRoomDTO.type.Adds the
NewRoomDTO.individualEquipmentand – possibly – theNewRoomDTO.commonEquipmentto theRoom. Sets the new Room as the back-reference on the individual equipment.- Parameters:
dto- The data-transfer object which the new Room shall be based on.- Returns:
- The new Room of the correct concrete class and with the DTO's equipment.
- Implementation Note:
1. Why is this method necessary?
This method is necessary because
- MapStruct is apparently unable to choose the correct concrete implementation of the abstract Room class,
- it could not be determined how to tell MapStruct to set up the back-reference on the individual equipment,
- MapStruct is unable to map
NewRoomDTO.commonEquipmenttoConferenceRoom.commonEquipment, because the return type is the abstract Room class.
2. Why does this method not throw an exception for illegal common equipment?
As specified elsewhere,
NewRoomDTO.commonEquipmentmust only be specified ifNewRoomDTO.typeis set toRoomType.CONFERENCE_ROOM. However, if this requirement is not met, this method does not throw an exception and instead ignores the common equipment.2.1. The critical error case
This may be counterintuitive, but has a very specific reason. Imagine this scenario:
- User sets the room type to conference room.
- User selects several types of common equipment.
- User switches the room type back to
RoomType.QUIET_STUDY_ROOM. - User presses “submit”.
Then, the HTTP request would still include the common equipment from step 2 because the respective HTML input fields have not been reset. The server would yell at the user: “How dare you select any common equipment for a quiet-study room?!”
However, we absolutely do not want the user to manually unselect all the common equipment, so the common equipment must be unselected automatically for the user.
2.2. Approaches to automatically reset the input fields
CSS can only (visually) hide the common equipment's HTML input fields, but cannot change their actual values. So, in order to unset the common-equipment whenever the user switches from
RoomType.CONFERENCE_ROOMtoRoomType.QUIET_STUDY_ROOM, we would have to either …- … rely on (i.e. mandatorily require) JavaScript (which is not desirable for accessibility reasons) or
- make an HTTP request asking the server to reset the common equipment in the form.
Such an HTTP request could only be made with a special submit button.
However, if we did nothing besides adding the new submit button, the server would think that the HTTP request
serves the purpose of creating a new Room.
So, in order to tell the server that the second button is only meant to reset the common equipment, we would
either …
- … need to use a different form
actionpath (but the room-type input field can only be part of one form, so this option is impossible) or - add a special
inputHTML element, but – again – we could not modify its value dynamically.
- … need to use a different form
In other words, option 2 cannot be implemented. Only option 1 can be implemented, but would not work for any user who has disabled JavaScript.
3. Conclusion
Therefore, if we do not want to impose a JavaScript requirement on the users, we must silently discard the common equipment for quiet-study rooms.
Why does this method not throw an exception for individual equipment whose
countis zero?Once again, without JavaScript, we cannot modify the values of the individual-equipment's HTML input fields. Therefore, on the server side, we cannot distinguish between these cases:
- The user forgot to select a valid equipment count.
- The user set the
IndividualEquipment.countto zero because they want no individual equipment of thatRoomEquipment.typein the new Room.
Consequently, we can only ignore individual equipment where
count == 0.
-
convertCommonEquipmentToDto
@NonNull protected @NonNull @Unmodifiable Set<String> convertCommonEquipmentToDto(@NonNull @NonNull Set<CommonEquipment> commonEquipment) Converts aSetofCommonEquipmentto a Set ofCommonEquipmentType. This is done because the only additional information a CommonEquipment object holds is a database ID, which is irrelevant when communicating the facilities of aConferenceRoom.- Parameters:
commonEquipment- The CommonEquipment that shall be reduced to the matching CommonEquipmentTypes.- Returns:
- The CommonEquipmentTypes present in the given Set.
-