Skip to content

Commit

Permalink
[REFACTOR] Refactoring of operations with devices (#75)
Browse files Browse the repository at this point in the history
Refactoring of operations with devices, refactoring of  test cases
  • Loading branch information
justJavaProgrammer authored Aug 27, 2024
1 parent 194450e commit 4ec29ea
Show file tree
Hide file tree
Showing 34 changed files with 323 additions and 435 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import com.odeyalo.sonata.connect.model.Device;
import com.odeyalo.sonata.connect.model.User;
import com.odeyalo.sonata.connect.service.TargetDevices;
import com.odeyalo.sonata.connect.service.player.DeviceOperations;
import com.odeyalo.sonata.connect.service.player.DisconnectDeviceArgs;
import com.odeyalo.sonata.connect.service.player.SwitchDeviceCommandArgs;
import com.odeyalo.sonata.connect.service.player.TargetDeactivationDevices;
import com.odeyalo.sonata.connect.service.player.sync.TargetDevices;
import com.odeyalo.sonata.connect.service.support.mapper.dto.AvailableDevicesResponseDtoConverter;
import com.odeyalo.sonata.connect.support.web.HttpStatus;
import com.odeyalo.sonata.connect.support.web.annotation.ConnectionTarget;
Expand Down Expand Up @@ -39,7 +39,7 @@ public Mono<ResponseEntity<?>> getAvailableDevices(@NotNull final User user) {
public Mono<ResponseEntity<?>> addDevice(@NotNull final User user,
@NotNull @ConnectionTarget final Device device) {

return deviceOperations.addDevice(user, device)
return deviceOperations.connectDevice(user, device)
.subscribeOn(Schedulers.boundedElastic())
.thenReturn(HttpStatus.default204Response());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;

import static org.springframework.http.ResponseEntity.*;
import static org.springframework.http.ResponseEntity.badRequest;
import static org.springframework.http.ResponseEntity.unprocessableEntity;

@RestControllerAdvice
public class GlobalExceptionHandlerController {

public static final String NO_ACTIVE_DEVICE_ERROR_DESCRIPTION = "Player command failed: No active device found";

@ExceptionHandler(WebExchangeBindException.class)
public ResponseEntity<ExceptionMessages> handleWebExchangeBindException(WebExchangeBindException ex) {
ExceptionMessages messages = ExceptionMessages.empty();
Expand All @@ -37,7 +36,7 @@ public ResponseEntity<ExceptionMessage> handleIllegalStateException(IllegalState

@ExceptionHandler(NoActiveDeviceException.class)
public ResponseEntity<ReasonCodeAwareExceptionMessage> handleNoActiveDeviceException(NoActiveDeviceException ex) {
return badRequest().body(ReasonCodeAwareExceptionMessage.of(ex.getReasonCode(), NO_ACTIVE_DEVICE_ERROR_DESCRIPTION));
return badRequest().body(ReasonCodeAwareExceptionMessage.of(ex.getReasonCode(), "Player command failed: No active device found"));
}


Expand Down Expand Up @@ -78,6 +77,11 @@ public ResponseEntity<?> handleMissingRequestParameterException(final MissingReq
.body(ExceptionMessage.of(ex.getMessage()));
}

@ExceptionHandler(IllegalCommandStateException.class)
public ResponseEntity<ReasonCodeAwareExceptionMessage> handleIllegalCommandStateException(IllegalCommandStateException ex) {
return badRequest().body(ReasonCodeAwareExceptionMessage.of(ex.getReasonCode(), "Player command failed: Nothing is playing now and context is null!"));
}

@ExceptionHandler(MissingPlayableItemException.class)
public ResponseEntity<?> handleMissingPlayableItemException(final MissingPlayableItemException ex) {
final var body = ReasonCodeAwareExceptionMessage.of(ex.getReasonCode(), "Player command error: no item is playing");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.odeyalo.sonata.connect.model;

import com.odeyalo.sonata.connect.exception.IllegalCommandStateException;
import com.odeyalo.sonata.connect.exception.MissingPlayableItemException;
import com.odeyalo.sonata.connect.exception.NoActiveDeviceException;
import com.odeyalo.sonata.connect.exception.SeekPositionExceedDurationException;
import com.odeyalo.sonata.connect.service.player.SeekPosition;
import com.odeyalo.sonata.connect.service.player.TargetDeactivationDevice;
Expand Down Expand Up @@ -153,6 +155,11 @@ public CurrentPlayerState transferPlayback(@NotNull final TargetDevice deviceToT

@NotNull
public CurrentPlayerState play(@NotNull final PlayableItem item) {

if ( missingActiveDevice() ) {
throw NoActiveDeviceException.defaultException();
}

return this.toBuilder()
.playing(true)
.playableItem(item)
Expand All @@ -164,6 +171,11 @@ public CurrentPlayerState play(@NotNull final PlayableItem item) {

@NotNull
public CurrentPlayerState resumePlayback() {

if ( missingPlayingItem() ) {
throw IllegalCommandStateException.withCustomMessage("Player command failed: Nothing is playing now and context is null!");
}

return this.toBuilder()
.playing(true)
.playStartTime(clock.currentTimeMillis())
Expand All @@ -172,6 +184,11 @@ public CurrentPlayerState resumePlayback() {

@NotNull
public CurrentPlayerState pause() {

if ( missingActiveDevice() ) {
throw NoActiveDeviceException.defaultException();
}

if ( isPlaying() ) {
return this.toBuilder()
.playing(false)
Expand Down
22 changes: 14 additions & 8 deletions src/main/java/com/odeyalo/sonata/connect/model/Devices.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ public static Devices empty() {
return builder().build();
}

@NotNull
public static Devices of(final Device... devices) {
return fromCollection(Arrays.asList(devices));
}

public boolean isEmpty() {
return devices.isEmpty();
}
Expand Down Expand Up @@ -129,6 +134,7 @@ public Devices deactivateDevice(@NotNull final Device deviceToDeactivate) {

/**
* Change the volume for ACTIVE device
*
* @param volume - volume to set for active deivce
* @return - updated {@link Devices}
* @throws NoActiveDeviceException - if there is no active device present
Expand All @@ -147,14 +153,7 @@ public Devices changeVolume(@NotNull final Volume volume) {
@NotNull
private Device findDeviceToActivate(@NotNull final TargetDevice searchTarget) {
return findById(searchTarget)
.orElseThrow(() -> DeviceNotFoundException.withCustomMessage(String.format("Device with ID: %s not found", searchTarget.getId())));
}

@Nullable
private Device findCurrentlyActiveDevice() {
return getActiveDevices().stream()
.findFirst()
.orElse(null);
.orElseThrow(() -> DeviceNotFoundException.withCustomMessage(String.format("Device with ID: %s not found!", searchTarget.getId())));
}

@NotNull
Expand All @@ -164,6 +163,13 @@ private Devices removeDevice(@NotNull final String deviceId) {
.collect(CollectorImpl.instance());
}

@Nullable
private Device findCurrentlyActiveDevice() {
return getActiveDevices().stream()
.findFirst()
.orElse(null);
}

@NotNull
private Devices addDevice(@NotNull final Device device) {
return Devices.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.odeyalo.sonata.connect.service.player.sync;
package com.odeyalo.sonata.connect.service;

import com.odeyalo.sonata.connect.service.player.TargetDevice;
import lombok.AllArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,41 @@
import com.odeyalo.sonata.connect.model.Device;
import com.odeyalo.sonata.connect.model.Devices;
import com.odeyalo.sonata.connect.model.User;
import com.odeyalo.sonata.connect.service.TargetDevices;
import com.odeyalo.sonata.connect.service.player.handler.TransferPlaybackCommandHandlerDelegate;
import com.odeyalo.sonata.connect.service.player.sync.TargetDevices;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class DefaultStorageDeviceOperations implements DeviceOperations {
private final TransferPlaybackCommandHandlerDelegate transferPlaybackCommandHandlerDelegate;
public final class DefaultDeviceOperations implements DeviceOperations {
private final PlayerStateService playerStateService;
private final TransferPlaybackCommandHandlerDelegate transferPlaybackCommandHandlerDelegate;

@Autowired
public DefaultStorageDeviceOperations(PlayerStateService playerStateService,
TransferPlaybackCommandHandlerDelegate transferPlaybackCommandHandlerDelegate) {
public DefaultDeviceOperations(PlayerStateService playerStateService,
TransferPlaybackCommandHandlerDelegate transferPlaybackCommandHandlerDelegate) {
this.playerStateService = playerStateService;
this.transferPlaybackCommandHandlerDelegate = transferPlaybackCommandHandlerDelegate;
}


@NotNull
@Override
public Mono<CurrentPlayerState> addDevice(@NotNull final User user,
@NotNull final Device device) {
public Mono<CurrentPlayerState> connectDevice(@NotNull final User user,
@NotNull final Device device) {
return playerStateService.loadPlayerState(user)
.map(playerState -> playerState.connectDevice(device))
.flatMap(playerStateService::save);
}

@NotNull
@Override
public Mono<Boolean> containsById(User user, String deviceId) {
return Mono.empty();
}

@NotNull
@Override
public Mono<CurrentPlayerState> transferPlayback(User user, SwitchDeviceCommandArgs args, TargetDeactivationDevices deactivationDevices, TargetDevices targetDevices) {
public Mono<CurrentPlayerState> transferPlayback(@NotNull final User user,
@NotNull final SwitchDeviceCommandArgs args,
@NotNull final TargetDeactivationDevices deactivationDevices,
@NotNull final TargetDevices targetDevices) {
return transferPlaybackCommandHandlerDelegate.transferPlayback(user, args, deactivationDevices, targetDevices);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.odeyalo.sonata.connect.service.player;

import com.odeyalo.sonata.connect.model.*;
import com.odeyalo.sonata.connect.service.player.handler.PauseCommandHandlerDelegate;
import com.odeyalo.sonata.connect.service.player.handler.PlayCommandHandlerDelegate;
import com.odeyalo.sonata.connect.service.support.mapper.CurrentPlayerState2CurrentlyPlayingPlayerStateConverter;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
Expand All @@ -15,10 +14,9 @@
import static reactor.core.publisher.Mono.defer;

@Component
@RequiredArgsConstructor
@AllArgsConstructor
public final class DefaultPlayerOperations implements BasicPlayerOperations {
private final PlayCommandHandlerDelegate playCommandHandlerDelegate;
private final PauseCommandHandlerDelegate pauseCommandHandlerDelegate;
private final CurrentPlayerState2CurrentlyPlayingPlayerStateConverter playerStateConverter;
private final PlayerStateService playerStateService;

Expand Down Expand Up @@ -59,7 +57,9 @@ public Mono<CurrentPlayerState> playOrResume(@NotNull final User user,
@Override
@NotNull
public Mono<CurrentPlayerState> pause(@NotNull User user) {
return pauseCommandHandlerDelegate.pause(user);
return playerStateService.loadPlayerState(user)
.map(CurrentPlayerState::pause)
.flatMap(playerStateService::save);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.odeyalo.sonata.connect.model.Device;
import com.odeyalo.sonata.connect.model.Devices;
import com.odeyalo.sonata.connect.model.User;
import com.odeyalo.sonata.connect.service.player.sync.TargetDevices;
import com.odeyalo.sonata.connect.service.TargetDevices;
import org.jetbrains.annotations.NotNull;
import reactor.core.publisher.Mono;

Expand All @@ -14,10 +14,7 @@
public interface DeviceOperations {

@NotNull
Mono<CurrentPlayerState> addDevice(User user, Device device);

@NotNull
Mono<Boolean> containsById(User user, String deviceId);
Mono<CurrentPlayerState> connectDevice(User user, Device device);

/**
* Transfer the playback to given devices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import com.odeyalo.sonata.connect.model.Device;
import com.odeyalo.sonata.connect.model.Devices;
import com.odeyalo.sonata.connect.model.User;
import com.odeyalo.sonata.connect.service.TargetDevices;
import com.odeyalo.sonata.connect.service.player.sync.PlayerSynchronizationManager;
import com.odeyalo.sonata.connect.service.player.sync.TargetDevices;
import com.odeyalo.sonata.connect.service.player.sync.event.DeviceConnectedPlayerEvent;
import com.odeyalo.sonata.connect.service.player.sync.event.DeviceDisconnectedPlayerEvent;
import org.jetbrains.annotations.NotNull;
Expand All @@ -25,8 +25,8 @@ public EventPublisherDeviceOperationsDecorator(DeviceOperations delegate, Player

@NotNull
@Override
public Mono<CurrentPlayerState> addDevice(User user, Device device) {
return delegate.addDevice(user, device)
public Mono<CurrentPlayerState> connectDevice(User user, Device device) {
return delegate.connectDevice(user, device)
.flatMap(state -> synchronizationManager.publishUpdatedState(user,
DeviceConnectedPlayerEvent.builder()
.playerState(state)
Expand All @@ -36,12 +36,6 @@ public Mono<CurrentPlayerState> addDevice(User user, Device device) {

}

@NotNull
@Override
public Mono<Boolean> containsById(User user, String deviceId) {
return delegate.containsById(user, deviceId);
}

@NotNull
@Override
public Mono<CurrentPlayerState> transferPlayback(User user, SwitchDeviceCommandArgs args, TargetDeactivationDevices deactivationDevices, TargetDevices targetDevices) {
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 4ec29ea

Please sign in to comment.