Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add zio-schema-quickstart #59

Merged
merged 4 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ $ sbt run
- [ZIO STM](zio-quickstart-stm) - many thanks to [@jorge-vasquez-2301](https://github.com/jorge-vasquez-2301) and his [article](https://scalac.io/blog/how-to-write-a-completely-lock-free-concurrent-lru-cache-with-zio-stm/) for this example
- [ZIO SQL](zio-quickstart-sql)
- [ZIO Streams](zio-quickstart-streams)
- [ZIO Schema](zio-quickstart-schema)
4 changes: 3 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ lazy val root =
`zio-quickstart-cache`,
`zio-quickstart-prelude`,
`zio-quickstart-stm`,
`zio-quickstart-sql`
`zio-quickstart-sql`,
`zio-quickstart-schema`
)
.settings(
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
Expand All @@ -62,3 +63,4 @@ lazy val `zio-quickstart-cache` = project
lazy val `zio-quickstart-prelude` = project
lazy val `zio-quickstart-stm` = project
lazy val `zio-quickstart-sql` = project
lazy val `zio-quickstart-schema` = project
15 changes: 15 additions & 0 deletions zio-quickstart-schema/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
scalaVersion := "2.13.12"
organization := "dev.zio"
name := "zio-quickstart-schema"

libraryDependencies ++= Seq(
"dev.zio" %% "zio-schema" % "1.4.1",
"dev.zio" %% "zio-schema-zio-test" % "1.4.1",
"dev.zio" %% "zio-schema-derivation" % "1.4.1",
"org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided",
"dev.zio" %% "zio-test" % "2.1.9" % Test,
"dev.zio" %% "zio-test-sbt" % "2.1.9" % Test,
"dev.zio" %% "zio-test-magnolia" % "2.1.9" % Test
)

resolvers ++= Resolver.sonatypeOssRepos("snapshots")
32 changes: 32 additions & 0 deletions zio-quickstart-schema/src/main/resources/incoming_data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Name,Email,Date of birth
Rosalia Marini,annamaria26@example.org,2021-10-29
Michela Rizzo-Traetta,pisaroniantonietta@example.com,1955-07-05
Gianpaolo Nibali,donatogagliardi@example.com,1995-06-08
Orlando Gradenigo,rcatenazzi@example.org,1970-09-07
Pasqual Disdero-Verri,rosaria88@example.com,1929-11-25
Alphons Amato,stefano58@example.net,1963-04-30
Annetta Balbi,federica81@example.org,1986-09-23
Sig. Ricciotti Gigli,bianchiflavia@example.net,1930-03-16
Isabella Petrocelli,francesca93@example.org,1972-09-27
Carolina Veneziano-Giovine,giulio81@example.net,1916-03-27
Melina Respighi,ippaziodisdero@example.org,2013-11-04
Dott. Mario Crespi,giampieroravaglioli@example.com,1920-02-23
Sig.ra Annunziata Sforza,ftomei@example.org,1952-08-27
Dott. Greca Paganini,eleanora72@example.org,1995-08-10
Virginia Draghi,krinaldi@example.org,1960-06-30
Ivo Magrassi-Ginese,qvarano@example.com,1961-07-13
Ferdinando Prodi,ybompiani@example.org,2019-02-17
Lucrezia Lucciano,tcarullo@example.com,1968-07-20
Germana Favata,marazzililiana@example.org,1983-10-12
Gioffre Sagnelli,ucontarini@example.org,2010-02-05
Elladio Garibaldi-Iannuzzi,farnesevirgilio@example.net,2002-06-02
Leopoldo Donarelli-Pagliaro,bettinaparri@example.net,1934-08-31
Dott. Cirillo Caetani,antoniorosselli@example.net,2001-08-27
Rosalia Roncalli-Gangemi,turatieugenia@example.com,1986-06-15
Rembrandt Briccialdi,imelda80@example.net,1965-07-18
Gianmarco Fanucci,ermenegildoprati@example.net,1962-09-12
Francesca Callegari,ferruccicostanzo@example.org,1917-09-09
Sig.ra Daria Nordio,donatozarlino@example.org,1911-01-24
Sig.ra Vanessa Cremonesi,virginia96@example.net,2008-05-20
Dott. Durante Treccani,borghesegionata@example.com,1933-07-12
Adelasia Satriani,rubertoarnaldo@example.com,1970-07-29
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.zio.quickstart

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

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

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

object Person {
implicit val schema: Schema[Person] = DeriveSchema.gen
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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
@@ -0,0 +1,64 @@
package dev.zio.quickstart

import zio._

import java.time.LocalDate
import java.io.{File, FileNotFoundException, IOException}
import scala.io.{BufferedSource, Source}
import zio.schema

object PrepareDataUtils {

val resourceName = "incoming_data.txt"

def openFile(name: String): IO[IOException, BufferedSource] =
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 getNameAndAgeOfPerson(
bufferedSourceFile: BufferedSource
): List[Person] = {

def getPerson: Iterator[Person] = for {
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
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.zio.quickstart

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

object SchemaValidator extends ZIOAppDefault {

import PrepareDataUtils._

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

val runStream = ZStream
.fromIterableZIO(res)
.map { person =>
Person.schema.validate(person) match {
case Chunk() => Right(person)
case Chunk(_) | Chunk(_, _) => Left(person)
}

}

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 =
program

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

}
Loading
Loading