Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTOR] Refactoring of operations with devices #75

Merged
merged 11 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading