Skip to content

Commit

Permalink
fixed comments on PR
Browse files Browse the repository at this point in the history
  • Loading branch information
Yummy-Yums committed Sep 18, 2024
1 parent 9a8e69f commit a4c26c6
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 89 deletions.
Original file line number Diff line number Diff line change
@@ -1,46 +1,15 @@
package dev.zio.quickstart

import zio._
import zio.schema._
import zio.schema.annotation.validate
import zio.schema.validation.Validation
import zio.stream.ZStream

// one can choose the detailed way of validation or use annotations

case class Person(
name: String,
case class Person(name: String,
@validate(Validation.greaterThan(18))
age: Int)

object Person {
implicit val schema : Schema[Person] = DeriveSchema.gen
}


// one can choose the detailed way of validation or use annotations

//case class Person(name: String, age: Int)

// object Person {
// implicit val schema: Schema[Person] = CaseClass2(
// id0 = TypeId.fromTypeName("Person"),
// field01 = Schema.Field(
// name0 = "name",
// schema0 = Schema[String],
// validation0 = Validation.minLength(15),
// get0 = (p: Person) => p.name,
// set0 = { (p: Person, s: String) => p.copy(name = s) }
// ),
// field02 = Schema.Field(
// name0 = "age",
// schema0 = Schema[Int],
// validation0 = Validation.greaterThan(18),
// get0 = (p: Person) => p.age,
// set0 = { (p: Person, age: Int) => p.copy(age = age) }
// ),
// construct0 = (name, age) => Person(name, age),
// )

// }

implicit val schema: Schema[Person] = DeriveSchema.gen
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dev.zio.quickstart

import zio._
import zio.schema.Schema.CaseClass1
import zio.schema._
import zio.schema.annotation.validate
import zio.schema.validation._
import zio.stream.ZStream

case class PersonWithEmail(email: String)

object PersonWithEmail {

val localPart = Regex.letter.atLeast(3)
val tld = (Regex.literal("org") | Regex.literal("net") | Regex.literal("com")) // Matches top-level domains (2 or more letters)
val regexValidator = localPart ~ Regex.digit.atLeast(1) ~ Regex.literal("@") ~ Regex.letter.atLeast(3) ~ Regex.literal(".") ~ tld

implicit val schema: Schema[PersonWithEmail] = CaseClass1(
id0 = TypeId.fromTypeName("PersonWithEmail"),
field0 = Schema.Field(
name0 = "email",
schema0 = Schema[String],
validation0 = Validation.regex(regexValidator),
get0 = (p: PersonWithEmail) => p.email,
set0 = { (p: PersonWithEmail, s: String) => p.copy(email = s) }
),
defaultConstruct0 = email => PersonWithEmail(email),
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,46 @@ import zio.schema

object PrepareDataUtils {

val homeDirectory = java.lang.System.getProperty("user.home")
val fileName = homeDirectory + "/Desktop/centre/scala/zio-quickstarts/zio-quickstart-schema/src/main/resources/incoming_data.txt"

val resourceName = "incoming_data.txt"

def openFile(name: String): IO[IOException, BufferedSource] =
ZIO.attemptBlockingIO(Source.fromFile(name))
ZIO.attemptBlockingIO(Source.fromResource(name))

def closeFile(bufferedSourceFile: BufferedSource): ZIO[Any, Nothing, Unit] =
ZIO.succeedBlocking(bufferedSourceFile.close())

def withFile[A](name: String)(useFile: BufferedSource => Task[A]): Task[A] =
ZIO.acquireReleaseWith(openFile(name))(closeFile)(useFile)

def prepareData(bufferedSourceFile: BufferedSource): List[Person] = {
def getNameAndAgeOfPerson(bufferedSourceFile: BufferedSource): List[Person] = {

def getPerson: Iterator[Person] = for {
line <- bufferedSourceFile.getLines().filter(incomingString => !incomingString.contains("Name"))
arr = line.split(",")
dob = arr.reverse.head
name = arr.head
age = getAge(dob)
person = Person(name, age)
line <- bufferedSourceFile.getLines().filter(incomingString => !incomingString.contains("Name"))
list = line.split(",")
dob = list.reverse.head
name = list.head
age = getAge(dob)
person = Person(name, age)
} yield person

getPerson.toList

}

def getEmailOfPerson(bufferedSourceFile: BufferedSource): List[PersonWithEmail] = {

def getPersonWithEmail: Iterator[PersonWithEmail] = for {
line <- bufferedSourceFile.getLines().filter(incomingString => !incomingString.contains("Name"))
arr = line.split(",")
emaii = arr(1)


personWithEmail = PersonWithEmail(emaii)
} yield personWithEmail

getPersonWithEmail.toList

}

def getAge(dob: String): Int = {
val currYear = LocalDate.now().getYear
currYear - LocalDate.parse(dob).getYear
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object SchemaValidator extends ZIOAppDefault {

import PrepareDataUtils._

val res = withFile(fileName)(file => ZIO.attempt(prepareData(file)))
val res = withFile(resourceName)(file => ZIO.attempt(getNameAndAgeOfPerson(file)))

val runStream = ZStream
.fromIterableZIO(res)
Expand All @@ -23,21 +23,21 @@ object SchemaValidator extends ZIOAppDefault {

}

val b = runStream
val listOfValidPersons = runStream
.runFold((List.empty[Person], List.empty[String])) {
case ((valid, invalid), Right(person)) => (valid :+ person, invalid) // Collect valid persons
case ((valid, invalid), Left(error)) => (valid, invalid :+ error.toString) // Collect errors
}


def run=
def run=
program


val program =
for {
count <- runStream.runFold(0)((accum, _) => accum + 1)
c <- b
c <- listOfValidPersons
_ <- Console.printLine(s"Total count: ${c._2.size}")
} yield ()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import zio.{Chunk, ZIO}


object StreamWithSchemaValidation {
private val res = withFile(fileName)(file => ZIO.attempt(prepareData(file)))
private val listOfNameAndAgeOfPersons = withFile(resourceName)(file => ZIO.attempt(getNameAndAgeOfPerson(file)))
private val listOfEmailOfPersons = withFile(resourceName)(file => ZIO.attempt(getEmailOfPerson(file)))

private val runStream = ZStream
.fromIterableZIO(res)
private val streamOfPersonWithNameAndAge = ZStream
.fromIterableZIO(listOfNameAndAgeOfPersons)
.map{ person =>
val validatedRecord = Person.schema.validate(person)

Expand All @@ -20,8 +21,19 @@ object StreamWithSchemaValidation {
}
}

private val streamOfPersonWithEmail = ZStream
.fromIterableZIO(listOfEmailOfPersons)
.map{ person =>
val validatedRecord = PersonWithEmail.schema.validate(person)

validatedRecord match {
case Chunk() => Right(person)
case Chunk(_) | Chunk(_,_) => Left(person)
}
}

def getTotalNumberofPeopleAbove18: ZIO[Any, Throwable, Int] =
runStream
streamOfPersonWithNameAndAge
.runFold(0)((acc, x) =>
x match {
case Right(_) => acc + 1
Expand All @@ -30,7 +42,7 @@ object StreamWithSchemaValidation {
)

def getTotalNumberofRecords: ZIO[Any, Throwable, Int] =
runStream
streamOfPersonWithNameAndAge
.runCount
.map(_.toInt)

Expand All @@ -40,27 +52,53 @@ object StreamWithSchemaValidation {
totalNumber <- getTotalNumberofRecords
} yield totalNumber - peopleAbove18


def getFirstPersonAbove18: ZIO[Any, Throwable, List[Person]] =
runStream
streamOfPersonWithNameAndAge
.runFold(List.empty[Person]){
case (resList, Right(person)) => resList :+ person
case (resList, Left(_)) => resList
}

def getFirstPersonbelow18: ZIO[Any, Throwable, List[Person]] =
runStream
def getFirstPersonBelow18: ZIO[Any, Throwable, List[Person]] =
streamOfPersonWithNameAndAge
.runFold(List.empty[Person]){
case (resList, Left(person)) => resList :+ person
case (resList, Right(_)) => resList
}

}
def validEmailsTotal: ZIO[Any, Throwable, Int] =
streamOfPersonWithEmail
.runFold(0)((accum, res) => {
res match {
case Left(_) => accum
case Right(_) => accum + 1
}
})

def invalidEmailsTotal: ZIO[Any, Throwable, Int] = {
for {
res <- streamOfPersonWithEmail.runCollect
total = res.size
validEmailsTotal <- validEmailsTotal
} yield total - validEmailsTotal
}

def listOfValidEmail = {
for {
list <- streamOfPersonWithEmail.runFold(List.empty[String])((list, res) => {
res match {
case Left(_) => list
case Right(elem) => list :+ elem.email
}
})
} yield list
}

object SchemaValidatorSpec extends ZIOSpecDefault {
}

object Answers {

object ExamplesSpec extends ZIOSpecDefault {
object PersonsData {
val firstFiveNamesOfPeopleAbove18: List[Person] = List(
Person("Michela Rizzo-Traetta", 69),
Person("Gianpaolo Nibali", 29),
Expand All @@ -77,34 +115,73 @@ object SchemaValidatorSpec extends ZIOSpecDefault {
Person("Sig.ra Vanessa Cremonesi", 16)
)

val listOfValidEmails = List(
"annamaria26@example.org",
"rosaria88@example.com",
"stefano58@example.net",
"federica81@example.org",
"francesca93@example.org",
"giulio81@example.net",
"eleanora72@example.org",
"imelda80@example.net",
"virginia96@example.net"
)

}
def spec: Spec[Any, Throwable] = suite("ExampleSpec")(
test("Get total number of people"){
assertZIO(StreamWithSchemaValidation.getTotalNumberofRecords)(Assertion.equalTo(31))
},
test("Get people above the age of 18"){
for {
count <- StreamWithSchemaValidation.getTotalNumberofPeopleAbove18
} yield assertTrue(count == 26)
},
test("First name in the stream"){
for {
persons <- StreamWithSchemaValidation.getFirstPersonAbove18
} yield assertTrue(persons.head == Answers.firstFiveNamesOfPeopleAbove18.head)
},
test("First five names of persons above 18"){
for {
persons <- StreamWithSchemaValidation.getFirstPersonAbove18
} yield assertTrue(persons.take(5) == Answers.firstFiveNamesOfPeopleAbove18)
},
test("First name of person below 18 is Rosalia Marina"){
for {
persons <- StreamWithSchemaValidation.getFirstPersonbelow18
nameOfFirstPerson = persons.head.name
mustBeRosalia = Answers.firstFiveNamesOfPeoplebelow18.head.name

} yield assertTrue(nameOfFirstPerson == mustBeRosalia)
}

def spec: Spec[Any, Throwable] = suite("ExampleSpec")(
test("Total number of people is 31"){
assertZIO(StreamWithSchemaValidation.getTotalNumberofRecords)(Assertion.equalTo(31))
},
test("Number of persons above the age 18 is 26"){
for {
count <- StreamWithSchemaValidation.getTotalNumberofPeopleAbove18
} yield assertTrue(count == 26)
},
test("Number of persons below the age 18 is 5"){
for {
count <- StreamWithSchemaValidation.getPeopleBelow18
} yield assertTrue(count == 5)
},
test("First name in the stream of persons Above 18 is Michela Rizzo-Traetta"){
for {
persons <- StreamWithSchemaValidation.getFirstPersonAbove18
} yield assertTrue(persons.head == PersonsData.firstFiveNamesOfPeopleAbove18.head)
},
test("First five names of persons above 18"){
for {
persons <- StreamWithSchemaValidation.getFirstPersonAbove18
} yield assertTrue(persons.take(5) == PersonsData.firstFiveNamesOfPeopleAbove18)
},
test("First name of person below 18 is Rosalia Marina"){
for {
persons <- StreamWithSchemaValidation.getFirstPersonBelow18
nameOfFirstPerson = persons.head.name
mustBeRosalia = PersonsData.firstFiveNamesOfPeoplebelow18.head.name

} yield assertTrue(nameOfFirstPerson == mustBeRosalia)
},
test("Total number of valid emails ( valid emails must have numbers before the '@'"){
for {
total <- StreamWithSchemaValidation.validEmailsTotal
} yield assertTrue(total == 9)
},
test("Total number of invalid emails"){
for {
total <- StreamWithSchemaValidation.invalidEmailsTotal
} yield assertTrue(total == 22)
},
test("first valid email is annamaria26@example.org"){
for {
emails <- StreamWithSchemaValidation.listOfValidEmail
firstEmail = emails.head
} yield assertTrue(firstEmail == PersonsData.listOfValidEmails.head)
},
test("valid emails list must match the one provided"){
for {
emails <- StreamWithSchemaValidation.listOfValidEmail

} yield assertTrue(emails == PersonsData.listOfValidEmails, emails.size == 9)
}
)
}

0 comments on commit a4c26c6

Please sign in to comment.