XLS support added
authorVásáry Dániel <vasary@elgekko.net>
Tue, 27 Feb 2024 11:29:13 +0000 (12:29 +0100)
committerVásáry Dániel <vasary@elgekko.net>
Tue, 27 Feb 2024 11:29:13 +0000 (12:29 +0100)
mc-vod-sync/mc-vod-sync-app/src/test/java/hu/user/mcvodsync/AssetImportExportBase.java
mc-vod-sync/mc-vod-sync-service/pom.xml
mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodFastXlsProcessor.java [moved from mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodXlsProcessor.java with 96% similarity]
mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodXlsPOIProcessor.java [new file with mode: 0644]
mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/XlsProcessor.java [new file with mode: 0644]
mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/schedule/ScheduledImport.java

index 43e937358f89e0439e5260f907a62828e0d8dad4..b34b0f19f85cd9ede3a1dc9105e9e382092c37fa 100644 (file)
@@ -18,12 +18,13 @@ import hu.user.mcvodsync.db.repository.PlaylistSyncRepository;
 import hu.user.mcvodsync.service.data.CompositeSummary;
 import hu.user.mcvodsync.service.data.Summary;
 import hu.user.mcvodsync.service.in.AssetImportService;
-import hu.user.mcvodsync.service.in.VodXlsProcessor;
+import hu.user.mcvodsync.service.in.XlsProcessor;
 import hu.user.mcvodsync.service.out.SyncProcessor;
 import hu.user.mcvodsync.service.out.VideoMapper;
 import lombok.extern.log4j.Log4j2;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -41,7 +42,8 @@ import static org.junit.Assert.assertNotNull;
 @Log4j2
 public class AssetImportExportBase {
     @Autowired
-    private VodXlsProcessor vodXlsProcessor;
+    @Qualifier("fastXLSProcessor")
+    private XlsProcessor xlsProcessor;
 
     @Autowired
     private AssetRepository assetRepository;
@@ -173,7 +175,7 @@ public class AssetImportExportBase {
         CompositeSummary summary;
         try {
             Path input = Paths.get(xlsFile);
-            summary = vodXlsProcessor.process(input.getFileName().toString(), Files.readAllBytes(input));
+            summary = xlsProcessor.process(input.getFileName().toString(), Files.readAllBytes(input));
         } catch (IOException e) {
             log.error(e);
             throw new RuntimeException(e);
index b00502b7c82e4496e1bf1243633b04849863a27a..8138e72482f7d3effa40eaaff763eb945528382c 100644 (file)
             <version>0.0.1-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.15.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>5.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>5.2.5</version>
+        </dependency>
     </dependencies>
 
     <build>
similarity index 96%
rename from mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodXlsProcessor.java
rename to mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodFastXlsProcessor.java
index 47309637274568bc846268f63e5fa3a0ef7ec0a0..c5aa8aeef5ae8a3825a73f234b21bed7f573f5f1 100644 (file)
@@ -9,6 +9,7 @@ import org.dhatim.fastexcel.reader.ReadableWorkbook;
 import org.dhatim.fastexcel.reader.Row;
 import org.dhatim.fastexcel.reader.Sheet;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -26,7 +27,8 @@ import java.util.stream.Stream;
 
 @Log4j2
 @Component
-public class VodXlsProcessor {
+@Qualifier("fastXLSProcessor")
+public class VodFastXlsProcessor implements XlsProcessor {
     private List<Cell> headers;
 
     @Autowired
@@ -37,6 +39,7 @@ public class VodXlsProcessor {
 
 
     @Transactional
+    @Override
     public CompositeSummary process(String fileName, byte[] xlsData) {
         CompositeSummary summary = CompositeSummary.builder().started(Instant.now()).build();
         try (InputStream is = new ByteArrayInputStream(xlsData);
diff --git a/mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodXlsPOIProcessor.java b/mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/VodXlsPOIProcessor.java
new file mode 100644 (file)
index 0000000..af9b1ae
--- /dev/null
@@ -0,0 +1,148 @@
+package hu.user.mcvodsync.service.in;
+
+import hu.user.mcvodsync.db.Asset;
+import hu.user.mcvodsync.service.data.CompositeSummary;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+@Log4j2
+@Component
+@Qualifier("poiXLSProcessor")
+public class VodXlsPOIProcessor implements XlsProcessor {
+    private List<Cell> headers;
+
+    @Autowired
+    private AssetMapper assetMapper;
+
+    @Autowired
+    private AssetImportService assetImportService;
+
+
+    @Transactional
+    public CompositeSummary process(String fileName, byte[] xlsData) {
+        CompositeSummary summary = CompositeSummary.builder().started(Instant.now()).build();
+        try (InputStream is = new ByteArrayInputStream(xlsData);
+             Workbook wb = getWorkbook(fileName, is)) {
+            Sheet sheet = wb.getSheetAt(0);
+
+            Iterator<Row> rowIterator = sheet.iterator();
+            while (rowIterator.hasNext()) {
+                Row row = rowIterator.next();
+
+                if (row.getRowNum() == 0) {
+                    assetImportService.prepare(LocalDate.now());
+                    headers = getHeaders(row);
+                } else {
+                    log.info("Processing {}", row.getRowNum());
+                    summary.getVideo().incAll();
+                    processRow(row, summary);
+                }
+
+            }
+            assetImportService.processPlaylists(summary);
+
+        } catch (IOException e) {
+            log.error("Excel file reading error from {}. System message: {}", fileName, e.getMessage());
+        }
+        summary.setFinished(Instant.now());
+        log.info(summary);
+        return summary;
+    }
+
+    private Workbook getWorkbook(String fileName, InputStream is) throws IOException {
+        if (fileName.toUpperCase().endsWith("XLS")) {
+            return new HSSFWorkbook(is);
+        } else {
+            return new XSSFWorkbook(is);
+        }
+    }
+
+    private List<Cell> getHeaders(Row row) {
+        Iterator<Cell> cellIterator = row.cellIterator();
+        Iterable<Cell> iterable = () -> cellIterator;
+        return StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
+    }
+
+    private void processRow(Row row, CompositeSummary summary) {
+        Map<String, String> rowData = new HashMap<>();
+        Iterator<Cell> cellIterator = row.cellIterator();
+        Iterable<Cell> iterable = () -> cellIterator;
+
+        StreamSupport.stream(iterable.spliterator(), false).filter(Objects::nonNull).forEach(c -> {
+            try {
+                String header = headers.get(c.getColumnIndex()).getStringCellValue();
+
+                String data = null;
+                switch (c.getCellType()) {
+                    case NUMERIC:
+                        data = String.valueOf(c.getNumericCellValue());
+                        break;
+                    default:
+                        data = c.getStringCellValue();
+                        break;
+                }
+                rowData.put(header, data);
+            } catch (Exception e) {
+                log.error("Cell error!", e);
+            }
+        });
+
+        Asset asset = null;
+        try {
+            asset = assetMapper.toEntity(rowData);
+            if (isAssetValid(asset)) {
+                assetImportService.processAsset(asset, summary);
+            } else {
+                summary.getVideo().incSkip();
+            }
+            summary.getVideo().incSuccess();
+        } catch (Exception e) {
+            summary.getVideo().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;
+    }
+
+}
diff --git a/mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/XlsProcessor.java b/mc-vod-sync/mc-vod-sync-service/src/main/java/hu/user/mcvodsync/service/in/XlsProcessor.java
new file mode 100644 (file)
index 0000000..151572f
--- /dev/null
@@ -0,0 +1,9 @@
+package hu.user.mcvodsync.service.in;
+
+import hu.user.mcvodsync.service.data.CompositeSummary;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface XlsProcessor {
+    @Transactional
+    CompositeSummary process(String fileName, byte[] xlsData);
+}
index bba8f9e6ead6f53dad93c399019b6df13a3fcfd3..53eca8926c8f4dd668abd3faefaf6d69621df275 100644 (file)
@@ -5,9 +5,10 @@ import hu.user.mcvodsync.db.repository.UploadFileRepository;
 import hu.user.mcvodsync.service.data.CompositeSummary;
 import hu.user.mcvodsync.service.event.ImportCompletedEvent;
 import hu.user.mcvodsync.service.event.ImportStartedEvent;
-import hu.user.mcvodsync.service.in.VodXlsProcessor;
+import hu.user.mcvodsync.service.in.XlsProcessor;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Component;
 
@@ -23,7 +24,8 @@ public class ScheduledImport implements Runnable {
     private UploadFileRepository uploadFileRepository;
 
     @Autowired
-    private VodXlsProcessor vodXlsProcessor;
+    @Qualifier("poiXLSProcessor")
+    private XlsProcessor xlsProcessor;
 
     @Override
     public void run() {
@@ -33,7 +35,7 @@ public class ScheduledImport implements Runnable {
             if (opUploadFile.isPresent()) {
                 applicationEventPublisher.publishEvent(new ImportStartedEvent(this, opUploadFile.get().getName()));
                 log.info("ScheduledImport started from {}", opUploadFile.get().getName());
-                summary = vodXlsProcessor.process(opUploadFile.get().getName(), opUploadFile.get().getFile());
+                summary = xlsProcessor.process(opUploadFile.get().getName(), opUploadFile.get().getFile());
             }
         } catch (Exception e) {
             log.error("ScheduledImport error!", e);