Browse Source

first commit

placidenduwayo 1 year ago
parent
commit
90aa9a6711

+ 5
- 30
src/main/java/fr/natan/akkastreamfileprocessingapi/controller/TvSeriesController.java View File

13
 import org.springframework.web.bind.annotation.RestController;
13
 import org.springframework.web.bind.annotation.RestController;
14
 import play.api.libs.json.JsValue;
14
 import play.api.libs.json.JsValue;
15
 import play.api.libs.json.Json;
15
 import play.api.libs.json.Json;
16
-import scala.Option;
17
 import scala.collection.IndexedSeq;
16
 import scala.collection.IndexedSeq;
18
 import scala.concurrent.Future;
17
 import scala.concurrent.Future;
19
 
18
 
20
 import java.util.ArrayList;
19
 import java.util.ArrayList;
21
 import java.util.List;
20
 import java.util.List;
22
-import java.util.Random;
23
 import java.util.concurrent.CompletableFuture;
21
 import java.util.concurrent.CompletableFuture;
24
 import java.util.concurrent.ExecutionException;
22
 import java.util.concurrent.ExecutionException;
25
 
23
 
30
 
28
 
31
     private final AkkaStreamFileProcessingFuture akkaStreamFilesProcessing;
29
     private final AkkaStreamFileProcessingFuture akkaStreamFilesProcessing;
32
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
30
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
33
-    private static final int BORN_INF = 100, BORN_SUP = 2000;
34
 
31
 
