Browse Source

first commit

placidenduwayo 1 year ago
parent
commit
140fbebeea

+ 7
- 1
src/main/java/fr/natan/akkastreamfileprocessingapi/controller/MovieController.java View File

35
         return new ResponseEntity<>("is running", HttpStatus.OK);
35
         return new ResponseEntity<>("is running", HttpStatus.OK);
36
     }
36
     }
37
 
37
 
38
-    @RequestMapping(value = "/persons/{personID}", method = RequestMethod.GET)
38
+    @RequestMapping(value = "/persons/id/{personID}", method = RequestMethod.GET)
39
     private ResponseEntity<String> getPersonByID(@PathVariable(name = "personID") String nconst){
39
     private ResponseEntity<String> getPersonByID(@PathVariable(name = "personID") String nconst){
40
        akkaStreamFilesProcessing.getPersonById(nconst);
40
        akkaStreamFilesProcessing.getPersonById(nconst);
41
 
41
 
42
        return new ResponseEntity<>("is running", HttpStatus.OK);
42
        return new ResponseEntity<>("is running", HttpStatus.OK);
43
 
43
 
44
     }
44
     }
45
+
46
+    @RequestMapping(value = "/persons/name/{primaryName}", method = RequestMethod.GET)
47
+    private ResponseEntity<String> getPersonByName(@PathVariable(name = "primaryName") String primaryName){
48
+        akkaStreamFilesProcessing.getPersonByName(primaryName);
49
+        return new ResponseEntity<>("is running", HttpStatus.OK);
50
+    }
45
 }
51
 }

+ 0
- 5
src/main/scala/fr/natan/akkastreamfileprocessingapi/jsonformat/ToJsonMapping.scala View File

1
-package fr.natan.akkastreamfileprocessingapi.jsonformat
2
-
3
-case class ToJsonMapping() {
4
-
5
-}

+ 48
- 0
src/main/scala/fr/natan/akkastreamfileprocessingapi/models/Models.scala View File

1
+package fr.natan.akkastreamfileprocessingapi.models
2
+
3
+object Models {
4
+
5
+  final case class Person(
6
+                           nconst: String,
7
+                           primaryName: String,
8
+                           birthYear: String,
9
+                           deathYear: String,
10
+                           primaryProfession: List[String],
11
+                           knownForTitles: List[String]
12
+                         ) {
13
+    override def toString: String = {
14
+      "Person[person-ID:" + nconst +
15
+        ", primary-name:" + primaryName +
16
+        ", birth-year:" + birthYear +
17
+        ", dearth year:" + deathYear +
18
+        ", primary profession:" + primaryProfession +
19
+        ", known for titles:" + knownForTitles +
20
+        "]"
21
+    }
22
+  }
23
+
24
+  final case class TvSeries(
25
+                             tconst: String,
26
+                             titleType: String,
27
+                             primaryTitle: String,
28
+                             originalTitle: String,
29
+                             isAdult: String,
30
+                             startYear: String,
31
+                             endYear: String,
32
+                             runtimeMinutes: String,
33
+                             genres: String
34
+                           ) {
35
+
36
+    override def toString: String = {
37
+      "TvSerie[tvSerieID : " + tconst +
38
+        ", title-type:" + titleType +
39
+        ", primary-title:" + primaryTitle + "" +
40
+        ", riginal-title:" + originalTitle +
41
+        ", is adult (no=0, yes=1):" + isAdult +
42
+        ", start year:" + startYear +
43
+        ", end year:" + endYear +
44
+        ", runtime minutes:" + runtimeMinutes +
45
+        ", genre:" + genres + "]"
46
+    }
47
+  }
48
+}

+ 30
- 0
src/main/scala/fr/natan/akkastreamfileprocessingapi/models/ModelsBuilder.scala View File

