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

[Issue29] 영상 메타데이터 관련 기능 구현 #30

Merged
merged 10 commits into from
Nov 7, 2024
Merged
3 changes: 2 additions & 1 deletion mitube-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.rest-assured:rest-assured:5.3.1'
}

tasks.named('bootBuildImage') {
Expand All @@ -22,4 +23,4 @@ tasks.named('bootBuildImage') {

tasks.named('test') {
useJUnitPlatform()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public WebSecurityCustomizer webSecurityCustomizer() {
"/comments/**",
"/channels/**",
"/home",
"/videofiles/**"
"/videofiles/**",
"/videoMetadata/**"
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.misim.controller;

import com.misim.controller.model.Response.MetadataResponse;
import com.misim.entity.VideoMetadata;
import com.misim.exception.CommonResponse;
import com.misim.service.VideoMetadataService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/videoMetadata")
public class VideoMetadataController {

private final VideoMetadataService videoMetadataService;

public VideoMetadataController(VideoMetadataService videoMetadataService) {
this.videoMetadataService = videoMetadataService;
}

@GetMapping("/{videoMetadataId}")
public CommonResponse<MetadataResponse> getVideoMetadata(@PathVariable Long videoMetadataId) {

VideoMetadata metadata = videoMetadataService.read(videoMetadataId);

MetadataResponse response = new MetadataResponse(metadata.getViewCount(), metadata.getLikeCount(), metadata.getDislikeCount());

return CommonResponse
.<MetadataResponse>builder()
.body(response)
.build();
}

@PostMapping("/{videoMetadataId}/view")
public void addVideoMetadataViewCount(@PathVariable Long videoMetadataId) {

videoMetadataService.updateViewCount(videoMetadataId);
}

@PostMapping("/{videoMetadataId}/like")
public void addVideoMetadataLikeCount(@PathVariable Long videoMetadataId, @RequestParam Boolean isChecked) {

videoMetadataService.updateLikeCount(videoMetadataId, isChecked);
}

@PostMapping("/{videoMetadataId}/dislike")
public void addVideoMetadataDislikeCount(@PathVariable Long videoMetadataId, @RequestParam Boolean isChecked) {

videoMetadataService.updateDislikeCount(videoMetadataId, isChecked);
}

@DeleteMapping("/{videoMetadataId}")
public void deleteVideoMetadata(@PathVariable Long videoMetadataId) {

videoMetadataService.delete(videoMetadataId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.misim.controller.model.Response;

public record MetadataResponse (
Long viewCount, Long likeCount, Long dislikeCount
) {
}
14 changes: 9 additions & 5 deletions mitube-app/src/main/java/com/misim/entity/VideoCatalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -24,16 +24,20 @@ public class VideoCatalog extends BaseTimeEntity {

private String description;

@ManyToOne
private Integer categoryId;

@OneToOne
private VideoFile videoFile;

private Integer categoryId;
@OneToOne
private VideoMetadata videoMetadata;

@Builder
public VideoCatalog(String title, String description, VideoFile videoFile, Integer categoryId) {
public VideoCatalog(String title, String description, Integer categoryId, VideoFile videoFile, VideoMetadata videoMetadata) {
this.title = title;
this.description = description;
this.videoFile = videoFile;
this.categoryId = categoryId;
this.videoFile = videoFile;
this.videoMetadata = videoMetadata;
}
}
56 changes: 56 additions & 0 deletions mitube-app/src/main/java/com/misim/entity/VideoMetadata.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.misim.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor
public class VideoMetadata extends BaseTimeEntity{

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private Long viewCount;

private Long likeCount;

private Long dislikeCount;

@Builder
public VideoMetadata(Long viewCount, Long likeCount, Long dislikeCount) {
this.viewCount = viewCount;
this.likeCount = likeCount;
this.dislikeCount = dislikeCount;
}

public void incrementViewCount() {
this.viewCount++;
}

public void incrementLikeCount() {
this.likeCount++;
}

public void incrementDislikeCount() {
this.dislikeCount++;
}

public void decrementLikeCount() {
if (this.likeCount > 0) {
this.likeCount--;
}
}

public void decrementDislikeCount() {
if (this.dislikeCount > 0) {
this.dislikeCount--;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package com.misim.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@Order(value = 1)
@ExceptionHandler(MitubeException.class)
public ResponseEntity<CommonResponse<?>> handleMitubeException(MitubeException e) {

e.fillInStackTrace();
log.error("Handler MitubeException: {}", e.getMessage(), e);

CommonResponse<?> commonResponse = new CommonResponse<>(e.getErrorCode().getCode(),
e.getErrorCode().getMessage(), null);
Expand All @@ -23,7 +25,7 @@ public ResponseEntity<CommonResponse<?>> handleMitubeException(MitubeException e
@ExceptionHandler(Exception.class)
public ResponseEntity<CommonResponse<?>> handleUnknownException(Exception e) {

e.fillInStackTrace();
log.error("Handler UnknownException: {}", e.getMessage(), e);

CommonResponse<?> commonResponse = new CommonResponse<>(
MitubeErrorCode.UNKNOWN_EXCEPTION.getCode(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.misim.repository;

import com.misim.entity.VideoMetadata;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface VideoMetadataRepository extends JpaRepository<VideoMetadata, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.misim.service;

import com.misim.entity.VideoMetadata;
import com.misim.repository.VideoMetadataRepository;
import java.util.NoSuchElementException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class VideoMetadataService {

private final VideoMetadataRepository videoMetadataRepository;

public VideoMetadata create() {

VideoMetadata metadata = VideoMetadata.builder()
.viewCount(0L)
.likeCount(0L)
.dislikeCount(0L)
.build();

return videoMetadataRepository.save(metadata);
}

public VideoMetadata read(Long id) {

return videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new);
}

public Long readViewCount(Long id) {

return videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new)
.getViewCount();
}

public Long readLikeCount(Long id) {

return videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new)
.getLikeCount();
}

public Long readDislikeCount(Long id) {

return videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new)
.getDislikeCount();
}

public void updateViewCount(Long id) {

VideoMetadata metadata = videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new);

metadata.incrementViewCount();

videoMetadataRepository.save(metadata);
}

public void updateLikeCount(Long id, boolean isChecked) {

VideoMetadata metadata = videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new);

if (isChecked) {
metadata.incrementLikeCount();
} else {
metadata.decrementLikeCount();
}

videoMetadataRepository.save(metadata);
}

public void updateDislikeCount(Long id, boolean isChecked) {

VideoMetadata metadata = videoMetadataRepository.findById(id)
.orElseThrow(NoSuchElementException::new);

if (isChecked) {
metadata.incrementDislikeCount();
} else {
metadata.decrementDislikeCount();
}

videoMetadataRepository.save(metadata);
}

public void delete(Long id) {

videoMetadataRepository.deleteById(id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void testStreamVideo_Success() throws Exception {
// given
Long videoId = 1L;
VideoFile videoFile = new VideoFile("path/to/video.mp4");
VideoCatalog videoCatalog = new VideoCatalog("title", "description", videoFile, 0);
VideoCatalog videoCatalog = new VideoCatalog("title", "description", 0, videoFile, null);
when(videoService.getVideo(videoId)).thenReturn(videoCatalog);

byte[] videoContent = "test video content".getBytes();
Expand All @@ -101,4 +101,4 @@ void testStreamVideo_VideoNotFound() throws Exception {
mockMvc.perform(get("/videofiles/1"))
.andExpect(status().isNotFound());
}
}
}
Loading
Loading