Skip to content

Utilities#

Providing convenient helper classes for the piveau context

Build & Install#

Requirements:

  • Git
  • Maven 3
  • Java 17
$ git clone https://gitlab.com/piveau/utilities/piveau-utils.git
$ cd piveau-utils
$ mvn install

Use#

Add repository to your project pom file:

<repository>
    <id>paca</id>
    <name>paca</name>
    <url>https://paca.okd.fokus.fraunhofer.de/repository/maven-public/</url>
</repository>

Add dependency to your project pom file:

<dependency>
    <groupId>io.piveau.utils</groupId>
    <artifactId>piveau-utils</artifactId>
    <version>11.0.3</version>
</dependency>

APIs#

RDF#

General RDF helper and extensions

Hydra#

This API provides an implementation of the PagedCollection defined in the Hydra Core Vocabulary, a vocabulary for hypermedia-driven Web APIs.

val paging = findHydraPaging(model)
val total = paging.total ?: -1
val next = paging.next
HydraPaging paging = HydraPaging.findPaging(model);
int total = paging.getTotal() != null ? paging.getTotal() : -1;
String next = paging.getNext();

In some cases the provider uses the paging incorrectly. In these cases you can provide a base URI, and the class will try to fix the misbehaviour.

val paging = findHydraPaging(model, baseUri)
HydraPaging paging = HydraPaging.findPaging(model, baseUri);

The implementation currently only supports total items and next page.

Geo parsing#

Simple Method to convert an RDF Literal into a geo json object. The literal may be one of the following formats:

  • application/vnd.geo+json
  • http://www.openlinksw.com/schemas/virtrdf#Geometry
  • http://www.opengis.net/ont/geosparql#gmlLiteral

In all other cases and on any parsing problems the method returns an empty json object.

val jsonObject = parseGeoLiteral(geoLiteral)
JsonObject jsonObject = GeoParsingKt.parseGeoLiteral(geoLiteral);

Pre-Processing#

Apache Jena extensions#

Triple Hash#

RDF Vocabularies#

Common RDF vocabularies and concept schemes

DCAT-AP model builder#

POJOs for building DCAT-AP dataset graphs

DCAT-AP model parser#

Parsing rdf graphs for DCAT-AP classes and properties

DCAT-AP SPARQL triple store#

Connecting your app to a triple store following a DCAT-AP naming scheme

Using a DCAT-AP namespace schema#

DCATAPUriSchema.config = json {
    obj {
        "baseUri" to "https://piveau.io/"
        "catalogueContext" to "id/catalogues/"
        "datasetContext" to "set/data/"
        "distributionContext" to "set/distribution/"
        "recordContext" to "set/record/"
        "metricsContext" to "id/metrics/"
    }
}
DCATAPUriSchema.setConfig(new JsonObject()
        .put("baseUri", "https://piveau.io/")
        .put("catalogueContext", "id/catalogues/")
        .put("datasetContext", "set/data/")
        .put("distributionContext", "set/distribution/")
        .put("recordContext", "set/record/")
        .put("metricsContext", "id/metrics/"));

These are the default values. You can just override some or all of them if required.

The two main methods of this singleton is to parse a given uriRef and tells you what it is, and to generate a uriRef from a given external identifier

// check uri ref type
when {
    DCATAPUriSchema.isCatalogueUriRef(uriRef) -> {}
    DCATAPUriSchema.isDatasetUriRef(uriRef) -> {}
    DCATAPUriSchema.isDistributionUriRef(uriRef) -> {}
    DCATAPUriSchema.isRecordUriRef(uriRef) -> {}
    DCATAPUriSchema.isMetricsUriRef(uriRef) -> {}
    else -> {}
}

// parse given URIRef and provide a DCATAPUriRef
val dcatapUriRef = DCATAPUriSchema.parse(uriRef)

// context & id
val context = dcatapUriRef.context
val id = dcatapUriRef.id

