package hu.user.mcvodsync;
+import com.brightcove.cms.client.model.CreateVideoRequestBodyFields;
import com.brightcove.cms.client.model.Playlist;
+import com.brightcove.cms.client.model.Video;
import hu.user.mcvodsync.brightcove.BrightCoveClient;
import lombok.extern.log4j.Log4j2;
import org.junit.Test;
import java.util.List;
-import static org.junit.Assert.assertNotNull;
-
@Log4j2
@RunWith(SpringRunner.class)
@ComponentScan("hu.user.mcvodsync")
@ActiveProfiles("dev")
@TestPropertySource("classpath:application-dev.yaml")
public class BrightCoveClientIT {
+
@Autowired
private BrightCoveClient bcClient;
- @Test
- public void testOAuth() {
- String authToken = bcClient.createToken();
- log.info("Token created {}", authToken);
- assertNotNull(authToken);
- }
@Test
public void testGetPlayLists() {
- String authToken = bcClient.createToken();
try {
- List<Playlist> playLists = bcClient.getPlayLists(authToken, 0, 10);
+ List<Playlist> playLists = bcClient.getPlayLists(0, 10);
playLists.forEach(playList -> {
log.info(playList.getName());
}
}
+ @Test
+ public void testGetVideos() {
+ try {
+ List<Video> videos = bcClient.getVideos(0, 10);
+
+ videos.forEach(video -> {
+ log.info("{} ref: {} {} {}", video.getId(), video.getReferenceId(), video.getName(), video.getState());
+ });
+
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ @Test
+ public void testGetVideoById() {
+ try {
+ Video video = bcClient.getVideoById("6328122715112");
+ log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ @Test
+ public void testGetVideosById() {
+ try {
+ List<Video> videos = bcClient.getVideosById("6328122715112,6339727091112");
+ videos.forEach(video -> {
+ log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ });
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+
+ @Test
+ public void testCreateVideo() {
+ try {
+ CreateVideoRequestBodyFields fields = new CreateVideoRequestBodyFields();
+ fields.setName("TEST video 00001");
+ fields.setReferenceId("MCVODSYNC00001");
+ fields.setState(CreateVideoRequestBodyFields.StateEnum.INACTIVE);
+ fields.setEconomics(CreateVideoRequestBodyFields.EconomicsEnum.FREE);
+ Video video = bcClient.createVideo(fields);
+ log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ @Test
+ public void testGetVideoByRefId() {
+ try {
+ Video video = bcClient.getVideoById("ref:MCVODSYNC00001");
+ log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ @Test
+ public void testDeleteVideo() {
+ try {
+ bcClient.deleteVideo("ref:MCVODSYNC00001");
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+
}
package hu.user.mcvodsync;
+import hu.user.mcvodsync.db.repository.AssetRepository;
+import hu.user.mcvodsync.service.xls.ImportSummary;
import hu.user.mcvodsync.service.xls.VodXlsProcessor;
import lombok.extern.log4j.Log4j2;
import org.junit.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
@Log4j2
@TestPropertySource("classpath:application-dev.yaml")
public class VodXlsProcessorIT {
@Autowired
- VodXlsProcessor vodXlsProcessor;
+ private VodXlsProcessor vodXlsProcessor;
+
+ @Autowired
+ private AssetRepository assetRepository;
+
+ @Test
+ public void queryPlayLists() {
+ List<String> playlists = assetRepository.queryDistinctPlaylists();
+ assertNotNull(playlists);
+
+ List<String> assets = assetRepository.queryPlaylistsAssets(playlists.get(0));
+ assertNotNull(assets);
+ }
@Test
public void processXLS() throws IOException {
- Path xlsFile = Paths.get("src/test/resources/AMC_Selekt_jogositott_tartalmak_20230906.xlsx");
- vodXlsProcessor.process(xlsFile.getFileName().toString(), Files.readAllBytes(xlsFile));
+ Path xlsFile = Paths.get("src/test/resources/testdata.xlsx");
+ ImportSummary process = vodXlsProcessor.process(xlsFile.getFileName().toString(), Files.readAllBytes(xlsFile));
+ assertEquals(process.getAll(), process.getSuccess());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
- <component name="AdditionalModuleElements">
- <content url="file://$MODULE_DIR$" dumb="true">
- <sourceFolder url="file://$MODULE_DIR$/generated" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/main/generated" isTestSource="false" generated="true" />
- </content>
+ <component name="SonarLintModuleSettings">
+ <option name="uniqueId" value="55ebe799-fcdc-47c7-96d3-ffde0937b72e" />
</component>
</module>
\ No newline at end of file
package hu.user.mcvodsync.brightcove;
import com.brightcove.cms.client.api.PlaylistsApi;
+import com.brightcove.cms.client.api.VideosApi;
+import com.brightcove.cms.client.model.CreateVideoRequestBodyFields;
import com.brightcove.cms.client.model.Playlist;
+import com.brightcove.cms.client.model.Video;
import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.URLConnectionClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
import org.springframework.stereotype.Service;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@Log4j2
@Service
public class BrightCoveClient {
+ private String authToken;
+ public static final String BEARER = "Bearer ";
private final PlaylistsApi playListApi = new PlaylistsApi();
+ private final VideosApi videosApi = new VideosApi();
+
@Autowired
private ApiProperties apiProperties;
return token;
}
+ private String getToken() {
+ if (StringUtils.isBlank(authToken)) {
+ authToken = BEARER + createToken();
+ }
+ return authToken;
+ }
- public List<Playlist> getPlayLists(String authToken, int offset, int limit) throws RestClientException {
+ public List<Playlist> getPlayLists(int offset, int limit) throws RestClientException {
String q = null;
String sort = null;
- return playListApi.getPlaylists(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE,
- "Bearer " + authToken, limit, offset, q, sort);
+ return playListApi.getPlaylists(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), limit, offset, q, sort);
}
+
+ public List<Video> getVideos(int offset, int limit) throws RestClientException {
+ String sort = null;
+ String query = null;
+ return videosApi.getVideos(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE,
+ getToken(), limit, offset, sort, query);
+ }
+
+ public Video getVideoById(String id) throws RestClientException {
+ return videosApi.getVideoByIdOrReferenceId(apiProperties.getAccountId(), "/" + id, MediaType.APPLICATION_JSON_VALUE,
+ getToken(), true);
+ }
+
+ public List<Video> getVideosById(String id) throws RestClientException {
+ return getVideoByIdOrReferenceIdWithHttpInfo(apiProperties.getAccountId(), "/" + id, MediaType.APPLICATION_JSON_VALUE,
+ getToken(), true).getBody();
+ }
+
+
+ public Video createVideo(CreateVideoRequestBodyFields fields) {
+ return videosApi.createVideo(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), fields);
+ }
+
+ public void deleteVideo(String id) {
+ videosApi.deleteVideo(apiProperties.getAccountId(), "/" + id, MediaType.APPLICATION_JSON_VALUE, getToken());
+ }
+
+ private ResponseEntity<List<Video>> getVideoByIdOrReferenceIdWithHttpInfo(String accountId, String videoIds, String contentType, String authorization, Boolean includeVariants) throws RestClientException {
+ Object postBody = null;
+
+ // verify the required parameter 'accountId' is set
+ if (accountId == null) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'accountId' when calling getVideoByIdOrReferenceId");
+ }
+
+ // verify the required parameter 'videoIds' is set
+ if (videoIds == null) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'videoIds' when calling getVideoByIdOrReferenceId");
+ }
+
+ // verify the required parameter 'contentType' is set
+ if (contentType == null) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'contentType' when calling getVideoByIdOrReferenceId");
+ }
+
+ // verify the required parameter 'authorization' is set
+ if (authorization == null) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'authorization' when calling getVideoByIdOrReferenceId");
+ }
+
+ // create path and map variables
+ final Map<String, Object> uriVariables = new HashMap<String, Object>();
+ uriVariables.put("account_id", accountId);
+ uriVariables.put("video_ids", videoIds);
+
+ final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
+ final HttpHeaders headerParams = new HttpHeaders();
+ final MultiValueMap<String, String> cookieParams = new LinkedMultiValueMap<String, String>();
+ final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
+
+ queryParams.putAll(videosApi.getApiClient().parameterToMultiValueMap(null, "include_variants", includeVariants));
+
+ if (contentType != null)
+ headerParams.add("Content-Type", videosApi.getApiClient().parameterToString(contentType));
+ if (authorization != null)
+ headerParams.add("Authorization", videosApi.getApiClient().parameterToString(authorization));
+
+ final String[] localVarAccepts = {
+ "application/json"
+ };
+ final List<MediaType> localVarAccept = videosApi.getApiClient().selectHeaderAccept(localVarAccepts);
+ final String[] contentTypes = {};
+ final MediaType localVarContentType = videosApi.getApiClient().selectHeaderContentType(contentTypes);
+
+ String[] authNames = new String[]{"BC_OAuth2"};
+
+ ParameterizedTypeReference<List<Video>> returnType = new ParameterizedTypeReference<List<Video>>() {
+ };
+ return videosApi.getApiClient().invokeAPI("/v1/accounts/{account_id}/videos{video_ids}", HttpMethod.GET, uriVariables, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, authNames, returnType);
+ }
+
}
-- // Create system tables
-- Migration SQL that makes the change goes here.
-CREATE TABLE ASSOCIATE (
+CREATE TABLE associate (
id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
name VARCHAR(255),
login VARCHAR(255),
CONSTRAINT pk_associate PRIMARY KEY (id)
);
-INSERT INTO ASSOCIATE
+INSERT INTO associate
(name, login, password, active)
VALUES
('Test User', 'user', 'password', 1);
-- //@UNDO
-- SQL to undo the change goes here.
-DROP TABLE ASSOCIATE;
+DROP TABLE associate;
-- // Create business tables
-- Migration SQL that makes the change goes here.
-CREATE TABLE UPLOAD_FILE (
+CREATE TABLE upload_file (
id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
created TIMESTAMP,
name VARCHAR(255),
CONSTRAINT pk_uploadfile PRIMARY KEY (id)
);
-CREATE TABLE ASSET (
- episode_id VARCHAR(20) NOT NULL,
+CREATE TABLE asset (
+ catalog_id VARCHAR(20) NOT NULL,
season_id BIGINT NOT NULL,
series_id BIGINT NOT NULL,
- hub_info VARCHAR(255) NOT NULL,
- episode_title VARCHAR(255) NOT NULL,
- season_title VARCHAR(255),
- series_title VARCHAR(255),
+ sunset DATE NOT NULL,
+ sunrise DATE NOT NULL,
+ playlist VARCHAR(100) NOT NULL,
+ hub_info VARCHAR(100),
+ prog_local_title VARCHAR(255) NOT NULL,
+ season_local_title VARCHAR(255),
+ series_local_title VARCHAR(255),
season_nr INTEGER,
episode_nr INTEGER,
production_year INTEGER,
country VARCHAR(1000),
+ orig_language VARCHAR(20),
+ content_type VARCHAR(50),
+ content_source VARCHAR(50),
age_rating VARCHAR(10),
- CONSTRAINT pk_asset PRIMARY KEY (episode_id, season_id, series_id)
+ CONSTRAINT pk_catalog_id PRIMARY KEY (catalog_id)
);
+CREATE INDEX idx_asset_playlist ON asset(playlist);
-CREATE TABLE ASSET_SYNC (
- execution_id VARCHAR(36) NOT NULL,
- episode_id VARCHAR(20) NOT NULL,
- season_id BIGINT NOT NULL,
- series_id BIGINT NOT NULL,
+CREATE TABLE asset_sync (
+ id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ catalog_id VARCHAR(20) NOT NULL,
+ imported TIMESTAMP NOT NULL,
+ sync_type VARCHAR(6) NOT NULL,
+ exported_success TIMESTAMP,
+ exported_error TIMESTAMP,
+ CONSTRAINT pk_asset_sync PRIMARY KEY (id)
+);
+CREATE INDEX idx_asset_sync_exported_success ON asset_sync(exported_success);
+
+CREATE TABLE playlist_sync (
+ id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ playlist VARCHAR(100) NOT NULL,
+ imported TIMESTAMP NOT NULL,
sync_type VARCHAR(6) NOT NULL,
- completed TIMESTAMP,
- CONSTRAINT pk_asset_sync PRIMARY KEY (episode_id, season_id, series_id)
+ exported_success TIMESTAMP,
+ exported_error TIMESTAMP,
+ CONSTRAINT pk_playlist_sync PRIMARY KEY (id)
);
+CREATE INDEX idx_playlist_sync_exported_success ON asset_sync(exported_success);
+
-- //@UNDO
-- SQL to undo the change goes here.
-DROP TABLE ASSET;
-DROP TABLE ASSET_SYNC;
-DROP TABLE UPLOAD_FILE;
+DROP TABLE asset;
+DROP TABLE asset_sync;
+DROP TABLE playlist_sync;
+DROP TABLE upload_file;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
-import javax.persistence.IdClass;
import java.io.Serializable;
+import java.sql.Date;
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
-@IdClass(AssetId.class)
public class Asset implements Serializable {
@Id
- private String episodeId;
+ private String catalogId;
- @Id
private Long seasonId;
- @Id
private Long seriesId;
-
@Column(nullable = false)
- private String hubInfo;
-
+ private Date sunset;
@Column(nullable = false)
- private String episodeTitle;
+ private Date sunrise;
+ @Column(nullable = false)
+ private String playlist;
- private String seasonTitle;
+ private String hubInfo;
+ @Column(nullable = false)
+ private String progLocalTitle;
- private String seriesTitle;
+ private String seasonLocalTitle;
+ private String seriesLocalTitle;
private Integer seasonNr;
-
private Integer episodeNr;
-
private Integer productionYear;
-
private String country;
+ private String origLanguage;
+
+ private String contentType;
+
+ private String contentSource;
private String ageRating;
}
+++ /dev/null
-package hu.user.mcvodsync.db;
-
-import lombok.*;
-
-import javax.persistence.Column;
-import java.io.Serializable;
-
-@Getter
-@Setter
-@Builder
-@ToString
-@NoArgsConstructor
-@AllArgsConstructor
-public class AssetId implements Serializable {
-
- @Column(nullable = false)
- private String episodeId;
-
- @Column(nullable = false)
- private Long seasonId;
-
- @Column(nullable = false)
- private Long seriesId;
-
-}
@ToString
@NoArgsConstructor
@AllArgsConstructor
-@IdClass(AssetId.class)
public class AssetSync implements Serializable {
-
- @Column(nullable = false)
- private String executionId;
-
@Id
- private String episodeId;
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ Long id;
- @Id
- private Long seasonId;
+ private String catalogId;
- @Id
- private Long seriesId;
+ @Column(nullable = false)
+ private Date imported;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private SyncType syncType;
- private Date completed;
+ private Date exportedSuccess;
+
+ private Date exportedError;
}
package hu.user.mcvodsync.db.repository;
import hu.user.mcvodsync.db.Asset;
-import hu.user.mcvodsync.db.AssetId;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+public interface AssetRepository extends JpaRepository<Asset, String> {
+
+ @Query("SELECT DISTINCT(a.playlist) FROM Asset a ORDER BY a.playlist")
+ List<String> queryDistinctPlaylists();
+
+ @Query("SELECT a.catalogId FROM Asset a WHERE a.playlist = :playlist ORDER BY a.seasonNr, a.episodeNr")
+ List<String> queryPlaylistsAssets(String playlist);
-public interface AssetRepository extends JpaRepository<Asset, AssetId> {
}
package hu.user.mcvodsync.db.repository;
-import hu.user.mcvodsync.db.AssetId;
import hu.user.mcvodsync.db.AssetSync;
import org.springframework.data.jpa.repository.JpaRepository;
-public interface AssetSyncRepository extends JpaRepository<AssetSync, AssetId> {
+public interface AssetSyncRepository extends JpaRepository<AssetSync, String> {
}
<artifactId>fastexcel-reader</artifactId>
<version>0.15.7</version>
</dependency>
+ <dependency>
+ <groupId>org.threeten</groupId>
+ <artifactId>threetenbp</artifactId>
+ <version>1.4.0</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
@Service
public class TaskSchedules {
- @Scheduled(fixedDelay = 5000)
+ @Scheduled(fixedDelay = 50000)
public void scheduleFixedDelayTask() {
- System.out.println(
- "Fixed delay task - " + System.currentTimeMillis() / 1000);
+// System.out.println(
+// "Fixed delay task - " + System.currentTimeMillis() / 1000);
}
}
import hu.user.mcvodsync.db.Asset;
-import hu.user.mcvodsync.db.AssetId;
import hu.user.mcvodsync.db.AssetSync;
import hu.user.mcvodsync.db.SyncType;
import hu.user.mcvodsync.db.repository.AssetRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import java.util.Objects;
-import java.util.Optional;
+import java.time.Instant;
+import java.util.*;
@Log4j2
@Service
public class AssetImportService {
@Autowired
- AssetRepository assetRepository;
+ private AssetRepository assetRepository;
@Autowired
- AssetSyncRepository assetSyncRepository;
+ private AssetSyncRepository assetSyncRepository;
@Autowired
- EntityDataService<Asset> entityDataService;
+ private EntityDataService<Asset> entityDataService;
+
+ private Map<String, List<String>> currentPlaylists;
+
+ public void prepare() {
+ currentPlaylists = getPlayLists();
+ }
+
+ private Map<String, List<String>> getPlayLists() {
+ Map<String, List<String>> result = new HashMap<>();
+ List<String> playlistNames = assetRepository.queryDistinctPlaylists();
+ playlistNames.forEach(playlist -> {
+ List<String> playlistsAssets = assetRepository.queryPlaylistsAssets(playlist);
+ result.put(playlist, playlistsAssets);
+ });
+ return result;
+ }
@Transactional
- public void processAsset(String executionId, Asset asset) {
- AssetId assetId = AssetId.builder()
- .episodeId(asset.getEpisodeId())
- .seasonId(asset.getSeasonId())
- .seriesId(asset.getSeriesId())
- .build();
- Optional<Asset> optionalEntity = assetRepository.findById(assetId);
+ public void processAsset(Asset asset, ImportSummary summary) {
+ Optional<Asset> optionalEntity = assetRepository.findById(asset.getCatalogId());
AssetSync assetSync = AssetSync.builder()
- .executionId(executionId)
- .episodeId(asset.getEpisodeId())
- .seasonId(asset.getSeasonId())
- .seriesId(asset.getSeriesId())
+ .imported(Date.from(Instant.now()))
+ .catalogId(asset.getCatalogId())
+ .syncType(SyncType.INSERT)
.build();
if (optionalEntity.isPresent()) {
boolean areDifferent = entityDataService.areDifferent(asset, optionalEntity.get());
if (areDifferent) {
-// log.info("History UPDATE registered for {}", assetId);
assetSync.setSyncType(SyncType.UPDATE);
}
- } else {
-// log.info("History INSERT registered for {}", assetId);
- assetSync.setSyncType(SyncType.INSERT);
}
- if (Objects.nonNull(assetSync.getSyncType())) {
- assetSyncRepository.save(assetSync);
+ assetRepository.saveAndFlush(asset);
+ assetSyncRepository.saveAndFlush(assetSync);
+
+ if (assetSync.getSyncType() == SyncType.UPDATE) {
+ summary.incUpdated();
+ }
+ if (assetSync.getSyncType() == SyncType.INSERT) {
+ summary.incInserted();
}
- assetRepository.save(asset);
}
+ public void finish() {
+ Map<String, List<String>> newPlaylists = getPlayLists();
+
+ //CollectionUtils.isEqualCollection(Collection<?> a, Collection<?> b)
+ }
}
package hu.user.mcvodsync.service.xls;
import hu.user.mcvodsync.db.Asset;
+import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
+import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
+import java.sql.Date;
+import java.text.SimpleDateFormat;
import java.util.Map;
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface AssetMapper {
- @Mapping(target = "episodeId", source = "CATALOG_ID")
- @Mapping(target = "seasonId", source = "SEASON_CATALOG_ID")
- @Mapping(target = "seriesId", source = "SERIES_GROUP_CATALOG_ID")
+ SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
+
+ @Mapping(target = "catalogId", source = "CATALOG_ID")
+ @Mapping(target = "seasonId", source = "SEASON_CATALOG_ID", qualifiedByName = "mapNullableNumber")
+ @Mapping(target = "seriesId", source = "SERIES_GROUP_CATALOG_ID", qualifiedByName = "mapNullableNumber")
+ @Mapping(target = "sunset", source = "Sunset Date", qualifiedByName = "mapSunset")
+ @Mapping(target = "sunrise", source = "Sunrise Date", qualifiedByName = "mapSunrise")
+ @Mapping(target = "playlist", source = "PLAYLIST_NAME")
@Mapping(target = "hubInfo", source = "HUB_INFO")
- @Mapping(target = "episodeTitle", source = "PROG_ORIG_TITLE")
- @Mapping(target = "seasonTitle", source = "SEASON_ORIG_TITLE")
- @Mapping(target = "seriesTitle", source = "SER_GROUP_ORIG_TITLE")
- @Mapping(target = "seasonNr", source = "SEASON_NUMBER")
- @Mapping(target = "episodeNr", source = "EPISODE_NR")
- @Mapping(target = "ageRating", source = "AGE_RATING")
+ @Mapping(target = "progLocalTitle", source = "PROG_LOCAL_TITLE")
+ @Mapping(target = "seasonLocalTitle", source = "SEASON_LOCAL_TITLE")
+ @Mapping(target = "seriesLocalTitle", source = "SERIES_GROUP_LOCAL_TITLE")
+ @Mapping(target = "seasonNr", source = "SEASON_NUMBER", qualifiedByName = "mapNullableNumber")
+ @Mapping(target = "episodeNr", source = "EPISODE_NR", qualifiedByName = "mapNullableNumber")
+ @Mapping(target = "productionYear", source = "PRODUCTION_YEAR", qualifiedByName = "mapNullableNumber")
@Mapping(target = "country", source = "COUNTRY_OF_ORIGIN")
- @Mapping(target = "productionYear", source = "PRODUCTION_YEAR")
+ @Mapping(target = "origLanguage", source = "ORIGINAL_LANGUAGE")
+ @Mapping(target = "contentType", source = "CONTENT_TYPE")
+ @Mapping(target = "contentSource", source = "CONTENT_SOURCE")
+ @Mapping(target = "ageRating", source = "AGE_RATING")
Asset toEntity(Map<String, String> xlsRowData);
+ @Named("mapNullableNumber")
+ static long mapNullableNumber(String numberValue) {
+ long result = 0;
+ try {
+ if (StringUtils.isNotBlank(numberValue)) {
+ result = Long.parseLong(numberValue);
+ }
+ } catch (Exception ignored) {
+ }
+ return result;
+ }
+
+
+ @Named("mapSunrise")
+ static Date mapSunrise(String numberValue) {
+ long longValue = 0;
+ try {
+ longValue = Long.parseLong(numberValue);
+ } catch (Exception ignored) {
+ }
+ long javaDateValue = (longValue - 25569) * 86400 * 1000;
+ return new Date(javaDateValue);
+ }
+
+ @Named("mapSunset")
+ static Date mapSunset(String dateValue) {
+ Date result = null;
+ try {
+ if (StringUtils.isNotBlank(dateValue)) {
+ result = new Date(formatter.parse(dateValue).getTime());
+ }
+ } catch (Exception ignored) {
+ }
+ return result;
+ }
}
import hu.user.mcvodsync.db.Asset;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.time.DurationFormatUtils;
import org.dhatim.fastexcel.reader.Cell;
import org.dhatim.fastexcel.reader.ReadableWorkbook;
import org.dhatim.fastexcel.reader.Row;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.time.Duration;
import java.time.Instant;
-import java.util.*;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Log4j2
@Service
public class VodXlsProcessor {
- private final List<String> mappings = Collections.emptyList();
private List<Cell> headers;
@Autowired
- AssetMapper assetMapper;
+ private AssetMapper assetMapper;
@Autowired
- AssetImportService assetImportService;
+ private AssetImportService assetImportService;
- public void process(String fileName, byte[] xlsData) {
- Instant start = Instant.now();
- String executionId = UUID.randomUUID().toString();
+ public ImportSummary process(String fileName, byte[] xlsData) {
+ ImportSummary summary = ImportSummary.builder().started(Instant.now()).build();
try (InputStream is = new ByteArrayInputStream(xlsData);
ReadableWorkbook wb = new ReadableWorkbook(is)) {
Sheet sheet = wb.getFirstSheet();
-
try (Stream<Row> rows = sheet.openStream()) {
rows.forEach(row -> {
if (row.getRowNum() == 1) {
+ assetImportService.prepare();
headers = getHeaders(row);
} else {
- processRow(executionId, row);
+ summary.incAll();
+ processRow(row, summary);
}
});
}
+ assetImportService.finish();
+
} catch (IOException e) {
log.error("Excel file reading error from {}. System message: {}", fileName, e.getMessage());
}
- Duration executionDuration = Duration.between(start, Instant.now());
- String duration = DurationFormatUtils.formatDuration(executionDuration.toMillis(), "H:mm:ss", true);
- log.info("Processing took {}", duration);
+ summary.setFinished(Instant.now());
+ log.info(summary);
+ return summary;
}
private List<Cell> getHeaders(Row row) {
return row.stream().collect(Collectors.toList());
}
- private void processRow(String executionId, Row r) {
+ private void processRow(Row r, ImportSummary summary) {
Map<String, String> rowData = new HashMap<>();
r.stream().filter(Objects::nonNull).forEach(c -> {
try {
+ String header = headers.get(c.getColumnIndex()).getRawValue();
String data = c.getRawValue();
- rowData.put(headers.get(c.getColumnIndex()).getRawValue(), data);
+ rowData.put(header, data);
} catch (Exception e) {
log.error("Cell error!", e);
}
});
- Asset asset = assetMapper.toEntity(rowData);
- if (Objects.isNull(asset.getSeasonId())) {
- asset.setSeasonId(0L);
- }
- if (Objects.isNull(asset.getSeriesId())) {
- asset.setSeriesId(0L);
- }
- if (StringUtils.isBlank(asset.getHubInfo()) || StringUtils.isBlank(asset.getEpisodeTitle())) {
- //log.error("Hub not defined for {}", asset);
- } else {
- try {
- assetImportService.processAsset(executionId, asset);
- } catch (Exception e) {
- log.error("Processing error for {}", asset);
+ Asset asset = null;
+ try {
+ asset = assetMapper.toEntity(rowData);
+ if (isAssetValid(asset)) {
+ assetImportService.processAsset(asset, summary);
}
+ summary.incSuccess();
+ } catch (Exception e) {
+ summary.incError();
+ log.error("Processing error for {}", asset, e);
+ }
+ }
+
+ private boolean isAssetValid(Asset asset) {
+ if (StringUtils.isBlank(asset.getCatalogId())) {
+ log.warn("Catalog ID not defined for {}", asset);
+ return false;
+ }
+ if (StringUtils.isBlank(asset.getPlaylist())) {
+ log.warn("Playlist not defined for {}", asset);
+ return false;
+ }
+ if (StringUtils.isBlank(asset.getProgLocalTitle())) {
+ log.warn("Prog local title not defined for {}", asset);
+ return false;
+ }
+ if (Objects.isNull(asset.getSunset())) {
+ log.warn("Sunset not defined for {}", asset);
+ return false;
+ }
+ if (Objects.isNull(asset.getSunrise())) {
+ log.warn("Sunrise not defined for {}", asset);
+ return false;
}
+ return true;
}
}