1
+package fr.natan.akkastreamfileprocessingapi.models
2
+import Models.{Person, TvSeries}
3
+object ModelsBuilder {
4
+
5
+  def buildPersonModel(map: Map[String, String]): Person = {
6
+    Person(
7
+      map("nconst"),
8
+      map("primaryName"),
9
+      map("birthYear"),
10
+      map("deathYear"),
11
+      map("primaryProfession").split(",").toList,
12
+      map("knownForTitles").split(",").toList,
13
+    )
14
+  }
15
+
16
+  def buildTvSerieModel(map: Map[String, String]): TvSeries = {
17
+    val tvSerie: TvSeries = TvSeries(
18
+      map("tconst"),
19
+      map("titleType"),
20
+      map("primaryTitle"),
21
+      map("originalTitle"),
22
+      map("isAdult"),
23
+      map("startYear"),
24
+      map("endYear"),
25
+      map("runtimeMinutes"),
26
+      map("genres")
27
+    )
28
+    tvSerie
29
+  }
30
+}

+ 0
- 20
src/main/scala/fr/natan/akkastreamfileprocessingapi/models/Person.scala View File

1
-package fr.natan.akkastreamfileprocessingapi.models
2
-
3
-final case class Person(
4
-                         nconst: String,
5
-                         primaryName: String,
6
-                         birthYear: String,
7
-                         deathYear: String,
8
-                         primaryProfession: List[String],
9
-                         knownForTitles: List[String]
10
-                       ){
11
-  override def toString: String = {
12
-    "Person[ person-ID:"+nconst+
13
-      ", primary-name:"+primaryName+
14
-    ", birth-year:"+birthYear+
15
-    ", dearth year:"+deathYear+
16
-    ", primary profession:"+primaryProfession+
17
-    ", known for titles:"+knownForTitles+
18
-    "]"
19
-  }
20
-}

+ 0
- 26
src/main/scala/fr/natan/akkastreamfileprocessingapi/models/TvSeries.scala View File

1
-package fr.natan.akkastreamfileprocessingapi.models
2
-
3
-final case class TvSeries(
4
-                     tconst: String,
5
-                     titleType: String,
6
-                     primaryTitle: String,
7
-                    originalTitle: String,
8
-                     isAdult: String,
9
-                     startYear: String,
10
-                    endYear: String,
11
-                     runtimeMinutes: String,
12
-                     genres: String
13
-                   ) {
14
-
15
-  override def toString: String = {
16
-    "TvSerie[tvSerieID : " + tconst +
17
-      ", title-type:"+titleType+
18
-      ", primary-title:"+primaryTitle+"" +
19
-      ", riginal-title:"+originalTitle+
20
-      ", is adult (no=0, yes=1):"+isAdult+
21
-      ", start year:"+startYear+
22
-    ", end year:"+endYear+
23
-      ", runtime minutes:"+runtimeMinutes+
24
-      ", genre:"+genres+"]"
25
-  }
26
-}

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

2
 
2
 
3
 import akka.actor.ActorSystem
3
 import akka.actor.ActorSystem
4
 import akka.stream.alpakka.csv.scaladsl.{CsvParsing, CsvToMap}
4
 import akka.stream.alpakka.csv.scaladsl.{CsvParsing, CsvToMap}
5
-import akka.stream.javadsl.Framing
6
 import akka.stream.scaladsl.{Compression, FileIO, Flow, Sink, Source}
5
 import akka.stream.scaladsl.{Compression, FileIO, Flow, Sink, Source}
7
-import akka.util.ByteString
8
 import akka.{Done, NotUsed}
6
 import akka.{Done, NotUsed}
9
 import com.typesafe.scalalogging.slf4j.Logger
7
 import com.typesafe.scalalogging.slf4j.Logger
10
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException
8
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException
11
-import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.separator
12
-import fr.natan.akkastreamfileprocessingapi.models.{Person, TvSeries}
9
+import fr.natan.akkastreamfileprocessingapi.models.Models.{Person, TvSeries}
13
 import fr.natan.akkastreamfileprocessingapi.valitator.Validators.fileExists