// generate from external id.
val uriRef = DCATAPUriSchema.applyFor(externalId) 
// check uri ref type
if (DCATAPUriSchema.isCatalogueUriRef(uriRef)) {
} else if (DCATAPUriSchema.isDatasetUriRef(uriRef) {
} else if (DCATAPUriSchema.isDistributionUriRef(uriRef)) {
} else if (DCATAPUriSchema.isRecordUriRef(uriRef)) {
} else if (DCATAPUriSchema.isMetricsUriRef(uriRef)) {
} else {
}

// parse given URIRef and provide a DCATAPUriRef
DCATAPUriRef dcatapUriRef = DCATAPUriSchema.parse(uriRef);

// context & id
String context = dcatapUriRef.getContext();
String id = dcatapUriRef.getId();

// generate from external id.
DCATAPUriRef uriRef = DCATAPUriSchema.applyFor(externalId); 

Creating and configuring the triple store:#

val config = json {
    obj ("address" to "http://piveau-virtuoso:8890")   
}

val tripleStore = TripleStore(vertx, config)
JsonObject config = new JsonObject().put("address", "http://piveau-virtuoso:8890");
TripleStore tripleStore = new TripleStore(vertx, config);

with explicit WebClient

val client = WebClient.create(vertx)
val tripleStore = TripleStore(vertx, config, client)
WebClient client = WebClient.create(vertx);
TripleStore tripleStore = new TripleStore(vertx, config, client);

Using DCAT-AP specific managers#

The triple store comes with a set of DCAT-AP specific managers:

val catalogueManager = tripleStore.catalaogueManager
val datasetManager = tripleStore.datasetManager
val metricsManager = tripleStore.metricsManager
CatalogueManager catalogueManager = tripleStore.getCatalaogueManager();
DatasetManager datasetManager = tripleStore.getDatasetManager();
MetricsManager metricsManager = tripleStore.getMetricsManager();

Each manager provides a convenient API to deal with the corresponding DCAT-AP range. E.g.:

datasetManager.identify("originalId", "catalogueId") {
    when {
        it.succeeded() -> {
            val (datasetResource, recordResource) = it.result()
        }
        else -> {}
    }
}
datasetManager.identify("originalId", "catalogueId", ar -> {
    if (ar.succeeded()) {
        Resource datasetResource = ar.result().getFirst();
        Resource recordResource = ar.result().getSecond();

    } else {
    }
});

The managers rely heavenly on the DCATAPUriSchema, so make sure it is properly configured for your needs.

DQV extensions#

Building and managing DQV graphs

piveau Logging#

Convenient logging classes to log to a centralized ElasticStack instance

Deprecated

The main purpose of it was to trace within the microservice architecture, but we will soon switch to OpenTelemetry for tracing! You can still use it for any other kind of logging.

You need to create a PiveauContext in order to get access to the piveau logger.

val piveauContext = createPiveauContext("serviceName", "moduleName")
piveauContext.log.debug("I am here.")
PiveauContext piveauContext = PiveauContext.create("serviceName", "moduleName");
piveauContext.log().debug("I am here.");

The logger supports a slf4j style api.

You can extend the context for a specific resource:

val resourceContext = piveauContext.extend("resourceId")
resourceContext.log.debug("I am an extended resource.")
PiveauContext resourceContext = piveauContext.extend("resourceId");
resourceContext.log().debug("I am an extended resource.");

Triple store mock up server for testing#

A simple mock triple store for testing purposes

Deprecated

We recommend to use Testcontainers instead!

What else...#

All the rest

Normalize date time#

val dateTime = normalizeDateTime("2019-07-01T12:00:20.00+02")
String dateTime = DateTimeKt.normalizeDateTime("2019-07-01T12:00:20.00+02");

It returns the date or datetime as ISO-8601 instant standard string ("2019-07-01T14:00:20Z").

CORS helper#

To help you with the Vert.x CorsHandler.

CorsHelper(corsDomains).addRootHandler(routerBuilder)

// it is also possible to get assign the handler to a specific route yourself:

routerBuilder.route("/cors").handler(CorsHelper(corsDomains).handler)
new CorsHelper(corsDomains).addRootHandler(routerBuilder);

// it is also possible to get assign the handler to a specific route yourself:

routerBuilder.route("/cors").handler(new CorsHelper(corsDomains).handler)

If you want more customization options regarding the allowed Headers or Methods, you can overwrite the internal standard lists

val allowedHeaders = setOf<String>(
"x-requested-with",
"Access-Control-Allow-Origin",
"origin",
"Content-Type",
"accept");

val allowedMethods = setOf<HttpMethod>(HttpMethod.GET, HttpMethod.POST);

CorsHelper(corsDomains, allowedHeaders, allowedMethods).addRootHandler(routerBuilder)
Set<String> allowedHeaders = setOf<String>(
"x-requested-with",
"Access-Control-Allow-Origin",
"origin",
"Content-Type",
"accept");

Set<HttpMethod> allowedMethods = Set.of(HttpMethod.GET, HttpMethod.POST);

CorsHelper ch = new CorsHelper(corsDomains, allowedHeaders, allowedMethods);
ch.addRootHandler(routerBuilder);

Vert.x JsonObject and JsonArray extensions#

Although these extensions are most useful in Kotlin, you can use them also in Java.

val jsonObj = JsonObject()

// Put only if value is not null
jsonObj.putIfNotNull("key", value)
// Put only if json object is not empty
jsonObj.putIfNotEmpty("key", obj)

// Return json object of key or create a new one if not already exist. 
val obj = jsonObj.withJsonObject("key")
// Return json array of key or create a new one if not already exist. 
val array = jsonObj.withJsonArray("key")

// Forces key as `JsonObject`, even if it is a string   
val obj = jsonObj.asJsonObject("key")
// Forces key as `JsonArray`, even if it is a string   
val array = jsonObj.asJsonArray("key")

val jsonArray = JsonArray()
// Add only if value is not null
jsonArray.addIfNotNull(value)
// Add only if json object is not empty
jsonArray.addIfNotEmpty(obj)
JsonObject jsonObj = new JsonObject();

// Put only if value is not null
JsonExtensions.putIfNotNull(jsonObj, "key", value);
// Put only if json object is not empty
JsonExtensions.putIfNotEmpty(jsonObj, "key", obj);

// Return json object of key or create a new one if not already exist. 
JsonObject obj = JsonExtensions.withJsonObject(jsonObj, "key");
// Return json array of key or create a new one if not already exist. 
JsonArray array = JsonExtensions.withJsonArray(jsonObj, "key");

// Forces key as `JsonObject`, even if it is a string   
JsonObject obj = JsonExtensions.asJsonObject(jsonObj, "key");
// Forces key as `JsonArray`, even if it is a string   
JsonArray array = JsonExtensions.asJsonArray(jsonObj, "key");

JsonArray jsonArray = new JsonArray();
// Add only if value is not null
JsonExtensions.addIfNotNull(jsonArray, value);
// Add only if json object is not empty
JsonExtensions.addIfNotEmpty(jsonArray, obj);

Config helper#

Deprecated

Please use general Vert.x Json extension functions!

val jsonObject = config.asJsonObject("key")
val jsonArray = config.asJsonArray("key")
// Old way
JsonObject jsonObject = ConfigHelper.forConfig(config).forceJsonObject("key");
JsonObject jsonArray = ConfigHelper.forConfig(config).forceJsonArray("key");

// New way
JsonObject jsonObject = JsonExtensions.asJsonObject(config, "key");
JsonObject jsonArray = JsonExtensions.asJsonArray(config, "key");