Skip to content

Commit

Permalink
Merge pull request #59 from Yummy-Yums/master
Browse files Browse the repository at this point in the history
feat: Add zio-schema-quickstart
  • Loading branch information
khajavi authored Sep 29, 2024
2 parents 275a39e + 268141e commit bc1cf66
Show file tree
Hide file tree
Showing 9 changed files with 412 additions and 1 deletion.
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,[email protected],2021-10-29
Michela Rizzo-Traetta,[email protected],1955-07-05
Gianpaolo Nibali,[email protected],1995-06-08
Orlando Gradenigo,[email protected],1970-09-07
Pasqual Disdero-Verri,[email protected],1929-11-25
Alphons Amato,[email protected],1963-04-30
Annetta Balbi,[email protected],1986-09-23
Sig. Ricciotti Gigli,[email protected],1930-03-16
Isabella Petrocelli,[email protected],1972-09-27
Carolina Veneziano-Giovine,[email protected],1916-03-27
Melina Respighi,[email protected],2013-11-04
Dott. Mario Crespi,[email protected],1920-02-23
Sig.ra Annunziata Sforza,[email protected],1952-08-27
Dott. Greca Paganini,[email protected],1995-08-10
Virginia Draghi,[email protected],1960-06-30
Ivo Magrassi-Ginese,[email protected],1961-07-13
Ferdinando Prodi,[email protected],2019-02-17
Lucrezia Lucciano,[email protected],1968-07-20
Germana Favata,[email protected],1983-10-12
Gioffre Sagnelli,[email protected],2010-02-05
Elladio Garibaldi-Iannuzzi,[email protected],2002-06-02
Leopoldo Donarelli-Pagliaro,[email protected],1934-08-31
Dott. Cirillo Caetani,[email protected],2001-08-27
Rosalia Roncalli-Gangemi,[email protected],1986-06-15
Rembrandt Briccialdi,[email protected],1965-07-18
Gianmarco Fanucci,[email protected],1962-09-12
Francesca Callegari,[email protected],1917-09-09
Sig.ra Daria Nordio,[email protected],1911-01-24
Sig.ra Vanessa Cremonesi,[email protected],2008-05-20
Dott. Durante Treccani,[email protected],1933-07-12
Adelasia Satriani,[email protected],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

0 comments on commit bc1cf66

Please sign in to comment.