10
 import fr.natan.akkastreamfileprocessingapi.valitator.Validators.fileExists
11
+import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.{buildPersonModel, buildTvSerieModel}
14
 
12
 
15
 import java.io.File
13
 import java.io.File
16
 import java.nio.file.Paths
14
 import java.nio.file.Paths
20
 
18
 
21
   implicit val actor: ActorSystem = ActorSystem("AkkaStreamActor")
19
   implicit val actor: ActorSystem = ActorSystem("AkkaStreamActor")
22
 
20
 
23
-  private def convertToTvSerie(map: Map[String, String]): TvSeries = {
24
-    val tvSerie: TvSeries = TvSeries(
25
-      map("tconst"),
26
-      map("titleType"),
27
-      map("primaryTitle"),
28
-      map("originalTitle"),
29
-      map("isAdult"),
30
-      map("startYear"),
31
-      map("endYear"),
32
-      map("runtimeMinutes"),
33
-      map("genres")
34
-    )
35
-
36
-    tvSerie
37
-  }
38
-
39
-  private def convertToPerson(map: Map[String, String]): Person ={
40
-    Person(
41
-      map("nconst"),
42
-      map("primaryName"),
43
-      map("birthYear"),
44
-      map("deathYear"),
45
-      map("primaryProfession").split(",").toList,
46
-      map("knownForTitles").split(",").toList,
47
-    )
48
-  }
49
-
50
-  //flows
21
+  //flows building
51
 
22
 
23
+  //flow1
52
   def buildTvSerieFlow(): Flow[Map[String, String], TvSeries, NotUsed] = {
24
   def buildTvSerieFlow(): Flow[Map[String, String], TvSeries, NotUsed] = {
53
 
25
 
54
     val tvFlow: Flow[Map[String, String], TvSeries, NotUsed] =
26
     val tvFlow: Flow[Map[String, String], TvSeries, NotUsed] =
55
       Flow[Map[String, String]]
27
       Flow[Map[String, String]]
56
         .map(row => {
28
         .map(row => {
57
-          convertToTvSerie(row)
29
+          buildTvSerieModel(row)
58
         })
30
         })
59
     tvFlow
31
     tvFlow
60
   }
32
   }
61
 
33
 
34
+  //flow2
62
   def buildPersonFlow(): Flow[Map[String, String], Person, NotUsed] = {
35
   def buildPersonFlow(): Flow[Map[String, String], Person, NotUsed] = {
63
     val personFlow: Flow[Map[String, String], Person, NotUsed] =
36
     val personFlow: Flow[Map[String, String], Person, NotUsed] =
64
       Flow[Map[String, String]]
37
       Flow[Map[String, String]]
65
         .map((rowMap: Map[String, String]) => {
38
         .map((rowMap: Map[String, String]) => {
66
-          convertToPerson(rowMap)
39
+          buildPersonModel(rowMap)
67
         })
40
         })
68
 
41
 
69
     personFlow
42
     personFlow
70
   }
43
   }
71
 
44
 
45
+  //flow3
72
   def filterByMoviePrimaryTitleFlow(moviePrimaryTitle: String): Flow[Map[String, String], TvSeries, NotUsed] = {
46
   def filterByMoviePrimaryTitleFlow(moviePrimaryTitle: String): Flow[Map[String, String], TvSeries, NotUsed] = {
73
     val filterFlow: Flow[Map[String, String], TvSeries, NotUsed] = Flow[Map[String, String]]
47
     val filterFlow: Flow[Map[String, String], TvSeries, NotUsed] = Flow[Map[String, String]]
74
         .filter((rows: Map[String, String]) => {
48
         .filter((rows: Map[String, String]) => {
75
           rows.getOrElse("primaryTitle","")==moviePrimaryTitle
49
           rows.getOrElse("primaryTitle","")==moviePrimaryTitle
76
         })
50
         })
77
         .map(rowMap => {
51
         .map(rowMap => {
78
-          convertToTvSerie(map = rowMap)
52
+          buildTvSerieModel(map = rowMap)
79
         })
53
         })
80
 
54
 
81
     filterFlow
55
     filterFlow
82
   }
56
   }
