diff --git a/binary-array-ld-cli/src/main/resources/logback.xml b/binary-array-ld-cli/src/main/resources/logback.xml
new file mode 100644
index 0000000..4bd2e37
--- /dev/null
+++ b/binary-array-ld-cli/src/main/resources/logback.xml
@@ -0,0 +1,11 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-array-ld-cli/src/test/kotlin/net/bald/BinaryArrayConvertCliTest.kt b/binary-array-ld-cli/src/test/kotlin/net/bald/BinaryArrayConvertCliTest.kt
index adb5491..dc35c1f 100644
--- a/binary-array-ld-cli/src/test/kotlin/net/bald/BinaryArrayConvertCliTest.kt
+++ b/binary-array-ld-cli/src/test/kotlin/net/bald/BinaryArrayConvertCliTest.kt
@@ -1,16 +1,23 @@
package net.bald
import bald.model.ModelVerifier
-import bald.netcdf.CdlConverter.convertToNetCdf
+import bald.netcdf.CdlConverter.writeToNetCdf
import net.bald.vocab.BALD
import org.apache.jena.rdf.model.ModelFactory.createDefaultModel
import org.apache.jena.vocabulary.RDF
+import org.apache.jena.vocabulary.SKOS
+import org.junit.Assume
+import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
+import ucar.nc2.jni.netcdf.Nc4Iosp
import kotlin.test.assertEquals
/**
* Integration test for [BinaryArrayConvertCli].
+ *
+ * Test resources are stored in CDL format and converted to temporary NetCDF 4 files.
+ * In order to write the NetCDF 4 files, the ncgen command line utility must be available.
*/
class BinaryArrayConvertCliTest {
private fun run(vararg args: String) {
@@ -32,7 +39,7 @@ class BinaryArrayConvertCliTest {
@Test
fun run_withoutUri_outputsToFileWithInputFileUri() {
- val inputFile = convertToNetCdf("/netcdf/identity.cdl")
+ val inputFile = writeToNetCdf("/netcdf/identity.cdl")
val inputFileUri = inputFile.toPath().toUri().toString()
val outputFile = createTempFile()
run(inputFile.absolutePath, outputFile.absolutePath)
@@ -56,12 +63,33 @@ class BinaryArrayConvertCliTest {
@Test
fun run_withUri_withOutputFile_outputsToFile() {
- val inputFile = convertToNetCdf("/netcdf/identity.cdl")
+ val inputFile = writeToNetCdf("/netcdf/identity.cdl")
val outputFile = createTempFile()
run("--uri", "http://test.binary-array-ld.net/example", inputFile.absolutePath, outputFile.absolutePath)
val model = createDefaultModel().read(outputFile.toURI().toString(), "ttl")
ModelVerifier(model).apply {
+ resource("http://test.binary-array-ld.net/example/") {
+ statement(RDF.type, BALD.Container)
+ statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/var0")) {
+ statement(RDF.type, BALD.Resource)
+ }
+ statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/var1")) {
+ statement(RDF.type, BALD.Resource)
+ }
+ }
+ }
+ }
+
+ private fun run_withPrefixMapping_outputsPrefixMapping(cdlLoc: String) {
+ val inputFile = writeToNetCdf(cdlLoc)
+ val outputFile = createTempFile()
+ run("--uri", "http://test.binary-array-ld.net/example", inputFile.absolutePath, outputFile.absolutePath)
+
+ val model = createDefaultModel().read(outputFile.toURI().toString(), "ttl")
+ ModelVerifier(model).apply {
+ prefix("bald", BALD.prefix)
+ prefix("skos", SKOS.uri)
resource("http://test.binary-array-ld.net/example") {
statement(RDF.type, BALD.Container)
statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/")) {
@@ -77,9 +105,19 @@ class BinaryArrayConvertCliTest {
}
}
+ @Test
+ fun run_withPrefixMappingGroup_outputsPrefixMapping() {
+ run_withPrefixMapping_outputsPrefixMapping("/netcdf/prefix.cdl")
+ }
+
+ @Test
+ fun run_withPrefixMappingVar_outputsPrefixMapping() {
+ run_withPrefixMapping_outputsPrefixMapping("/netcdf/prefix-var.cdl")
+ }
+
@Test
fun run_withSubgroups_outputsWithSubgroups() {
- val inputFile = convertToNetCdf("/netcdf/identity-subgroups.cdl")
+ val inputFile = writeToNetCdf("/netcdf/identity-subgroups.cdl")
val outputFile = createTempFile()
run("--uri", "http://test.binary-array-ld.net/example", inputFile.absolutePath, outputFile.absolutePath)
diff --git a/binary-array-ld-lib/src/main/kotlin/net/bald/BinaryArray.kt b/binary-array-ld-lib/src/main/kotlin/net/bald/BinaryArray.kt
index d1f983f..730f0e0 100644
--- a/binary-array-ld-lib/src/main/kotlin/net/bald/BinaryArray.kt
+++ b/binary-array-ld-lib/src/main/kotlin/net/bald/BinaryArray.kt
@@ -1,5 +1,7 @@
package net.bald
+import org.apache.jena.shared.PrefixMapping
+
/**
* Represents the metadata of a binary array dataset.
* See https://www.opengis.net/def/binary-array-ld/Array
@@ -10,6 +12,11 @@ interface BinaryArray {
*/
val uri: String
+ /**
+ * The prefix mapping to apply to the RDF graph.
+ */
+ val prefixMapping: PrefixMapping
+
/**
* The root container.
*/
diff --git a/binary-array-ld-lib/src/main/kotlin/net/bald/model/ModelBinaryArrayBuilder.kt b/binary-array-ld-lib/src/main/kotlin/net/bald/model/ModelBinaryArrayBuilder.kt
index 0b8fe08..eb276a5 100644
--- a/binary-array-ld-lib/src/main/kotlin/net/bald/model/ModelBinaryArrayBuilder.kt
+++ b/binary-array-ld-lib/src/main/kotlin/net/bald/model/ModelBinaryArrayBuilder.kt
@@ -3,16 +3,46 @@ package net.bald.model
import net.bald.BinaryArray
import net.bald.vocab.BALD
import org.apache.jena.rdf.model.Model
+import org.apache.jena.shared.PrefixMapping
+import java.net.URI
class ModelBinaryArrayBuilder(
private val model: Model,
private val containerFct: ModelContainerBuilder.Factory
) {
fun addBinaryArray(ba: BinaryArray) {
+ addPrefixMapping(ba.prefixMapping)
val baRes = model.createResource(ba.uri, BALD.Container)
containerFct.forParent(baRes).addContainer(ba.root)
}
+ private fun addPrefixMapping(prefixMapping: PrefixMapping) {
+ prefixMapping.nsPrefixMap.onEach { (prefix, uri) ->
+ validatePrefixMapping(prefix, uri)
+ }.let(model::setNsPrefixes)
+ }
+
+ private fun validatePrefixMapping(prefix: String, uri: String) {
+ try {
+ if (!Prefix.pattern.matches(prefix)) {
+ throw IllegalArgumentException("Prefix must match pattern ${Prefix.pattern}.")
+ } else if (!uri.endsWith('/') && !uri.endsWith('#')) {
+ throw IllegalArgumentException("URI must end with / or #.")
+ } else {
+ val scheme = URI.create(uri).scheme
+ if (scheme != "http" && scheme != "https") {
+ throw IllegalArgumentException("URI must have HTTP or HTTPS scheme.")
+ }
+ }
+ } catch (e: Exception) {
+ throw IllegalArgumentException("Unable to add prefix mapping $prefix to model: ${e.message}")
+ }
+ }
+
+ private object Prefix {
+ val pattern = Regex("[A-Za-z_]+")
+ }
+
class Factory(
private val containerFct: ModelContainerBuilder.Factory
) {
diff --git a/binary-array-ld-lib/src/main/kotlin/net/bald/vocab/BALD.kt b/binary-array-ld-lib/src/main/kotlin/net/bald/vocab/BALD.kt
index 0f0c1ed..c280d1b 100644
--- a/binary-array-ld-lib/src/main/kotlin/net/bald/vocab/BALD.kt
+++ b/binary-array-ld-lib/src/main/kotlin/net/bald/vocab/BALD.kt
@@ -11,7 +11,7 @@ import org.apache.jena.rdf.model.ResourceFactory.createResource
* See https://www.opengis.net/def/binary-array-ld/.
*/
object BALD {
- private const val prefix = "https://www.opengis.net/def/binary-array-ld/"
+ const val prefix = "https://www.opengis.net/def/binary-array-ld/"
/**
* Resources
diff --git a/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayBuilderTest.kt b/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayBuilderTest.kt
index 8c9a397..a07bb5c 100644
--- a/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayBuilderTest.kt
+++ b/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayBuilderTest.kt
@@ -9,8 +9,13 @@ import net.bald.BinaryArray
import net.bald.Container
import net.bald.vocab.BALD
import org.apache.jena.rdf.model.ModelFactory
+import org.apache.jena.shared.PrefixMapping
import org.apache.jena.vocabulary.RDF
-import org.junit.jupiter.api.*
+import org.apache.jena.vocabulary.SKOS
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.lang.IllegalArgumentException
+import kotlin.test.assertEquals
class ModelBinaryArrayBuilderTest {
private val containerBuilder = mock()
@@ -20,9 +25,13 @@ class ModelBinaryArrayBuilderTest {
private val model = ModelFactory.createDefaultModel()
private val builder = ModelBinaryArrayBuilder.Factory(containerFct).forModel(model)
private val root = mock()
+ private val prefix = PrefixMapping.Factory.create()
+ .setNsPrefix("bald", BALD.prefix)
+ .setNsPrefix("skos", SKOS.uri)
private val ba = mock {
on { uri } doReturn "http://test.binary-array-ld.net/example"
on { this.root } doReturn root
+ on { prefixMapping } doReturn prefix
}
@Test
@@ -39,4 +48,40 @@ class ModelBinaryArrayBuilderTest {
verify(containerFct).forParent(model.getResource("http://test.binary-array-ld.net/example"))
verify(containerBuilder).addContainer(root)
}
+
+ @Test
+ fun addBinaryArray_addsPrefixMapping() {
+ builder.addBinaryArray(ba)
+ ModelVerifier(model).apply {
+ prefix("bald", BALD.prefix)
+ prefix("skos", SKOS.uri)
+ }
+ }
+
+ @Test
+ fun addBinaryArray_prefixMappingWithInvalidChar_throwsException() {
+ prefix.setNsPrefix("bald-eg", "http://example.org/prefix/")
+ val iae = assertThrows {
+ builder.addBinaryArray(ba)
+ }
+ assertEquals("Unable to add prefix mapping bald-eg to model: Prefix must match pattern [A-Za-z_]+.", iae.message)
+ }
+
+ @Test
+ fun addBinaryArray_prefixMappingWithInvalidScheme_throwsException() {
+ prefix.setNsPrefix("eg", "file:///example/prefix/")
+ val iae = assertThrows {
+ builder.addBinaryArray(ba)
+ }
+ assertEquals("Unable to add prefix mapping eg to model: URI must have HTTP or HTTPS scheme.", iae.message)
+ }
+
+ @Test
+ fun addBinaryArray_prefixMappingWithoutTrailingChar_throwsException() {
+ prefix.setNsPrefix("eg", "http://example.org/prefix")
+ val iae = assertThrows {
+ builder.addBinaryArray(ba)
+ }
+ assertEquals("Unable to add prefix mapping eg to model: URI must end with / or #.", iae.message)
+ }
}
\ No newline at end of file
diff --git a/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayConverterTest.kt b/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayConverterTest.kt
index 77e0933..6371334 100644
--- a/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayConverterTest.kt
+++ b/binary-array-ld-lib/src/test/kotlin/net/bald/model/ModelBinaryArrayConverterTest.kt
@@ -8,7 +8,9 @@ import net.bald.Container
import net.bald.Var
import net.bald.vocab.BALD
import org.apache.jena.rdf.model.Model
+import org.apache.jena.shared.PrefixMapping
import org.apache.jena.vocabulary.RDF
+import org.apache.jena.vocabulary.SKOS
import org.junit.jupiter.api.*
/**
@@ -33,13 +35,19 @@ class ModelBinaryArrayConverterTest {
on { vars() } doReturn vars.asSequence()
on { subContainers() } doReturn emptySequence()
}
+ val prefix = PrefixMapping.Factory.create()
+ .setNsPrefix("bald", BALD.prefix)
+ .setNsPrefix("skos", SKOS.uri)
val ba = mock {
on { uri } doReturn "http://test.binary-array-ld.net/example"
on { this.root } doReturn root
+ on { prefixMapping } doReturn prefix
}
val model = convert(ba)
ModelVerifier(model).apply {
+ prefix("bald", BALD.prefix)
+ prefix("skos", SKOS.uri)
resource("http://test.binary-array-ld.net/example") {
statement(RDF.type, BALD.Container)
statement(BALD.contains, model.createResource("http://test.binary-array-ld.net/example/")) {
diff --git a/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfBinaryArray.kt b/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfBinaryArray.kt
index 37f1bc2..438cf0d 100644
--- a/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfBinaryArray.kt
+++ b/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfBinaryArray.kt
@@ -2,10 +2,11 @@ package net.bald.netcdf
import net.bald.BinaryArray
import net.bald.Container
-import ucar.nc2.NetcdfFile
-import ucar.nc2.NetcdfFiles
+import org.apache.jena.shared.PrefixMapping
+import ucar.nc2.*
import java.io.Closeable
import java.io.File
+import java.lang.IllegalStateException
/**
* NetCDF implementation of [BinaryArray].
@@ -15,12 +16,41 @@ class NetCdfBinaryArray(
override val uri: String,
private val file: NetcdfFile
): BinaryArray, Closeable {
- override val root: Container get() = NetCdfContainer(file.rootGroup)
+ override val root: Container get() = container(file.rootGroup)
+ override val prefixMapping: PrefixMapping get() = prefixMapping() ?: PrefixMapping.Factory.create()
override fun close() {
file.close()
}
+ private fun container(group: Group): Container {
+ val prefixSrc = prefixSourceName()
+ return NetCdfContainer(group, prefixSrc)
+ }
+
+ private fun prefixMapping(): PrefixMapping? {
+ return prefixSource()?.let(::NetCdfPrefixMappingBuilder)?.build()
+ }
+
+ private fun prefixSource(): AttributeContainer? {
+ return prefixSourceName()?.let { name ->
+ file.findGroup(name)
+ ?: file.findVariable(name)
+ ?: throw IllegalStateException("Prefix group or variable $name not found.")
+ }
+ }
+
+ private fun prefixSourceName(): String? {
+ return file.findGlobalAttribute(Attribute.prefix)?.let { attr ->
+ attr.stringValue
+ ?: throw IllegalStateException("Global prefix attribute ${Attribute.prefix} has a non-string value.")
+ }
+ }
+
+ private object Attribute {
+ const val prefix = "bald__isPrefixedBy"
+ }
+
companion object {
/**
* Instantiate a [BinaryArray] representation of the given NetCDF file and identifying URI.
@@ -31,9 +61,17 @@ class NetCdfBinaryArray(
*/
@JvmStatic
fun create(fileLoc: String, uri: String? = null): NetCdfBinaryArray {
- val requiredUri = uri ?: uri(fileLoc)
val file = NetcdfFiles.open(fileLoc)
- return NetCdfBinaryArray(requiredUri, file)
+ val requiredUri = uri ?: uri(fileLoc)
+ return create(file, requiredUri)
+ }
+
+ /**
+ * @see [create].
+ */
+ @JvmStatic
+ fun create(file: NetcdfFile, uri: String): NetCdfBinaryArray {
+ return NetCdfBinaryArray(uri, file)
}
private fun uri(fileLoc: String): String {
diff --git a/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfContainer.kt b/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfContainer.kt
index 1c42c55..9415d00 100644
--- a/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfContainer.kt
+++ b/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfContainer.kt
@@ -3,20 +3,30 @@ package net.bald.netcdf
import net.bald.Container
import net.bald.Var
import ucar.nc2.Group
+import ucar.nc2.Variable
/**
* NetCDF implementation of [Container].
*/
class NetCdfContainer(
- private val group: Group
+ private val group: Group,
+ private val prefixSrc: String? = null
): Container {
override val name: String? get() = group.shortName
override fun vars(): Sequence {
- return group.variables.asSequence().map(::NetCdfVar)
+ return group.variables.asSequence().filter(::acceptVar).map(::NetCdfVar)
}
override fun subContainers(): Sequence {
- return group.groups.asSequence().map(::NetCdfContainer)
+ return group.groups.asSequence().filter(::acceptGroup).map(::NetCdfContainer)
+ }
+
+ private fun acceptVar(v: Variable): Boolean {
+ return prefixSrc != v.shortName
+ }
+
+ private fun acceptGroup(group: Group): Boolean {
+ return prefixSrc != group.shortName
}
}
\ No newline at end of file
diff --git a/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfPrefixMappingBuilder.kt b/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfPrefixMappingBuilder.kt
new file mode 100644
index 0000000..f03e842
--- /dev/null
+++ b/binary-array-ld-netcdf/src/main/kotlin/net/bald/netcdf/NetCdfPrefixMappingBuilder.kt
@@ -0,0 +1,36 @@
+package net.bald.netcdf
+
+import org.apache.jena.shared.PrefixMapping
+import ucar.nc2.Attribute
+import ucar.nc2.AttributeContainer
+
+/**
+ * Class for building a
+ * NetCDF implementation of [PrefixMapping].
+ */
+class NetCdfPrefixMappingBuilder(
+ private val attrs: AttributeContainer
+) {
+ fun build(): PrefixMapping {
+ val prefixMap = attrs.asSequence()
+ .filter(::isPrefixAttr)
+ .associateBy(::prefix, ::uri)
+ return PrefixMapping.Factory.create().setNsPrefixes(prefixMap)
+ }
+
+ private fun isPrefixAttr(attr: Attribute): Boolean {
+ return attr.shortName.endsWith(suffix)
+ }
+
+ private fun prefix(attr: Attribute): String {
+ return attr.shortName.substringBeforeLast("__")
+ }
+
+ private fun uri(attr: Attribute): String {
+ return attr.stringValue ?: throw IllegalStateException("Prefix attribute ${attr.shortName} has a non-string value.")
+ }
+
+ companion object {
+ private const val suffix = "__"
+ }
+}
\ No newline at end of file
diff --git a/binary-array-ld-netcdf/src/test/kotlin/net/bald/netcdf/NetCdfBinaryArrayTest.kt b/binary-array-ld-netcdf/src/test/kotlin/net/bald/netcdf/NetCdfBinaryArrayTest.kt
index d9613b2..8d97019 100644
--- a/binary-array-ld-netcdf/src/test/kotlin/net/bald/netcdf/NetCdfBinaryArrayTest.kt
+++ b/binary-array-ld-netcdf/src/test/kotlin/net/bald/netcdf/NetCdfBinaryArrayTest.kt
@@ -1,34 +1,38 @@
package net.bald.netcdf
-import bald.netcdf.CdlConverter.convertToNetCdf
+import bald.netcdf.CdlConverter.writeToNetCdf
import net.bald.BinaryArray
import net.bald.Container
+import net.bald.vocab.BALD
+import org.apache.jena.vocabulary.SKOS
import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
class NetCdfBinaryArrayTest {
+
private fun fromCdl(cdlLoc: String, uri: String? = null): BinaryArray {
- val file = convertToNetCdf(cdlLoc)
+ val file = writeToNetCdf(cdlLoc)
return NetCdfBinaryArray.create(file.absolutePath, uri)
}
@Test
- fun create_withUri_returnsBinaryArray() {
+ fun uri_withUri_returnsValue() {
val uri = "http://test.binary-array-ld.net/identity.nc"
val ba = fromCdl("/netcdf/identity.cdl", uri)
assertEquals(uri, ba.uri)
}
@Test
- fun create_withoutUri_returnsBinaryArrayWithFileUri() {
- val netCdfFile = convertToNetCdf("/netcdf/identity.cdl")
+ fun uri_withoutUri_returnsFileUri() {
+ val netCdfFile = writeToNetCdf("/netcdf/identity.cdl")
val ba = NetCdfBinaryArray.create(netCdfFile.absolutePath)
val expectedUri = netCdfFile.toPath().toUri().toString()
assertEquals(expectedUri, ba.uri)
}
@Test
- fun create_withVars_returnsBinaryArrayWithVars() {
+ fun root_vars_withVars_returnsVariables() {
val uri = "http://test.binary-array-ld.net/identity.nc"
val ba = fromCdl("/netcdf/identity.cdl", uri)
@@ -39,7 +43,7 @@ class NetCdfBinaryArrayTest {
}
@Test
- fun create_withSubgroups_returnsSubgroups() {
+ fun root_subContainers_withSubgroups_returnsSubgroups() {
val uri = "http://test.binary-array-ld.net/identity-subgroups.nc"
val ba = fromCdl("/netcdf/identity-subgroups.cdl", uri)
val root = ba.root
@@ -61,4 +65,74 @@ class NetCdfBinaryArrayTest {
assertEquals("var4", group1Vars[0].name)
assertEquals("var5", group1Vars[1].name)
}
+
+ @Test
+ fun root_subContainers_withInternalPrefixMappingGroup_excludesPrefixMapping() {
+ val ba = fromCdl("/netcdf/identity.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ assertEquals(emptyList(), ba.root.subContainers().toList())
+ }
+
+ @Test
+ fun root_subContainers_withInternalPrefixMappingVar_excludesPrefixMapping() {
+ val ba = fromCdl("/netcdf/identity.cdl", "http://test.binary-array-ld.net/prefix-var.nc")
+ val vars = ba.root.vars().toList()
+ assertEquals(2, vars.size)
+ assertEquals("var0", vars[0].name)
+ assertEquals("var1", vars[1].name)
+ }
+
+ @Test
+ fun prefixMapping_withoutPrefixMapping_returnsEmptyPrefixMapping() {
+ val ba = fromCdl("/netcdf/identity.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ assertEquals(emptyMap(), ba.prefixMapping.nsPrefixMap)
+ }
+
+ @Test
+ fun prefixMapping_withInternalPrefixMappingGroup_returnsPrefixMapping() {
+ val ba = fromCdl("/netcdf/prefix.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ val prefix = ba.prefixMapping.nsPrefixMap
+ val expected = mapOf(
+ "bald" to BALD.prefix,
+ "skos" to SKOS.uri
+ )
+ assertEquals(expected, prefix)
+ }
+
+ @Test
+ fun prefixMapping_withInternalPrefixMappingVar_returnsPrefixMapping() {
+ val ba = fromCdl("/netcdf/prefix-var.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ val prefix = ba.prefixMapping.nsPrefixMap
+ val expected = mapOf(
+ "bald" to BALD.prefix,
+ "skos" to SKOS.uri
+ )
+ assertEquals(expected, prefix)
+ }
+
+ @Test
+ fun prefixMapping_prefixGroupDoesNotExist_throwsException() {
+ val ba = fromCdl("/netcdf/prefix-group-error.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ val ise = assertThrows {
+ ba.prefixMapping
+ }
+ assertEquals("Prefix group or variable not_prefix_list not found.", ise.message)
+ }
+
+ @Test
+ fun prefixMapping_prefixGroupAttrNonString_throwsException() {
+ val ba = fromCdl("/netcdf/prefix-attr-error.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ val ise = assertThrows {
+ ba.prefixMapping
+ }
+ assertEquals("Global prefix attribute bald__isPrefixedBy has a non-string value.", ise.message)
+ }
+
+ @Test
+ fun prefixMapping_prefixUriNonString_throwsException() {
+ val ba = fromCdl("/netcdf/prefix-uri-error.cdl", "http://test.binary-array-ld.net/prefix.nc")
+ val ise = assertThrows {
+ ba.prefixMapping
+ }
+ assertEquals("Prefix attribute skos__ has a non-string value.", ise.message)
+ }
}
\ No newline at end of file
diff --git a/binary-array-ld-test/pom.xml b/binary-array-ld-test/pom.xml
index 50e0194..a9c62a4 100644
--- a/binary-array-ld-test/pom.xml
+++ b/binary-array-ld-test/pom.xml
@@ -27,6 +27,11 @@
cdm-core
5.3.2
+
+ edu.ucar
+ netcdf4
+ 5.3.2
+
org.jetbrains.kotlin
kotlin-test-junit
diff --git a/binary-array-ld-test/src/main/kotlin/bald/model/ModelVerifier.kt b/binary-array-ld-test/src/main/kotlin/bald/model/ModelVerifier.kt
index 9e9a69a..2594c87 100644
--- a/binary-array-ld-test/src/main/kotlin/bald/model/ModelVerifier.kt
+++ b/binary-array-ld-test/src/main/kotlin/bald/model/ModelVerifier.kt
@@ -3,6 +3,7 @@ package bald.model
import org.apache.jena.rdf.model.Model
import org.apache.jena.rdf.model.Resource
import org.junit.jupiter.api.fail
+import kotlin.test.assertEquals
import kotlin.test.assertTrue
/**
@@ -23,4 +24,13 @@ class ModelVerifier(
assertTrue(model.containsResource(resource), "Expected resource $resource in model.")
ResourceVerifier(resource).statements(verify)
}
+
+ /**
+ * Verify that the given prefix name is associated with the given URI.
+ * @param prefix The prefix name.
+ * @param uri The prefix URI.
+ */
+ fun prefix(prefix: String, uri: String) {
+ assertEquals(uri, model.getNsPrefixURI(prefix), "Expected prefix mapping for $prefix.")
+ }
}
\ No newline at end of file
diff --git a/binary-array-ld-test/src/main/kotlin/bald/netcdf/CdlConverter.kt b/binary-array-ld-test/src/main/kotlin/bald/netcdf/CdlConverter.kt
index d69cf2c..efe8509 100644
--- a/binary-array-ld-test/src/main/kotlin/bald/netcdf/CdlConverter.kt
+++ b/binary-array-ld-test/src/main/kotlin/bald/netcdf/CdlConverter.kt
@@ -15,7 +15,7 @@ object CdlConverter {
* @param cdlLoc The location of the CDL resource.
* @return The NetCDF file.
*/
- fun convertToNetCdf(cdlLoc: String): File {
+ fun writeToNetCdf(cdlLoc: String): File {
val cdlFile = createTempFile()
javaClass.getResourceAsStream(cdlLoc).use { cdl ->
cdlFile.outputStream().use(cdl::copyTo)
diff --git a/binary-array-ld-test/src/main/kotlin/bald/netcdf/NcmlConverter.kt b/binary-array-ld-test/src/main/kotlin/bald/netcdf/NcmlConverter.kt
index c9cc365..a16647a 100644
--- a/binary-array-ld-test/src/main/kotlin/bald/netcdf/NcmlConverter.kt
+++ b/binary-array-ld-test/src/main/kotlin/bald/netcdf/NcmlConverter.kt
@@ -1,5 +1,7 @@
package bald.netcdf
+import ucar.nc2.NetcdfFile
+import ucar.nc2.NetcdfFileWriter
import ucar.nc2.ncml.NcMLReader
import java.io.File
@@ -10,17 +12,29 @@ import java.io.File
*/
object NcmlConverter {
/**
- * Convert a NCML resource into a temporary NetCDF file.
+ * Convert a NCML resource into a temporary NetCDF 4 file.
+ * In order to write NetCDF 4 successfully, the Unidata NetCDF C library must be available.
* @param ncmlLoc The location of the NCML resource.
* @return The NetCDF file.
*/
- fun convertToNetCdf(ncmlLoc: String): File {
+ fun writeToNetCdf(ncmlLoc: String): File {
val netCdfFile = createTempFile()
val netCdfLoc = netCdfFile.absolutePath
javaClass.getResourceAsStream(ncmlLoc).use { ncml ->
- NcMLReader.writeNcMLToFile(ncml, netCdfLoc)
+ NcMLReader.writeNcMLToFile(ncml, netCdfLoc, NetcdfFileWriter.Version.netcdf4, null)
}
return netCdfFile
}
+
+ /**
+ * Convert a NCML resource into a [NetcdfFile] in memory.
+ * @param ncmlLoc The location of the NCML resource.
+ * @return The NetCDF file representation.
+ */
+ fun readAsNetCdf(ncmlLoc: String): NetcdfFile {
+ return javaClass.getResourceAsStream(ncmlLoc).use { ncml ->
+ NcMLReader.readNcML(ncml, null)
+ }
+ }
}
\ No newline at end of file
diff --git a/binary-array-ld-test/src/main/resources/netcdf/prefix-attr-error.cdl b/binary-array-ld-test/src/main/resources/netcdf/prefix-attr-error.cdl
new file mode 100644
index 0000000..acb589d
--- /dev/null
+++ b/binary-array-ld-test/src/main/resources/netcdf/prefix-attr-error.cdl
@@ -0,0 +1,13 @@
+netcdf prefix {
+ dimensions:
+ d0 = 1 ;
+ d1 = 1 ;
+ variables:
+ int var0 ;
+ int var1 ;
+ :bald__isPrefixedBy = 100;
+ group: prefix_list {
+ :bald__ = "https://www.opengis.net/def/binary-array-ld/";
+ :skos__ = "http://www.w3.org/2004/02/skos/core#";
+ }
+}
\ No newline at end of file
diff --git a/binary-array-ld-test/src/main/resources/netcdf/prefix-group-error.cdl b/binary-array-ld-test/src/main/resources/netcdf/prefix-group-error.cdl
new file mode 100644
index 0000000..1cf9faf
--- /dev/null
+++ b/binary-array-ld-test/src/main/resources/netcdf/prefix-group-error.cdl
@@ -0,0 +1,13 @@
+netcdf prefix {
+ dimensions:
+ d0 = 1 ;
+ d1 = 1 ;
+ variables:
+ int var0 ;
+ int var1 ;
+ :bald__isPrefixedBy = "not_prefix_list";
+ group: prefix_list {
+ :bald__ = "https://www.opengis.net/def/binary-array-ld/";
+ :skos__ = "http://www.w3.org/2004/02/skos/core#";
+ }
+}
\ No newline at end of file
diff --git a/binary-array-ld-test/src/main/resources/netcdf/prefix-uri-error.cdl b/binary-array-ld-test/src/main/resources/netcdf/prefix-uri-error.cdl
new file mode 100644
index 0000000..16095ff
--- /dev/null
+++ b/binary-array-ld-test/src/main/resources/netcdf/prefix-uri-error.cdl
@@ -0,0 +1,13 @@
+netcdf prefix {
+ dimensions:
+ d0 = 1 ;
+ d1 = 1 ;
+ variables:
+ int var0 ;
+ int var1 ;
+ :bald__isPrefixedBy = "prefix_list";
+ group: prefix_list {
+ :bald__ = "https://www.opengis.net/def/binary-array-ld/";
+ :skos__ = 100;
+ }
+}
\ No newline at end of file
diff --git a/binary-array-ld-test/src/main/resources/netcdf/prefix-var.cdl b/binary-array-ld-test/src/main/resources/netcdf/prefix-var.cdl
new file mode 100644
index 0000000..e51d28b
--- /dev/null
+++ b/binary-array-ld-test/src/main/resources/netcdf/prefix-var.cdl
@@ -0,0 +1,13 @@
+netcdf identity {
+ dimensions:
+ d0 = 1 ;
+ d1 = 1 ;
+ variables:
+ int var0 ;
+ int var1 ;
+ int prefix_list ;
+ prefix_list:bald__ = "https://www.opengis.net/def/binary-array-ld/";
+ prefix_list:skos__ = "http://www.w3.org/2004/02/skos/core#";
+
+ :bald__isPrefixedBy = "prefix_list";
+}
\ No newline at end of file
diff --git a/binary-array-ld-test/src/main/resources/netcdf/prefix.cdl b/binary-array-ld-test/src/main/resources/netcdf/prefix.cdl
new file mode 100644
index 0000000..09671f6
--- /dev/null
+++ b/binary-array-ld-test/src/main/resources/netcdf/prefix.cdl
@@ -0,0 +1,13 @@
+netcdf identity {
+ dimensions:
+ d0 = 1 ;
+ d1 = 1 ;
+ variables:
+ int var0 ;
+ int var1 ;
+ :bald__isPrefixedBy = "prefix_list";
+ group: prefix_list {
+ :bald__ = "https://www.opengis.net/def/binary-array-ld/";
+ :skos__ = "http://www.w3.org/2004/02/skos/core#";
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 958049a..432b56d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,6 +109,14 @@
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+