Skip to content

Commit 05f4669

Browse files
Attributes (#22)
* Add vocab reference object * Add classes for composing RDF model * Add RDF model test utils and tests * Add binary array to model conversion API impl * Add NetCDF binary array factory method impl, tests * Add CLI impl, test, docs * Fix Java version in maven compiler plugin * Add prefix mapping concept on binary array * Add prefix mapping to model composition, tests * Add NetCDF impl of prefix mapping concept * Add tests, upgrade test format to NetCDF4 to support prefix group. * Add logback config on CLI to suppress debug logs * NetCDF4 considerations in tests * Add option to supply external prefixes for NetCDF to model conversion * Add external prefix / context parameter to CLI, add test * Update Java example with external prefixes. * Rename var * Improve error message wording * Add file container, refactor * Add file container to tests * Fix tests * Add NetCDF URI parser class * Replace BALD PrefixMapping concept with standard Jena PrefixMapping * Add attribute, attribute source concepts * Add NetCDF implementation of attribute concepts * Add root group and variable attributes to RDF model composition * Add attribute tests * Add separate class for handling NetCDF attributes, hide reserved attributes. * Fix existing tests * Add attributes CLI test * Changed test data to CDL format * Fix test * Remove NCML references * Fix Java version on demo * ADD name and subgroups to container concept * Enhance binary array converter to describe subgroups * Fix test consistency * Add prefix var support * Remove prefix group / var from graph * Replace BALD prefix mapping concept with Jena prefix mapping * Fix merge issue * Use common test method * Add prefix mapping validation * Refactor the RDF context impl as a decorator * Add prefix conflict validation * Fix reduce on empty list * Restore closeable interface * Add extension function for URI composition * Fix tests * Tidy up
1 parent 48717c5 commit 05f4669

File tree

26 files changed

+649
-54
lines changed

26 files changed

+649
-54
lines changed

binary-array-ld-cli/src/test/kotlin/net/bald/BinaryArrayConvertCliTest.kt

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ import bald.model.ModelVerifier
55
import bald.netcdf.CdlConverter.writeToNetCdf
66
import net.bald.vocab.BALD
77
import org.apache.jena.rdf.model.ModelFactory.createDefaultModel
8-
import org.apache.jena.vocabulary.DCTerms
9-
import org.apache.jena.vocabulary.RDF
10-
import org.apache.jena.vocabulary.SKOS
11-
import org.apache.jena.vocabulary.XSD
8+
import org.apache.jena.rdf.model.ResourceFactory.*
9+
import org.apache.jena.vocabulary.*
1210
import org.junit.jupiter.api.Test
1311
import org.junit.jupiter.api.assertThrows
1412
import java.io.File
@@ -101,6 +99,7 @@ class BinaryArrayConvertCliTest {
10199
statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/var1")) {
102100
statement(RDF.type, BALD.Resource)
103101
}
102+
statement(BALD.isPrefixedBy, createPlainLiteral("prefix_list"))
104103
}
105104
}
106105
}
@@ -184,6 +183,43 @@ class BinaryArrayConvertCliTest {
184183
statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/var1")) {
185184
statement(RDF.type, BALD.Resource)
186185
}
186+
statement(BALD.isPrefixedBy, createPlainLiteral("prefix_list"))
187+
}
188+
}
189+
}
190+
191+
@Test
192+
fun run_withAttributes_outputsAttributes() {
193+
val inputFile = writeToNetCdf("/netcdf/attributes.cdl")
194+
val outputFile = createTempFile()
195+
val contextFile = ContextReader.toFile("/jsonld/context.json")
196+
197+
run(
198+
"--uri", "http://test.binary-array-ld.net/example",
199+
"--context", contextFile.absolutePath,
200+
inputFile.absolutePath,
201+
outputFile.absolutePath
202+
)
203+
204+
val model = createDefaultModel().read(outputFile.toURI().toString(), "ttl")
205+
ModelVerifier(model).apply {
206+
prefix("bald", BALD.prefix)
207+
prefix("skos", SKOS.uri)
208+
prefix("dct", DCTerms.NS)
209+
resource("http://test.binary-array-ld.net/example/") {
210+
statement(DCTerms.publisher, createResource("${BALD.prefix}Organisation"))
211+
statement(createProperty("http://test.binary-array-ld.net/example/date"), createPlainLiteral("2020-10-29"))
212+
statement(RDF.type, BALD.Container)
213+
statement(SKOS.prefLabel, createPlainLiteral("Attributes metadata example"))
214+
statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/var0")) {
215+
statement(RDF.type, BALD.Array)
216+
statement(RDF.type, BALD.Resource)
217+
statement(SKOS.prefLabel, createPlainLiteral("Variable 0"))
218+
}
219+
statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/var1")) {
220+
statement(RDF.type, BALD.Resource)
221+
}
222+
statement(BALD.isPrefixedBy, createPlainLiteral("prefix_list"))
187223
}
188224
}
189225
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package net.bald
2+
3+
import org.apache.jena.rdf.model.RDFNode
4+
5+
/**
6+
* A description of a property of an [AttributeSource] entity.
7+
*/
8+
interface Attribute {
9+
/**
10+
* The URI which identifies the attribute, if it has one. Otherwise, null.
11+
*/
12+
val uri: String?
13+
14+
/**
15+
* The local name of the attribute.
16+
*/
17+
val name: String
18+
19+
/**
20+
* The values of the attribute, expressed as RDF resource or literal nodes.
21+
*/
22+
val values: List<RDFNode>
23+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package net.bald
2+
3+
/**
4+
* An entity which is described by its [Attribute]s.
5+
*/
6+
interface AttributeSource {
7+
/**
8+
* Obtain the list of attributes that describe this entity.
9+
* @param prefixMapping The prefix mapping to use to expand compact URIs.
10+
* @return The list of attributes.
11+
*/
12+
fun attributes(prefixMapping: org.apache.jena.shared.PrefixMapping): List<Attribute>
13+
}

binary-array-ld-lib/src/main/kotlin/net/bald/Container.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package net.bald
44
* Represents a container of resources.
55
* See https://www.opengis.net/def/binary-array-ld/Container
66
*/
7-
interface Container {
7+
interface Container: AttributeSource {
88
/**
99
* The local name of the container, if it has one.
1010
* The root container may have no name or an empty name.

binary-array-ld-lib/src/main/kotlin/net/bald/Var.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package net.bald
33
/**
44
* Represents a binary array variable.
55
*/
6-
interface Var {
6+
interface Var: AttributeSource {
77
/**
88
* The local name of the variable.
99
*/
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.bald.model
2+
3+
import net.bald.Attribute
4+
import org.apache.jena.rdf.model.Resource
5+
6+
open class ModelAttributeBuilder(
7+
private val resource: Resource
8+
) {
9+
open fun addAttribute(attr: Attribute) {
10+
val propUri = attr.uri ?: resource.withTrailingSlash() + attr.name
11+
val prop = resource.model.createProperty(propUri)
12+
attr.values.forEach { value ->
13+
resource.addProperty(prop, value)
14+
}
15+
}
16+
17+
open class Factory {
18+
open fun forResource(resource: Resource): ModelAttributeBuilder {
19+
return ModelAttributeBuilder(resource)
20+
}
21+
}
22+
}

binary-array-ld-lib/src/main/kotlin/net/bald/model/ModelBinaryArrayConverter.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import org.apache.jena.shared.PrefixMapping
1010
*/
1111
object ModelBinaryArrayConverter {
1212
private val modelFct = run {
13-
val varFct = ModelVarBuilder.Factory()
14-
val containerFct = ModelContainerBuilder.Factory(varFct)
13+
val attrFct = ModelAttributeBuilder.Factory()
14+
val varFct = ModelVarBuilder.Factory(attrFct)
15+
val containerFct = ModelContainerBuilder.Factory(varFct, attrFct)
1516
ModelBinaryArrayBuilder.Factory(containerFct)
1617
}
1718

binary-array-ld-lib/src/main/kotlin/net/bald/model/ModelContainerBuilder.kt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,45 @@
11
package net.bald.model
22

3+
import net.bald.AttributeSource
34
import net.bald.vocab.BALD
45
import net.bald.Container
56
import org.apache.jena.rdf.model.Resource
67

78
open class ModelContainerBuilder(
89
private val parent: Resource,
9-
private val varFct: ModelVarBuilder.Factory
10+
private val varFct: ModelVarBuilder.Factory,
11+
private val attrFct: ModelAttributeBuilder.Factory
1012
) {
1113
open fun addContainer(container: Container) {
12-
val containerUri = containerUri(container)
14+
val containerUri = parent.withTrailingSlash() + (container.name ?: "")
1315
val containerRes = parent.model.createResource(containerUri, BALD.Container)
14-
buildSubgroups(container, containerRes)
15-
buildVars(container, containerRes)
16+
addSubContainers(container, containerRes)
17+
addVars(container, containerRes)
18+
addAttributes(container, containerRes)
1619
parent.addProperty(BALD.contains, containerRes)
1720
}
1821

19-
private fun containerUri(container: Container): String {
20-
val parentUri = parent.uri
21-
val prefix = if (parentUri.endsWith('/')) parentUri else "$parentUri/"
22-
return prefix + (container.name ?: "")
22+
private fun addSubContainers(container: Container, containerRes: Resource) {
23+
val builder = ModelContainerBuilder(containerRes, varFct, attrFct)
24+
container.subContainers().forEach(builder::addContainer)
2325
}
2426

25-
private fun buildSubgroups(container: Container, containerRes: Resource) {
26-
val builder = ModelContainerBuilder(containerRes, varFct)
27-
container.subContainers().forEach(builder::addContainer)
27+
private fun addVars(container: Container, containerRes: Resource) {
28+
val builder = varFct.forContainer(containerRes)
29+
container.vars().forEach(builder::addVar)
2830
}
2931

30-
private fun buildVars(container: Container, containerRes: Resource) {
31-
varFct.forContainer(containerRes).apply {
32-
container.vars().forEach(::addVar)
33-
}
32+
private fun addAttributes(source: AttributeSource, resource: Resource) {
33+
val builder = attrFct.forResource(resource)
34+
source.attributes(resource.model).forEach(builder::addAttribute)
3435
}
3536

3637
open class Factory(
37-
private val varFct: ModelVarBuilder.Factory
38+
private val varFct: ModelVarBuilder.Factory,
39+
private val attrFct: ModelAttributeBuilder.Factory
3840
) {
3941
open fun forParent(parent: Resource): ModelContainerBuilder {
40-
return ModelContainerBuilder(parent, varFct)
42+
return ModelContainerBuilder(parent, varFct, attrFct)
4143
}
4244
}
4345
}
Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
package net.bald.model
22

3+
import net.bald.AttributeSource
34
import net.bald.Var
45
import net.bald.vocab.BALD
56
import org.apache.jena.rdf.model.Resource
6-
import org.apache.jena.vocabulary.RDF
77

88
open class ModelVarBuilder(
9-
private val container: Resource
9+
private val container: Resource,
10+
private val attrFct: ModelAttributeBuilder.Factory
1011
) {
1112
open fun addVar(v: Var) {
12-
val varUri = varUri(v)
13+
val varUri = container.withTrailingSlash() + v.name
1314
val vRes = container.model.createResource(varUri, BALD.Resource)
1415
container.addProperty(BALD.contains, vRes)
16+
addAttributes(v, vRes)
1517
}
1618

17-
private fun varUri(v: Var): String {
18-
val containerUri = container.uri
19-
val prefix = if (containerUri.endsWith('/')) containerUri else "$containerUri/"
20-
return prefix + v.name
19+
private fun addAttributes(source: AttributeSource, resource: Resource) {
20+
val builder = attrFct.forResource(resource)
21+
source.attributes(resource.model).forEach(builder::addAttribute)
2122
}
2223

23-
open class Factory {
24+
open class Factory(
25+
private val attrFct: ModelAttributeBuilder.Factory
26+
) {
2427
open fun forContainer(container: Resource): ModelVarBuilder {
25-
return ModelVarBuilder(container)
28+
return ModelVarBuilder(container, attrFct)
2629
}
2730
}
2831
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package net.bald.model
2+
3+
import org.apache.jena.rdf.model.Resource
4+
5+
fun Resource.withTrailingSlash(): String {
6+
return if (uri.endsWith('/')) uri else "$uri/"
7+
}

0 commit comments

Comments
 (0)