83
 
57
 
84
-  def filterByPersonID(nconst: String): Flow[Map[String, String], Person, NotUsed]={
58
+  //flow4
59
+  def filterByPersonIdFlow(nconst: String): Flow[Map[String, String], Person, NotUsed]={
85
     val personFilter: Flow[Map[String, String], Person, NotUsed]=
60
     val personFilter: Flow[Map[String, String], Person, NotUsed]=
86
       Flow[Map[String, String]]
61
       Flow[Map[String, String]]
87
         .filter((rowMap:Map[String, String])=>{
62
         .filter((rowMap:Map[String, String])=>{
88
           rowMap.getOrElse("nconst","")==nconst
63
           rowMap.getOrElse("nconst","")==nconst
89
         })
64
         })
90
         .map(rowMap=>{
65
         .map(rowMap=>{
91
-          convertToPerson(map = rowMap)
66
+          buildPersonModel(map = rowMap)
67
+        })
68
+
69
+    personFilter
70
+  }
71
+
72
+  def filterByPersonNameFlow(personName: String): Flow[Map[String, String], Person, NotUsed] ={
73
+    val personFilter: Flow[Map[String, String], Person, NotUsed] =
74
+      Flow[Map[String, String]]
75
+        .filter((rowMap: Map[String, String]) =>{
76
+          rowMap.getOrElse("primaryName","")==personName
77
+        })
78
+        .map((rowMap: Map[String, String])=>{
79
+          buildPersonModel(map = rowMap)
92
         })
80
         })
93
 
81
 
94
     personFilter
82
     personFilter
95
   }
83
   }
96
 
84
 
97
-  //source
85
+  //source building
98
   def buildSource(inputFile: File): Source[Map[String, String], NotUsed] = {
86
   def buildSource(inputFile: File): Source[Map[String, String], NotUsed] = {
99
 
87
 
100
     var datasource: Source[Map[String, String], NotUsed] = null
88
     var datasource: Source[Map[String, String], NotUsed] = null
126
     source
114
     source
127
   }
115
   }
128
 
116
 
