Skip to content

Commit 112681d

Browse files
committed
Add list-schemas for the embedded repo (close #212)
1 parent 6e68bb6 commit 112681d

File tree

7 files changed

+123
-5
lines changed

7 files changed

+123
-5
lines changed

modules/core/src/main/scala/com.snowplowanalytics.iglu/client/resolver/registries/RegistryLookup.scala

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ object RegistryLookup {
7979
implicit class LookupOps(val repositoryRef: Registry) extends AnyVal with Serializable {
8080
def lookupSchema[F[_]: RegistryLookup](schemaKey: SchemaKey): F[Either[RegistryError, Json]] =
8181
RegistryLookup[F].lookup(repositoryRef, schemaKey)
82+
83+
def list[F[_]: RegistryLookup](
84+
vendor: String,
85+
name: String,
86+
model: Int
87+
): F[Either[RegistryError, SchemaList]] =
88+
RegistryLookup[F].list(repositoryRef, vendor: String, name: String, model: Int)
8289
}
8390

8491
implicit def ioLookupInstance[F[_]](implicit F: Sync[F]): RegistryLookup[F] =
@@ -98,7 +105,10 @@ object RegistryLookup {
98105
): F[Either[RegistryError, SchemaList]] =
99106
registry match {
100107
case Registry.Http(_, connection) => httpList(connection, vendor, name, model)
101-
case _ => F.pure(RegistryError.NotFound.asLeft)
108+
case Registry.Embedded(_, base) =>
109+
val path = toSubpath(base, vendor, name)
110+
Sync[F].delay(Utils.unsafeEmbeddedList(path, model))
111+
case _ => F.pure(RegistryError.NotFound.asLeft)
102112
}
103113
}
104114

@@ -128,6 +138,9 @@ object RegistryLookup {
128138
case Registry.Http(_, connection) =>
129139
val subpath = toSubpath(connection.uri.toString, vendor, name, model)
130140
Utils.stringToUri(subpath).flatMap(Utils.unsafeHttpList(_, connection.apikey))
141+
case Registry.Embedded(_, base) =>
142+
val path = toSubpath(base, vendor, name)
143+
Utils.unsafeEmbeddedList(path, model)
131144
case _ =>
132145
RegistryError.NotFound.asLeft
133146
}
@@ -151,6 +164,13 @@ object RegistryLookup {
151164
): String =
152165
s"${prefix.stripSuffix("/")}/schemas/$vendor/$name/jsonschema/$model"
153166

167+
private def toSubpath(
168+
prefix: String,
169+
vendor: String,
170+
name: String
171+
): String =
172+
s"${prefix.stripSuffix("/")}/schemas/$vendor/$name/jsonschema"
173+
154174
/**
155175
* Retrieves an Iglu Schema from the Embedded Iglu Repo as a JSON
156176
*

modules/core/src/main/scala/com.snowplowanalytics.iglu/client/resolver/registries/Utils.scala

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ package com.snowplowanalytics.iglu.client
1414
package resolver.registries
1515

1616
// Java
17-
import java.io.InputStream
17+
import com.snowplowanalytics.iglu.core.{SchemaKey, SchemaVer}
18+
19+
import java.io.{File, InputStream}
1820
import java.net.URI
1921
import java.net.http.HttpResponse.BodyHandlers
2022
import java.net.http.{HttpClient, HttpRequest, HttpResponse}
2123
import java.time.Duration
24+
import scala.util.matching.Regex
2225

2326
// Scala
2427
import scala.io.Source
@@ -29,6 +32,7 @@ import cats.effect.Sync
2932
import cats.syntax.either._
3033
import cats.syntax.option._
3134
import cats.syntax.show._
35+
import cats.syntax.traverse._
3236

3337
// circe
3438
import io.circe.parser.parse
@@ -72,6 +76,61 @@ private[registries] object Utils {
7276
repoFailure(e).asLeft
7377
}
7478

79+
def unsafeEmbeddedList(path: String, modelMatch: Int): Either[RegistryError, SchemaList] =
80+
try {
81+
val d =
82+
new File(
83+
getClass.getResource(path).getPath
84+
) // this will throw NPE for missing entry in embedded repos
85+
val schemaFileRegex: Regex = (".*/schemas/?" + // path to file
86+
"([a-zA-Z0-9-_.]+)/" + // Vendor
87+
"([a-zA-Z0-9-_]+)/" + // Name
88+
"([a-zA-Z0-9-_]+)/" + // Format
89+
"([1-9][0-9]*)-(\\d+)-(\\d+)$").r // MODEL, REVISION and ADDITION
90+
91+
def getFolderContent(d: File): List[String] = {
92+
d.listFiles
93+
.filter(_.isFile)
94+
.toList
95+
.filter(_.getName.startsWith(s"${modelMatch.toString}-"))
96+
.map(_.getAbsolutePath)
97+
}
98+
99+
val content =
100+
if (d.exists & d.isDirectory)
101+
getFolderContent(d)
102+
else
103+
List.empty[String]
104+
105+
content
106+
.traverse {
107+
case schemaFileRegex(vendor, name, format, model, revision, addition)
108+
if model == modelMatch.toString =>
109+
SchemaKey(
110+
vendor = vendor,
111+
name = name,
112+
format = format,
113+
version = SchemaVer
114+
.Full(model = model.toInt, revision = revision.toInt, addition = addition.toInt)
115+
).asRight
116+
case f => RegistryError.RepoFailure(s"Corrupted schema file name at $f").asLeft
117+
}
118+
.map(_.sortBy(_.version))
119+
.flatMap(s =>
120+
if (s.isEmpty)
121+
RegistryError.NotFound.asLeft
122+
else
123+
s.asRight
124+
)
125+
.map(SchemaList.apply)
126+
} catch {
127+
case NonFatal(e) =>
128+
e match {
129+
case _: NullPointerException => RegistryError.NotFound.asLeft
130+
case _ => repoFailure(e).asLeft
131+
}
132+
}
133+
75134
/** Not-RT analog of [[RegistryLookup.embeddedLookup]] */
76135
def unsafeEmbeddedLookup(path: String): Either[RegistryError, Json] =
77136
try {
@@ -84,7 +143,10 @@ private[registries] object Utils {
84143
result
85144
} catch {
86145
case NonFatal(e) =>
87-
repoFailure(e).asLeft
146+
e match {
147+
case _: NullPointerException => RegistryError.NotFound.asLeft
148+
case _ => repoFailure(e).asLeft
149+
}
88150
}
89151

90152
/** Non-RT analog of [[RegistryLookup.httpList]] */
@@ -156,6 +218,7 @@ private[registries] object Utils {
156218
RegistryError.RepoFailure(failure.show)
157219

158220
private[resolver] def repoFailure(failure: Throwable): RegistryError =
159-
RegistryError.RepoFailure(failure.getMessage)
160-
221+
RegistryError.RepoFailure(
222+
if (failure.getMessage != null) failure.getMessage else "Unhandled error"
223+
)
161224
}

modules/core/src/test/resources/iglu-test-embedded/schemas/com.snowplowanalytics.iglu-test/test-embedded-list/jsonschema/1-0-0

Whitespace-only changes.

modules/core/src/test/resources/iglu-test-embedded/schemas/com.snowplowanalytics.iglu-test/test-embedded-list/jsonschema/1-0-1

Whitespace-only changes.

modules/core/src/test/resources/iglu-test-embedded/schemas/com.snowplowanalytics.iglu-test/test-embedded-list/jsonschema/1-2-0

Whitespace-only changes.

modules/core/src/test/resources/iglu-test-embedded/schemas/com.snowplowanalytics.iglu-test/test-embedded-list/jsonschema/1-2-11

Whitespace-only changes.

modules/core/src/test/scala/com.snowplowanalytics.iglu.client/resolver/registries/EmbeddedSpec.scala

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package com.snowplowanalytics.iglu.client.resolver.registries
1515
// Cats
1616
import cats.effect.IO
1717
import cats.effect.testing.specs2.CatsEffect
18+
import com.snowplowanalytics.iglu.core.SchemaList
1819

1920
// circe
2021
import io.circe.literal._
@@ -38,6 +39,7 @@ class EmbeddedSpec extends Specification with CatsEffect {
3839
retrieving an existent JSON Schema from an embedded RepositoryRef should work $e3
3940
requesting a non-existent JSON Schema from an embedded RepositoryRef should return None $e4
4041
requesting a corrupted JSON Schema from an embedded RepositoryRef should return an appropriate Failure $e5
42+
Schema list should work for embedded repo $e6
4143
"""
4244

4345
val AcmeConfig =
@@ -119,4 +121,37 @@ class EmbeddedSpec extends Specification with CatsEffect {
119121
.map(result => result must beLeft)
120122
}
121123

124+
def e6 = {
125+
val schemaList = SchemaList(
126+
List(
127+
SchemaKey(
128+
"com.snowplowanalytics.iglu-test",
129+
"test-embedded-list",
130+
"jsonschema",
131+
SchemaVer.Full(1, 0, 0)
132+
),
133+
SchemaKey(
134+
"com.snowplowanalytics.iglu-test",
135+
"test-embedded-list",
136+
"jsonschema",
137+
SchemaVer.Full(1, 0, 1)
138+
),
139+
SchemaKey(
140+
"com.snowplowanalytics.iglu-test",
141+
"test-embedded-list",
142+
"jsonschema",
143+
SchemaVer.Full(1, 2, 0)
144+
),
145+
SchemaKey(
146+
"com.snowplowanalytics.iglu-test",
147+
"test-embedded-list",
148+
"jsonschema",
149+
SchemaVer.Full(1, 2, 11)
150+
)
151+
)
152+
)
153+
SpecHelpers.EmbeddedTest
154+
.list[IO]("com.snowplowanalytics.iglu-test", "test-embedded-list", 1)
155+
.map(result => result must beRight(schemaList))
156+
}
122157
}

0 commit comments

Comments
 (0)