35
     public TvSeriesController(AkkaStreamFileProcessingFuture akkaStreamFilesProcessing) {
32
     public TvSeriesController(AkkaStreamFileProcessingFuture akkaStreamFilesProcessing) {
36
         this.akkaStreamFilesProcessing = akkaStreamFilesProcessing;
33
         this.akkaStreamFilesProcessing = akkaStreamFilesProcessing;
38
 
35
 
39
     @RequestMapping(value = "/persons/id/{personID}", method = RequestMethod.GET)
36
     @RequestMapping(value = "/persons/id/{personID}", method = RequestMethod.GET)
40
     private String getPersonByID(@PathVariable(name = "personID") String personID) throws ExecutionException, InterruptedException {
37
     private String getPersonByID(@PathVariable(name = "personID") String personID) throws ExecutionException, InterruptedException {
41
-        Future<Option<ModelsAndJsonMap.Person>> futurePerson = akkaStreamFilesProcessing.getPersonByIdFuture(personID);
38
+        Future<ModelsAndJsonMap.Person> futurePerson = akkaStreamFilesProcessing.getPersonByIdFuture(personID);
42
         CompletableFuture<ModelsAndJsonMap.Person> completableFuture = CompletableFutureBuilder
39
         CompletableFuture<ModelsAndJsonMap.Person> completableFuture = CompletableFutureBuilder
43
                 .buildcompletableFuture1(futurePerson);
40
                 .buildcompletableFuture1(futurePerson);
44
-        while (!completableFuture.isDone()) {
45
-            logger.info("IS PROCESSING...");
46
-            Thread.sleep(new Random().nextInt(BORN_SUP-BORN_INF)+BORN_INF);
47
-        }
48
         ModelsAndJsonMap.Person person = completableFuture.get();
41
         ModelsAndJsonMap.Person person = completableFuture.get();
49
 
42
 
50
         JsValue personJs = Json.toJson(person, person.personJsonFormatter());
43
         JsValue personJs = Json.toJson(person, person.personJsonFormatter());
55
     private String getPersonByName(@PathVariable(name = "primaryName") String primaryName)
48
     private String getPersonByName(@PathVariable(name = "primaryName") String primaryName)
56
             throws ExecutionException, InterruptedException {
49
             throws ExecutionException, InterruptedException {
57
 
50
 
58
-        Future<Option<ModelsAndJsonMap.Person>> personFuture = akkaStreamFilesProcessing.getPersonByNameFuture(primaryName);
51
+        Future<ModelsAndJsonMap.Person> personFuture = akkaStreamFilesProcessing.getPersonByNameFuture(primaryName);
59
         CompletableFuture<ModelsAndJsonMap.Person> personCompletableFuture = CompletableFutureBuilder
52
         CompletableFuture<ModelsAndJsonMap.Person> personCompletableFuture = CompletableFutureBuilder
60
                 .buildcompletableFuture1(personFuture);
53
                 .buildcompletableFuture1(personFuture);
61
-        while (!personCompletableFuture.isDone()) {
62
-            logger.info("IS PROCESSING...");
63
-            Thread.sleep(new Random().nextInt(BORN_SUP-BORN_INF)+BORN_INF);
64
-        }
65
         ModelsAndJsonMap.Person person = personCompletableFuture.get();
54
         ModelsAndJsonMap.Person person = personCompletableFuture.get();
66
         JsValue personJs = Json.toJson(person, person.personJsonFormatter());
55
         JsValue personJs = Json.toJson(person, person.personJsonFormatter());
67
         return Json.prettyPrint(personJs);
56
         return Json.prettyPrint(personJs);
70
     @RequestMapping(value = "/tvseries/id/{tvSerieId}", method = RequestMethod.GET)
59
     @RequestMapping(value = "/tvseries/id/{tvSerieId}", method = RequestMethod.GET)
71
     private String getTvSerieByID(@PathVariable(name = "tvSerieId") String tvSerieID)
60
     private String getTvSerieByID(@PathVariable(name = "tvSerieId") String tvSerieID)
72
             throws ExecutionException, InterruptedException {
61
             throws ExecutionException, InterruptedException {
73
-        Future<Option<ModelsAndJsonMap.TvSerie>> tvSerieFuture = akkaStreamFilesProcessing.getTvSerieByIdFuture(tvSerieID);
62
+        Future<ModelsAndJsonMap.TvSerie> tvSerieFuture = akkaStreamFilesProcessing.getTvSerieByIdFuture(tvSerieID);
74
         CompletableFuture<ModelsAndJsonMap.TvSerie> tvSerieCompletableFuture = CompletableFutureBuilder
63
         CompletableFuture<ModelsAndJsonMap.TvSerie> tvSerieCompletableFuture = CompletableFutureBuilder
75
                 .buildcompletableFuture1(tvSerieFuture);
64
                 .buildcompletableFuture1(tvSerieFuture);
76
-        while (!tvSerieCompletableFuture.isDone()) {
77
-            logger.info("IS PROCESSING...");
78
-            Thread.sleep(new Random().nextInt(BORN_SUP-BORN_INF)+BORN_INF);
79
-        }
65
+
80
         ModelsAndJsonMap.TvSerie tvSerie = tvSerieCompletableFuture.get();
66
         ModelsAndJsonMap.TvSerie tvSerie = tvSerieCompletableFuture.get();
81
         JsValue tvSerieJs = Json.toJson(tvSerie, tvSerie.tvSerieJsonFormatter());
67
         JsValue tvSerieJs = Json.toJson(tvSerie, tvSerie.tvSerieJsonFormatter());
82
         return Json.prettyPrint(tvSerieJs);
68
         return Json.prettyPrint(tvSerieJs);
90
                 .getTvSeriesByPrimaryTitleFuture(tvseriePrimaryTitle);
76
                 .getTvSeriesByPrimaryTitleFuture(tvseriePrimaryTitle);
91
         CompletableFuture<IndexedSeq<ModelsAndJsonMap.TvSerie>> completableFuture =
77
         CompletableFuture<IndexedSeq<ModelsAndJsonMap.TvSerie>> completableFuture =
92
                 CompletableFutureBuilder.buildcompletableFuture2(listFuture);
78
                 CompletableFutureBuilder.buildcompletableFuture2(listFuture);
93
-        while (!completableFuture.isDone()) {
94
-            logger.info("IS PROCESSING...");
95
-            Thread.sleep(new Random().nextInt(BORN_SUP-BORN_INF)+BORN_INF);
96
-        }
79
+
97
         IndexedSeq<ModelsAndJsonMap.TvSerie> tvSerieList = completableFuture.get();
80
         IndexedSeq<ModelsAndJsonMap.TvSerie> tvSerieList = completableFuture.get();
98
         List<String> tvSeries = new ArrayList<>();
81
         List<String> tvSeries = new ArrayList<>();
99
         tvSerieList.foreach(tvSerie -> {
82
         tvSerieList.foreach(tvSerie -> {
113
                 .getPersonsForTvSerieByTvSerieTitleFuture(tvSerieTitle);
96
                 .getPersonsForTvSerieByTvSerieTitleFuture(tvSerieTitle);
114
         CompletableFuture<IndexedSeq<ModelsAndJsonMap.Person>> completableFuture = CompletableFutureBuilder
97
         CompletableFuture<IndexedSeq<ModelsAndJsonMap.Person>> completableFuture = CompletableFutureBuilder
115
                 .buildcompletableFuture2(futurePersonSeq);
98
                 .buildcompletableFuture2(futurePersonSeq);
116
-        while (!completableFuture.isDone()){
117
-            logger.info("IS PROCESSING...");
118
-            Thread.sleep(new Random().nextInt(BORN_SUP-BORN_INF)+BORN_INF);
119
-        }
120
 
99
 
121
         IndexedSeq<ModelsAndJsonMap.Person> personIndexedSeq = completableFuture.get();
100
         IndexedSeq<ModelsAndJsonMap.Person> personIndexedSeq = completableFuture.get();
122
         List<String> personList = new ArrayList<>();
101
         List<String> personList = new ArrayList<>();
138
         CompletableFuture<IndexedSeq<ModelsAndJsonMap.Person>> seqCompletableFuture = CompletableFutureBuilder
117
         CompletableFuture<IndexedSeq<ModelsAndJsonMap.Person>> seqCompletableFuture = CompletableFutureBuilder
139
                 .buildcompletableFuture2(futureIndexedSeqPersons);
118
                 .buildcompletableFuture2(futureIndexedSeqPersons);
140
 
119
 
141
-        while (!seqCompletableFuture.isDone()){
142
-            logger.info("IS PROCESSING...");
143
-            Thread.sleep(new Random().nextInt(BORN_SUP-BORN_INF)+BORN_INF);
144
-        }
145
         IndexedSeq<ModelsAndJsonMap.Person> personIndexedSeq = seqCompletableFuture.get();
120
         IndexedSeq<ModelsAndJsonMap.Person> personIndexedSeq = seqCompletableFuture.get();
146
         List<String> personsList = new ArrayList<>();
121
         List<String> personsList = new ArrayList<>();
147
         personIndexedSeq.foreach(person ->{
122
         personIndexedSeq.foreach(person ->{

+ 4
- 3
src/main/java/fr/natan/akkastreamfileprocessingapi/exceptionshandler/BusinessExceptionHandler.java View File

1
 package fr.natan.akkastreamfileprocessingapi.exceptionshandler;
1
 package fr.natan.akkastreamfileprocessingapi.exceptionshandler;
2
 
2
 
3
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException;
3
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException;
4
-import fr.natan.akkastreamfileprocessingapi.businessexceptions.MovieNotFoundException;
4
+import fr.natan.akkastreamfileprocessingapi.businessexceptions.TvSerieNotFoundException;
5
 import org.springframework.http.HttpStatus;
5
 import org.springframework.http.HttpStatus;
6
 import org.springframework.http.ResponseEntity;
6
 import org.springframework.http.ResponseEntity;
7
 import org.springframework.web.bind.annotation.ControllerAdvice;
7
 import org.springframework.web.bind.annotation.ControllerAdvice;
15
         return new ResponseEntity<>("The File Is Not Found Exception", HttpStatus.NOT_FOUND);
15
         return new ResponseEntity<>("The File Is Not Found Exception", HttpStatus.NOT_FOUND);
16
     }
16
     }
17
 
17
 
18
-    @ExceptionHandler(value = MovieNotFoundException.class)
19
-    private ResponseEntity<String> handleMovieNotFoundException(){
18
+    @ExceptionHandler(value = TvSerieNotFoundException.class)
19
+    private ResponseEntity<String> handleTvSerieNotFoundException(){
20
         return new ResponseEntity<>("Movie Title Not Found Exception", HttpStatus.NOT_FOUND);
20
         return new ResponseEntity<>("Movie Title Not Found Exception", HttpStatus.NOT_FOUND);
21
     }
21
     }
22
+
22
 }
23
 }

+ 17
- 7
src/main/java/fr/natan/akkastreamfileprocessingapi/futurecompleteness/CompletableFutureBuilder.java View File

1
 package fr.natan.akkastreamfileprocessingapi.futurecompleteness;
1
 package fr.natan.akkastreamfileprocessingapi.futurecompleteness;
2
 
2
 
3
-import scala.Option;
4
 import scala.collection.IndexedSeq;
3
 import scala.collection.IndexedSeq;
5
 import scala.concurrent.Future;
4
 import scala.concurrent.Future;
6
 
5
 
7
 import java.util.concurrent.CompletableFuture;
6
 import java.util.concurrent.CompletableFuture;
8
 import java.util.concurrent.Executors;
7
 import java.util.concurrent.Executors;
9
 import java.util.concurrent.TimeUnit;
8
 import java.util.concurrent.TimeUnit;
9
+import java.util.logging.Logger;
10
 
10
 
11
 
11
 
12
 public class CompletableFutureBuilder<T> {
12
 public class CompletableFutureBuilder<T> {
13
 
13
 
14
-    public static<T> CompletableFuture<T> buildcompletableFuture1(Future<Option<T>> futureT) {
14
+   private static final Logger logger = Logger.getLogger("log");
15
+    public static<T> CompletableFuture<T> buildcompletableFuture1(Future<T> futureT) {
15
         CompletableFuture<T> completableFuture = new CompletableFuture<>();
16
         CompletableFuture<T> completableFuture = new CompletableFuture<>();
17
+
18
+
16
         Executors.newSingleThreadExecutor().submit(() -> {
19
         Executors.newSingleThreadExecutor().submit(() -> {
17
             while(!futureT.isCompleted()){
20
             while(!futureT.isCompleted()){
18
-                TimeUnit.MILLISECONDS.sleep(300);
21
+                try {
22
+                    TimeUnit.MILLISECONDS.sleep(300);
23
+                } catch (InterruptedException e) {
24
+                    throw new RuntimeException(e);
25
+                }
19
             }
26
             }
20
-            T task = futureT.value().get().get().get();
27
+            T task = futureT.value().get().get();
21
             completableFuture.complete(task);
28
             completableFuture.complete(task);
22
-            return null;
23
         });
29
         });
24
 
30
 
25
         return completableFuture;
31
         return completableFuture;
30
         CompletableFuture<IndexedSeq<T>> completableFuture = new CompletableFuture<>();
36
         CompletableFuture<IndexedSeq<T>> completableFuture = new CompletableFuture<>();
31
         Executors.newSingleThreadExecutor().submit(() -> {
37
         Executors.newSingleThreadExecutor().submit(() -> {
32
             while (!futureListT.isCompleted()) {
38
             while (!futureListT.isCompleted()) {
33
-                TimeUnit.MILLISECONDS.sleep(300);
39
+                try {
40
+                    TimeUnit.MILLISECONDS.sleep(300);
41
+                } catch (InterruptedException e) {
42
+                    throw new RuntimeException(e);
43
+                }
34
             }
44
             }
35
 
45
 
36
             IndexedSeq<T> task = futureListT.value().get().get();
46
             IndexedSeq<T> task = futureListT.value().get().get();
37
             completableFuture.complete(task);
47
             completableFuture.complete(task);
38
-            return null;
48
+
39
         });
49
         });
40
 
50
 
41
         return completableFuture;
51
         return completableFuture;

src/main/scala/fr/natan/akkastreamfileprocessingapi/businessexceptions/MovieNotFoundException.scala → src/main/scala/fr/natan/akkastreamfileprocessingapi/businessexceptions/PersonNotFoundException.scala View File

1
 package fr.natan.akkastreamfileprocessingapi.businessexceptions
1
 package fr.natan.akkastreamfileprocessingapi.businessexceptions
2
 
2
 
3
-class MovieNotFoundException extends Exception{}
3
+class PersonNotFoundException extends Exception{}

+ 3
- 0
src/main/scala/fr/natan/akkastreamfileprocessingapi/businessexceptions/TvSerieNotFoundException.scala View File

1
+package fr.natan.akkastreamfileprocessingapi.businessexceptions
2
+
3
+class TvSerieNotFoundException extends Exception{}

+ 2
- 2
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/AkkaStreamComponents.scala View File

7
 import com.typesafe.scalalogging.slf4j.Logger
7
 import com.typesafe.scalalogging.slf4j.Logger
8
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException
8
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException
9
 import fr.natan.akkastreamfileprocessingapi.models.ModelsAndJsonMap.{Person, TvSerie}
9
 import fr.natan.akkastreamfileprocessingapi.models.ModelsAndJsonMap.{Person, TvSerie}
10
-import fr.natan.akkastreamfileprocessingapi.valitator.Validators.fileExists
11
 import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.{buildPersonModel, buildTvSerieModel}
10
 import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.{buildPersonModel, buildTvSerieModel}
11
+import fr.natan.akkastreamfileprocessingapi.valitator.Validators.fileExists
12
 
12
 
13
 import java.io.File
13
 import java.io.File
14
 import java.nio.file.Paths
14
 import java.nio.file.Paths
91
 
91
 
92
   //source building
92
   //source building
93
 
93
 
94
-  def buildSource(inputFile: File): Source[Map[String, String], NotUsed] = {
94
+  private def buildSource(inputFile: File): Source[Map[String, String], NotUsed] = {
95
 
95
 
96
     var datasource: Source[Map[String, String], NotUsed] = null
96
     var datasource: Source[Map[String, String], NotUsed] = null
97
     if (!fileExists(inputFile.getPath)) {
97
     if (!fileExists(inputFile.getPath)) {

+ 3
- 4
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/AkkaStreamFileProcessingFuture.scala View File

5
 
5
 
6
 import scala.concurrent.Future
6
 import scala.concurrent.Future
7
 
7
 
8
-//noinspection SpellCheckingInspection,AccessorLikeMethodIsUnit
9
 trait AkkaStreamFileProcessingFuture {
8
 trait AkkaStreamFileProcessingFuture {
10
-  def getPersonByIdFuture(personID: String): Future[Option[Person]]
11
-  def getPersonByNameFuture(primaryName: String):  Future[Option[Person]]
9
+  def getPersonByIdFuture(personID: String): Future[Person]
10
+  def getPersonByNameFuture(primaryName: String):  Future[Person]
12
 
11
 
13
-  def getTvSerieByIdFuture(tvSerieID: String): Future[Option[TvSerie]]
12
+  def getTvSerieByIdFuture(tvSerieID: String): Future[TvSerie]
14
   def getTvSeriesByPrimaryTitleFuture(tvSerieTitle: String):Future[IndexedSeq[TvSerie]]
13
   def getTvSeriesByPrimaryTitleFuture(tvSerieTitle: String):Future[IndexedSeq[TvSerie]]
15
 
14
 
16
   def getPersonsForTvSerieByTvSerieTitleFuture(tvSeriePrimaryTitle: String): Future[IndexedSeq[Person]]
15
   def getPersonsForTvSerieByTvSerieTitleFuture(tvSeriePrimaryTitle: String): Future[IndexedSeq[Person]]

+ 37
- 40
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/AkkaStreamFileProcessingImpl.scala View File

3
 import akka.Done
3
 import akka.Done
4
 import akka.stream.scaladsl.{Sink, Source}
4
 import akka.stream.scaladsl.{Sink, Source}
5
 import com.typesafe.scalalogging.slf4j.Logger
5
 import com.typesafe.scalalogging.slf4j.Logger
6
-import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics}
6
+import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics, titlePrincipalsBasics}
7
 import fr.natan.akkastreamfileprocessingapi.models.ModelsAndJsonMap.{Person, TvSerie}
7
 import fr.natan.akkastreamfileprocessingapi.models.ModelsAndJsonMap.{Person, TvSerie}
8
 import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{
8
 import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{
9
-  actorSystem, buildAllPersonsSink, buildAllTvSeriesSink, buildAndValidateSource, buildPersonFlow, buildSource,
10
-  buildTvSerieFlow, filterPersonByIdFlow, filterPersonByNameFlow, filterTvSerieByIdFlow, filterTvSerieByPrimaryTitleFlow}
11
-import fr.natan.akkastreamfileprocessingapi.service.UtilitiesClass.{
12
-  getListOfPersonsForTvSerie, getListOfPersonsIDByTvSerieID, getTvSerieIDFuture, getTvSerieIdByPrimaryTitle}
9
+  actorSystem, buildAllPersonsSink, buildAllTvSeriesSink, buildAndValidateSource, buildPersonFlow, buildTvSerieFlow,
10
+  filterPersonByIdFlow, filterPersonByNameFlow, filterTvSerieByIdFlow, filterTvSerieByPrimaryTitleFlow}
11
+import fr.natan.akkastreamfileprocessingapi.service.UtilitiesClass.{getListOfPersonsForTvSerie, getListOfPersonsIDByTvSerieID,
12
+  getTvSerieIDFuture, getTvSerieIdByPrimaryTitle}
13
 import org.slf4j.LoggerFactory
13
 import org.slf4j.LoggerFactory
14
 import org.springframework.stereotype.Component
14
 import org.springframework.stereotype.Component
15
 
15
 
24
 
24
 
25
   implicit val logger: Logger = Logger(LoggerFactory.getLogger(this.getClass))
25
   implicit val logger: Logger = Logger(LoggerFactory.getLogger(this.getClass))
26
 
26
 
27
-  override def getPersonByIdFuture(personID: String): Future[Option[Person]] = {
28
-    val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
27
+  override def getPersonByIdFuture(personID: String): Future[Person] = {
28
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = nameBasics)
29
 
29
 
30
     val start: Long = System.currentTimeMillis()
30
     val start: Long = System.currentTimeMillis()
31
-    val personFuture: Future[Option[Person]] = source
31
+    val personFuture: Future[Person] = source
32
       .via(flow = filterPersonByIdFlow(personID = personID))
32
       .via(flow = filterPersonByIdFlow(personID = personID))
33
-      .runWith(Sink.headOption[Person])
33
+      .runWith(Sink.head[Person])
34
 
34
 
35
     personFuture.andThen({
35
     personFuture.andThen({
36
-      case Failure(exception) => logger.info(s"$exception")
37
-      case Success(value: Option[Person]) =>
38
-        logger.info(s"$value")
39
-        logger.info(s"SUCCESS, elapsed time:${(System.currentTimeMillis() - start) / 1000} sec")
36
+      case Failure(exception) => logger.error(s"!${exception.printStackTrace()}")
40
     })
37
     })
41
 
38
 
42
     personFuture
39
     personFuture
43
   }
40
   }
44
 
41
 
45
-  override def getPersonByNameFuture(primaryName: String): Future[Option[Person]] = {
46
-    val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
42
+  override def getPersonByNameFuture(primaryName: String): Future[Person] = {
43
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = nameBasics)
47
 
44
 
48
     val start: Long = System.currentTimeMillis()
45
     val start: Long = System.currentTimeMillis()
49
-    val personFuture: Future[Option[Person]] = source
46
+    val personFuture: Future[Person] = source
50
       .via(flow = filterPersonByNameFlow(primaryName = primaryName))
47
       .via(flow = filterPersonByNameFlow(primaryName = primaryName))
51
-      .runWith(Sink.headOption[Person])
48
+      .runWith(Sink.head[Person])
52
 
49
 
53
     personFuture
50
     personFuture
54
   }
51
   }
55
 
52
 
56
-  override def getTvSerieByIdFuture(tvSerieID: String): Future[Option[TvSerie]] = {
57
-    val source: Source[Map[String, String], _] = buildSource(inputFile = titleBasics)
53
+  override def getTvSerieByIdFuture(tvSerieID: String): Future[TvSerie] = {
54
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = titleBasics)
58
 
55
 
59
     val start: Long = System.currentTimeMillis()
56
     val start: Long = System.currentTimeMillis()
60
-    val tvSerieFuture: Future[Option[TvSerie]] = source
57
+    val tvSerieFuture: Future[TvSerie] = source
61
       .via(flow = filterTvSerieByIdFlow(tvSerieID = tvSerieID))
58
       .via(flow = filterTvSerieByIdFlow(tvSerieID = tvSerieID))
62
-      .runWith(Sink.headOption[TvSerie])
59
+      .runWith(Sink.head[TvSerie])
63
 
60
 
64
     tvSerieFuture.onComplete({
61
     tvSerieFuture.onComplete({
65
       case Failure(exception) => logger.info(s"$exception")
62
       case Failure(exception) => logger.info(s"$exception")
66
-      case Success(value: Option[TvSerie]) =>
63
+      case Success(value: TvSerie) =>
67
         logger.info(s"$value")
64
         logger.info(s"$value")
68
         logger.info(s"SUCCESS, elapsed time:${(System.currentTimeMillis() - start) / 1000} sec")
65
         logger.info(s"SUCCESS, elapsed time:${(System.currentTimeMillis() - start) / 1000} sec")
69
     })
66
     })
91
   override def getPersonsForTvSerieByTvSerieTitleFuture(tvSeriePrimaryTitle: String): Future[IndexedSeq[Person]] = {
88
   override def getPersonsForTvSerieByTvSerieTitleFuture(tvSeriePrimaryTitle: String): Future[IndexedSeq[Person]] = {
92
 
89
 
93
     //futures chaining
90
     //futures chaining
94
-    logger.info("STEP 1/3 START")
91
+    logger.info("STEP 1/3 ...")
95
     val start1: Long = System.currentTimeMillis()
92
     val start1: Long = System.currentTimeMillis()
96
-    val tvSerieIDFuture: Future[Option[String]] = getTvSerieIdByPrimaryTitle(primaryTitle = tvSeriePrimaryTitle)
93
+    val tvSerieIDFuture: Future[Option[String]] = getTvSerieIdByPrimaryTitle(
94
+      primaryTitle = tvSeriePrimaryTitle,
95
+      inputFile = titleBasics
96
+    )
97
 
97
 
98
     val finalFuture: Future[IndexedSeq[Person]] =
98
     val finalFuture: Future[IndexedSeq[Person]] =
99
       tvSerieIDFuture.andThen({
99
       tvSerieIDFuture.andThen({
100
-        case Failure(exception) => logger.error(s"$exception")
101
         case Success(value: Option[String]) =>
100
         case Success(value: Option[String]) =>
102
           logger.info(s"TvSerie ID: $value")
101
           logger.info(s"TvSerie ID: $value")
103
           logger.info(s"STEP 1/3 END, elapsed time:${(System.currentTimeMillis() - start1) / 1000} sec")
102
           logger.info(s"STEP 1/3 END, elapsed time:${(System.currentTimeMillis() - start1) / 1000} sec")
105
       })
104
       })
106
         .flatMap({
105
         .flatMap({
107
           _ =>
106
           _ =>
108
-            logger.info("STEP 2/3 START")
107
+            logger.info("STEP 2/3 ...")
109
             val start2: Long = System.currentTimeMillis()
108
             val start2: Long = System.currentTimeMillis()
110
             val listPersonIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(
109
             val listPersonIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(
111
-              tvSerieIdFuture = tvSerieIDFuture)
110
+              tvSerieIdFuture = tvSerieIDFuture, inputFile = titlePrincipalsBasics
111
+            )
112
             listPersonIDsFuture.andThen({
112
             listPersonIDsFuture.andThen({
113
-              case Failure(exception) => logger.error(s"$exception")
114
               case Success(value) =>
113
               case Success(value) =>
115
                 value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
114
                 value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
116
                 logger.info(s"STEP 2/3 END, elapsed time:${(System.currentTimeMillis() - start2) / 1000} sec")
115
                 logger.info(s"STEP 2/3 END, elapsed time:${(System.currentTimeMillis() - start2) / 1000} sec")
117
             })
116
             })
118
               .flatMap({
117
               .flatMap({
119
                 _ =>
118
                 _ =>
120
-                  logger.info("STEP 3/3 START")
119
+                  logger.info("STEP 3/3 ...")
121
                   val start3: Long = System.currentTimeMillis()
120
                   val start3: Long = System.currentTimeMillis()
122
                   val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(
121
                   val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(
123
-                    listPersonsIDsFuture = listPersonIDsFuture)
122
+                    listPersonsIDsFuture = listPersonIDsFuture, inputFile = nameBasics)
124
                   personsTeamFuture.andThen({
123
                   personsTeamFuture.andThen({
125
-                    case Failure(exception) => logger.error(s"$exception")
126
                     case Success(value: IndexedSeq[Person]) =>
124
                     case Success(value: IndexedSeq[Person]) =>
127
                       value.foreach((person: Person) => logger.info(s"${person.toString}"))
125
                       value.foreach((person: Person) => logger.info(s"${person.toString}"))
128
                       logger.info(s"STEP 3/3 END, elapsed time:${(System.currentTimeMillis() - start3) / 1000} sec")
126
                       logger.info(s"STEP 3/3 END, elapsed time:${(System.currentTimeMillis() - start3) / 1000} sec")
136
   override def getPersonsForTvSerieByTvSerieIDFuture(tvSerieId: String): Future[IndexedSeq[Person]] = {
134
   override def getPersonsForTvSerieByTvSerieIDFuture(tvSerieId: String): Future[IndexedSeq[Person]] = {
137
 
135
 
138
     val start1: Long = System.currentTimeMillis()
136
     val start1: Long = System.currentTimeMillis()
139
-    logger.info("STEP 1/3")
140
-    val tvSerieIdFuture: Future[Option[String]] = getTvSerieIDFuture(tvSerieId = tvSerieId)
137
+    logger.info("STEP 1/3 ...")
138
+    val tvSerieIdFuture: Future[Option[String]] = getTvSerieIDFuture(
139
+      tvSerieID = tvSerieId, logger = logger, inputFile = titleBasics)
141
     tvSerieIdFuture.andThen({
140
     tvSerieIdFuture.andThen({
142
       case Failure(exception) => logger.error(s"${exception.printStackTrace()}")
141
       case Failure(exception) => logger.error(s"${exception.printStackTrace()}")
143
       case Success(value: Option[String]) =>
142
       case Success(value: Option[String]) =>
147
     })
146
     })
148
       .flatMap({
147
       .flatMap({
149
         _ =>
148
         _ =>
150
-          logger.info("STEP 2/3")
149
+          logger.info("STEP 2/3 ...")
151
           val start2: Long = System.currentTimeMillis()
150
           val start2: Long = System.currentTimeMillis()
152
           val listOfPersonsIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(
151
           val listOfPersonsIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(
153
-            tvSerieIdFuture = tvSerieIdFuture)
152
+            tvSerieIdFuture = tvSerieIdFuture, inputFile = titlePrincipalsBasics)
154
           listOfPersonsIDsFuture.andThen({
153
           listOfPersonsIDsFuture.andThen({
155
             case Failure(exception) => logger.error(s"${exception.printStackTrace()}")
154
             case Failure(exception) => logger.error(s"${exception.printStackTrace()}")
156
             case Success(value: IndexedSeq[Option[String]]) =>
155
             case Success(value: IndexedSeq[Option[String]]) =>
159
           })
158
           })
160
             .flatMap({
159
             .flatMap({
161
               _ =>
160
               _ =>
162
-                logger.info("STEP 3/3")
161
+                logger.info("STEP 3/3 ...")
163
                 val start3: Long = System.currentTimeMillis()
162
                 val start3: Long = System.currentTimeMillis()
164
                 val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(
163
                 val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(
165
-                  listPersonsIDsFuture = listOfPersonsIDsFuture)
164
+                  listPersonsIDsFuture = listOfPersonsIDsFuture, inputFile = nameBasics)
166
                 personsTeamFuture.andThen({
165
                 personsTeamFuture.andThen({
167
                   case Failure(exception) => logger.error(s"$exception")
166
                   case Failure(exception) => logger.error(s"$exception")
168
                   case Success(value: IndexedSeq[Person]) =>
167
                   case Success(value: IndexedSeq[Person]) =>
175
   }
174
   }
176
 
175
 
177
   override def getAllPersonsFuture: Future[Done] = {
176
   override def getAllPersonsFuture: Future[Done] = {
178
-    val personSource: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
177
+    val personSource: Source[Map[String, String], _] = buildAndValidateSource(inputFile = nameBasics)
179
     //graph
178
     //graph
180
     val startTime: Long = System.currentTimeMillis()
179
     val startTime: Long = System.currentTimeMillis()
181
     val result: Future[Done] = personSource
180
     val result: Future[Done] = personSource
189
         val time: Long = (System.currentTimeMillis() - startTime) / 100
188
         val time: Long = (System.currentTimeMillis() - startTime) / 100
190
         logger.info(s"elapsed time: $time")
189
         logger.info(s"elapsed time: $time")
191
     }
190
     }
192
-
193
     result
191
     result
194
   }
192
   }
195
 
193
 
211
 
209
 
212
     results
210
     results
213
   }
211
   }
214
-
215
 }
212
 }
216
 
213
 
217
 
214
 

+ 33
- 14
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/UtilitiesClass.scala View File

1
 package fr.natan.akkastreamfileprocessingapi.service
1
 package fr.natan.akkastreamfileprocessingapi.service
2
 
2
 
3
-import akka.stream.scaladsl.{Sink, Source}
4
-import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics, titlePrincipalsBasics}
3
+import akka.NotUsed
4
+import akka.stream.scaladsl.{Flow, Sink, Source}
5
+import com.typesafe.scalalogging.slf4j.Logger
6
+import fr.natan.akkastreamfileprocessingapi.businessexceptions.TvSerieNotFoundException
5
 import fr.natan.akkastreamfileprocessingapi.models.ModelsAndJsonMap.Person
7
 import fr.natan.akkastreamfileprocessingapi.models.ModelsAndJsonMap.Person
6
 import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.buildPersonModel
8
 import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.buildPersonModel
7
-import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{actorSystem, buildSource}
9
+import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{actorSystem, buildAndValidateSource}
8
 
10
 
11
+import java.io.File
12
+import scala.concurrent.ExecutionContext.Implicits.global
9
 import scala.concurrent.Future
13
 import scala.concurrent.Future
14
+import scala.util.{Failure, Success}
10
 
15
 
11
 object UtilitiesClass {
16
 object UtilitiesClass {
12
 
17
 
13
-  def getTvSerieIdByPrimaryTitle(primaryTitle: String): Future[Option[String]] = {
14
-    val source: Source[Map[String, String], _] = buildSource(inputFile = titleBasics)
18
+  def getTvSerieIdByPrimaryTitle(primaryTitle: String, inputFile: File): Future[Option[String]] = {
19
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = inputFile)
15
     val tvSerieIdFuture: Future[Option[String]] = source
20
     val tvSerieIdFuture: Future[Option[String]] = source
16
       .filter((rowMap: Map[String, String]) => {
21
       .filter((rowMap: Map[String, String]) => {
17
         rowMap.getOrElse(key = "primaryTitle", default = "") == primaryTitle
22
         rowMap.getOrElse(key = "primaryTitle", default = "") == primaryTitle
22
     tvSerieIdFuture
27
     tvSerieIdFuture
23
   }
28
   }
24
 
29
 
25
-  def getListOfPersonsIDByTvSerieID(tvSerieIdFuture: Future[Option[String]]): Future[IndexedSeq[Option[String]]] = {
26
-    val source: Source[Map[String, String], _] = buildSource(inputFile = titlePrincipalsBasics)
30
+  def getListOfPersonsIDByTvSerieID(tvSerieIdFuture: Future[Option[String]], inputFile: File): Future[IndexedSeq[Option[String]]] = {
31
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = inputFile)
27
     val personsIDsFuture: Future[IndexedSeq[Option[String]]] = source
32
     val personsIDsFuture: Future[IndexedSeq[Option[String]]] = source
28
       .filter((rowMaps: Map[String, String]) => {
33
       .filter((rowMaps: Map[String, String]) => {
29
         rowMaps.getOrElse(key = "tconst", default = "") == tvSerieIdFuture.value.get.get.get
34
         rowMaps.getOrElse(key = "tconst", default = "") == tvSerieIdFuture.value.get.get.get
36
     personsIDsFuture
41
     personsIDsFuture
37
   }
42
   }
38
 
43
 
39
-  def getListOfPersonsForTvSerie(listPersonsIDsFuture: Future[IndexedSeq[Option[String]]]): Future[IndexedSeq[Person]] = {
44
+  def getListOfPersonsForTvSerie(listPersonsIDsFuture: Future[IndexedSeq[Option[String]]], inputFile: File): Future[IndexedSeq[Person]] = {
40
 
45
 
41
-    val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
46
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = inputFile)
42
     val personsFuture: Future[IndexedSeq[Person]] = source
47
     val personsFuture: Future[IndexedSeq[Person]] = source
43
       .filter((rowMaps: Map[String, String]) => {
48
       .filter((rowMaps: Map[String, String]) => {
44
         listPersonsIDsFuture.value.get.get.contains(rowMaps.get(key = "nconst"))
49
         listPersonsIDsFuture.value.get.get.contains(rowMaps.get(key = "nconst"))
51
     personsFuture
56
     personsFuture
52
   }
57
   }
53
 
58
 
54
-  def getTvSerieIDFuture(tvSerieId: String): Future[Option[String]] = {
55
-    val source: Source[Map[String, String], _] = buildSource(inputFile = titlePrincipalsBasics)
59
+  private def getTvSerieIdFlow(tvSerieID: String): Flow[Map[String, String], Option[String], NotUsed] = {
60
+    val tvSerieIDFlow = Flow[Map[String, String]]
61
+      .filter(rowMap => rowMap.getOrElse(key = "tconst", default = "") == tvSerieID)
62
+      .map(row => row.get("tconst"))
56
 
63
 
57
-    val tvSerieIdFuture: Future[Option[String]] = source.
58
-      filter((rowMap: Map[String, String]) => rowMap.getOrElse(key = "tconst", default = "") == tvSerieId)
59
-      .map((rowMap: Map[String, String]) => rowMap.get(key = "tconst"))
64
+    tvSerieIDFlow
65
+  }
66
+
67
+  def getTvSerieIDFuture(tvSerieID: String, logger: Logger, inputFile: File): Future[Option[String]] = {
68
+    val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = inputFile)
69
+
70
+    val tvSerieIdFuture: Future[Option[String]] = source
71
+      .filter(rowMap => rowMap.getOrElse(key = "tconst", default = "") == tvSerieID)
72
+      .map(row => row.get("tconst"))
60
       .runWith(Sink.head)
73
       .runWith(Sink.head)
61
 
74
 
75
+    tvSerieIdFuture.onComplete({
76
+      case Failure(noSuchElementException: NoSuchElementException) => throw new TvSerieNotFoundException()
77
+      case Failure(exception: Exception) => throw new RuntimeException()
78
+      case Success(value) => logger.info(s"$value")
79
+    })
80
+
62
     tvSerieIdFuture
81
     tvSerieIdFuture
63
   }
82
   }
64
 
83
 

Powered by TurnKey Linux.