129
-  //sink
117
+  //sinks building
118
+
119
+  //sink1
130
   def buildTvSeriesSink(logger: Logger): Sink[TvSeries, Future[Done]] = {
120
   def buildTvSeriesSink(logger: Logger): Sink[TvSeries, Future[Done]] = {
131
     val tvSeriesSink : Sink[TvSeries, Future[Done]]= Sink.foreach[TvSeries](
121
     val tvSeriesSink : Sink[TvSeries, Future[Done]]= Sink.foreach[TvSeries](
132
       (movie: TvSeries) => {
122
       (movie: TvSeries) => {
136
     tvSeriesSink
126
     tvSeriesSink
137
   }
127
   }
138
 
128
 
139
-  def buildPersonsSink(logger: Logger): Sink[Person,Future[Done]] = {
140
-    val listPersonsSink: Sink[Person, Future[Done]]=
141
-      Sink.foreach[Person]((person: Person)=>{
142
-        logger.info(s"${person.toString}")
143
-      })
144
-
129
+  //sink2
130
+  def buildAllPersonsSink(logger: Logger): Sink[Person,Future[Seq[Person]]] = {
131
+    val listPersonsSink: Sink[Person, Future[Seq[Person]]]=
132
+      Sink.seq
145
     listPersonsSink
133
     listPersonsSink
146
   }
134
   }
147
 
135
 
136
+  //sink3
148
   def buildPersonSink(logger: Logger): Sink[Person, Future[Done]] = {
137
   def buildPersonSink(logger: Logger): Sink[Person, Future[Done]] = {
149
     Sink.foreach[Person](
138
     Sink.foreach[Person](
150
       (person: Person) => logger.info(s"${person.toString}")
139
       (person: Person) => logger.info(s"${person.toString}")

+ 1
- 4
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/AkkaStreamFileProcessing.scala View File

1
 package fr.natan.akkastreamfileprocessingapi.service
1
 package fr.natan.akkastreamfileprocessingapi.service
2
 
2
 
3
-import akka.Done
4
-
5
-import scala.concurrent.Future
6
-
7
 trait AkkaStreamFileProcessing {
3
 trait AkkaStreamFileProcessing {
8
 
4
 
9
   def getAllMovies()
5
   def getAllMovies()
12
   def getAllPersons()
8
   def getAllPersons()
13
 
9
 
14
   def getPersonById(nconst: String)
10
   def getPersonById(nconst: String)
11
+  def getPersonByName(primaryName: String)
15
 }
12
 }

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

5
 import akka.{Done, NotUsed}
5
 import akka.{Done, NotUsed}
6
 import com.typesafe.scalalogging.slf4j.Logger
6
 import com.typesafe.scalalogging.slf4j.Logger
7
 import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics}
7
 import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics}
8
-import fr.natan.akkastreamfileprocessingapi.models.{Person, TvSeries}
9
-import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{
10
-  buildAndValidateSource,
11
-  buildPersonFlow,
12
-  buildPersonSink,
13
-  buildPersonsSink,
14
-  buildSource, buildTvSerieFlow,
15
-  buildTvSeriesSink, filterByMoviePrimaryTitleFlow,
16
-  filterByPersonID
17
-}
8
+import fr.natan.akkastreamfileprocessingapi.models.Models.{Person, TvSeries}
9
+import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{buildAndValidateSource, buildPersonFlow, buildPersonSink, buildSource, buildTvSerieFlow, buildTvSeriesSink, filterByMoviePrimaryTitleFlow, filterByPersonIdFlow, filterByPersonNameFlow}
18
 import org.slf4j.LoggerFactory
10
 import org.slf4j.LoggerFactory
19
 import org.springframework.stereotype.Component
11
 import org.springframework.stereotype.Component
20
 
12
 
33
     val source: Source[Map[String, String], NotUsed] = buildAndValidateSource(inputFile = titleBasics)
25
     val source: Source[Map[String, String], NotUsed] = buildAndValidateSource(inputFile = titleBasics)
34
     val sink: Sink[TvSeries, Future[Done]] = buildTvSeriesSink(logger = logger)
26
     val sink: Sink[TvSeries, Future[Done]] = buildTvSeriesSink(logger = logger)
35
 
27
 
36
-
37
     val startingTime: Long = System.currentTimeMillis()
28
     val startingTime: Long = System.currentTimeMillis()
38
 
29
 
39
     //graph sink->flow->sink
30
     //graph sink->flow->sink
51
 
42
 
52
   override def getMoviesByTitle(moviePrimaryTitle: String): Unit = {
43
   override def getMoviesByTitle(moviePrimaryTitle: String): Unit = {
53
 
44
 
54
-    /*val tvSeriesSource: Source[String, NotUsed] = buildAndValidateSource(inputFile = titleBasics)
45
+    val tvSeriesSource: Source[Map[String, String], NotUsed] = buildAndValidateSource(inputFile = titleBasics)
55
     val tvSeriesSink: Sink[TvSeries, Future[Done]] = buildTvSeriesSink(logger = logger)
46
     val tvSeriesSink: Sink[TvSeries, Future[Done]] = buildTvSeriesSink(logger = logger)
56
 
47
 
57
-    val filterByMovieTitleFlow: Flow[String, TvSeries, NotUsed] =
48
+    val filterByMovieTitleFlow: Flow[Map[String, String], TvSeries, NotUsed] =
58
       filterByMoviePrimaryTitleFlow(moviePrimaryTitle = moviePrimaryTitle)
49
       filterByMoviePrimaryTitleFlow(moviePrimaryTitle = moviePrimaryTitle)
59
 
50
 
60
     val startTime: Long = System.currentTimeMillis()
51
     val startTime: Long = System.currentTimeMillis()
64
       .andThen {
55
       .andThen {
65
         case Success(value) =>
56
         case Success(value) =>
66
           val elapsedTime: Long = (System.currentTimeMillis() - startTime) / 1000
57
           val elapsedTime: Long = (System.currentTimeMillis() - startTime) / 1000
67
-          logger.info(s"$value: successfully processing file, elapsed time $titleBasics: $elapsedTime sec")
58
+          logger.info(s"$value: successfully processing file, elapsed time: $elapsedTime sec")
68
         case Failure(error: Error) => logger.error(s"$error")
59
         case Failure(error: Error) => logger.error(s"$error")
69
-      }*/
60
+      }
70
   }
61
   }
71
 
62
 
72
   override def getAllPersons(): Unit = {
63
   override def getAllPersons(): Unit = {
73
     val personSource: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics)
64
     val personSource: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics)
74
-    val personSink: Sink[Person, Future[Done]] = buildPersonsSink(logger = logger)
65
+    val personSink: Sink[Person, Future[Done]] = buildPersonSink(logger = logger)
75
 
66
 
76
     //graph
67
     //graph
77
     val startTime: Long = System.currentTimeMillis()
68
     val startTime: Long = System.currentTimeMillis()
81
       .andThen {
72
       .andThen {
82
         case Success(value) =>
73
         case Success(value) =>
83
           val elapsedTime: Long = (System.currentTimeMillis() - startTime) / 1000
74
           val elapsedTime: Long = (System.currentTimeMillis() - startTime) / 1000
84
-          logger.info(s"$value: successfully processing file $elapsedTime sec")
75
+          logger.info(s"$value: successfully processing, elapsed time: $elapsedTime sec")
85
         case Failure(error: Error) => logger.error(s"$error")
76
         case Failure(error: Error) => logger.error(s"$error")
86
       }
77
       }
87
   }
78
   }
88
 
79
 
89
   override def getPersonById(nconst: String): Unit = {
80
   override def getPersonById(nconst: String): Unit = {
90
     val source: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics)
81
     val source: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics)
91
-    val sink: Sink[Person, Future[Done]] = buildPersonSink(logger = logger)
92
 
82
 
93
     val startTime: Long = System.currentTimeMillis()
83
     val startTime: Long = System.currentTimeMillis()
94
     source
84
     source
95
-      .via(flow = filterByPersonID(nconst = nconst))
96
-      .runWith(sink = sink)
85
+      .via(flow = filterByPersonIdFlow(nconst = nconst))
86
+      .runWith(sink = buildPersonSink(logger = logger))
97
       .andThen {
87
       .andThen {
98
-        case Success(value) => {
88
+        case Success(value) =>
99
           val elapsedTime: Long = (System.currentTimeMillis()-startTime)/1000
89
           val elapsedTime: Long = (System.currentTimeMillis()-startTime)/1000
100
           logger.info(s"$value: Successfully processed, elapsed time: $elapsedTime")
90
           logger.info(s"$value: Successfully processed, elapsed time: $elapsedTime")
101
-        }
102
         case Failure(exception) => logger.error(s"$exception: Fail")
91
         case Failure(exception) => logger.error(s"$exception: Fail")
103
       }
92
       }
104
   }
93
   }
105
 
94
 
106
-
95
+  override def getPersonByName(primaryName: String): Unit = {
96
+    val source: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics)
97
+    source
98
+      .via(
99
+        flow = filterByPersonNameFlow(personName = primaryName)
100
+      )
101
+      .runWith(sink = buildPersonSink(logger = logger))
102
+      .andThen {
103
+        case Failure(exception) => logger.info(s"$exception")
104
+        case Success(value) => logger.info(s"$value: Successufully processing")
105
+      }
106
+  }
107
 }
107
 }
108
 
108
 
109
 
109
 

Powered by TurnKey Linux.