Skip to content

Commit

Permalink
geonetwork#61 DcatConverter - handling of literals and resources
Browse files Browse the repository at this point in the history
  • Loading branch information
stijngoedertier committed Oct 4, 2022
1 parent 088b52e commit 46c3944
Show file tree
Hide file tree
Showing 17 changed files with 261 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@
import static org.fao.geonet.index.model.dcat2.Dataset.ACCRUAL_PERIODICITY_URI_PREFIX;
import static org.fao.geonet.index.model.gn.IndexRecordFieldNames.Codelists.topic;
import static org.fao.geonet.index.model.gn.IndexRecordFieldNames.CommonField.defaultText;
import static org.fao.geonet.index.model.gn.IndexRecordFieldNames.CommonField.link;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -39,20 +39,25 @@
import org.fao.geonet.index.model.dcat2.DcatDistribution.DcatDistributionBuilder;
import org.fao.geonet.index.model.dcat2.DcatDistributionContainer;
import org.fao.geonet.index.model.dcat2.DcatDocument;
import org.fao.geonet.index.model.dcat2.DctAccessRights;
import org.fao.geonet.index.model.dcat2.DctLocation;
import org.fao.geonet.index.model.dcat2.DctPeriodOfTime;
import org.fao.geonet.index.model.dcat2.DctPeriodOfTime.DctPeriodOfTimeBuilder;
import org.fao.geonet.index.model.dcat2.DctPublisher;
import org.fao.geonet.index.model.dcat2.DctSpatial;
import org.fao.geonet.index.model.dcat2.DctTemporal;
import org.fao.geonet.index.model.dcat2.FoafDocument;
import org.fao.geonet.index.model.dcat2.FoafOrganization;
import org.fao.geonet.index.model.dcat2.ProvActivity;
import org.fao.geonet.index.model.dcat2.ProvGenerated;
import org.fao.geonet.index.model.dcat2.ProvHadPlan;
import org.fao.geonet.index.model.dcat2.ProvQualifiedAssociation;
import org.fao.geonet.index.model.dcat2.Provenance;
import org.fao.geonet.index.model.dcat2.ProvenanceStatement;
import org.fao.geonet.index.model.dcat2.RdfLiteral;
import org.fao.geonet.index.model.dcat2.RdfResource;
import org.fao.geonet.index.model.dcat2.ResourceContainer;
import org.fao.geonet.index.model.dcat2.RightsStatement;
import org.fao.geonet.index.model.dcat2.SkosConcept;
import org.fao.geonet.index.model.dcat2.Subject;
import org.fao.geonet.index.model.dcat2.VcardContact;
Expand Down Expand Up @@ -122,6 +127,7 @@ public CatalogRecord convert(JsonNode doc) {
String language = record.getMainLanguage() == null
? defaultLanguage : record.getMainLanguage();
String languageUpperCase = language.toUpperCase();
String languageAlpha2 = RdfLiteral.mapLanguageCode(language);

List<String> resourceLanguage = record.getResourceLanguage();

Expand All @@ -137,8 +143,14 @@ public CatalogRecord convert(JsonNode doc) {
.identifier(record.getResourceIdentifier().stream()
.map(c -> c.getCode()).collect(
Collectors.toList()))
.title(listOfNullable(record.getResourceTitle().get(defaultText)))
.description(listOfNullable(record.getResourceAbstract().get(defaultText)))
.title(listOfNullable(new RdfLiteral(
languageAlpha2,
null,
record.getResourceTitle().get(defaultText))))
.description(listOfNullable(new RdfLiteral(
languageAlpha2,
null,
record.getResourceAbstract().get(defaultText))))
.landingPage(listOfNullable(DcatDocument.builder()
.foafDocument(FoafDocument.builder()
.about(formatterConfiguration.buildLandingPageLink(
Expand All @@ -156,7 +168,12 @@ public CatalogRecord convert(JsonNode doc) {
new RdfResource(null, "dcat:" + RESSOURCE_TYPE_MAPPING.get(t), null))
.collect(Collectors.toList()))
// INSPIRE <dct:type rdf:resource="{$ResourceTypeCodelistUri}/{$ResourceType}"/>
.modified(toDate(record.getChangeDate()))
.modified(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(record.getChangeDate())
))
.theme(
Optional.ofNullable(record.getCodelists().get(topic))
.map(Collection::stream)
Expand All @@ -171,20 +188,39 @@ public CatalogRecord convert(JsonNode doc) {
// TODO: skos:inScheme
// See https://github.com/SEMICeu/iso-19139-to-dcat-ap/blob/master/iso-19139-to-dcat-ap.xsl#L2803-L2864
.skosConcept(SkosConcept.builder()
.about(t.get(link))
.prefLabel(t.get(defaultText))
.build()).build()).collect(Collectors.toList()));

record.getResourceDate().stream()
.filter(d -> "creation".equals(d.getType()))
.forEach(d -> datasetBuilder.created(toDate(d.getDate())));
.forEach(d -> datasetBuilder.created(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(d.getDate())
)
));

record.getResourceDate().stream()
.filter(d -> "publication".equals(d.getType()))
.forEach(d -> datasetBuilder.issued(toDate(d.getDate())));
.forEach(d -> datasetBuilder.issued(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(d.getDate())
)
));

record.getResourceDate().stream()
.filter(d -> "revision".equals(d.getType()))
.forEach(d -> datasetBuilder.modified(toDate(d.getDate())));
.forEach(d -> datasetBuilder.modified(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(d.getDate())
)
));

// TODO: Convert to meter ?
datasetBuilder.spatialResolutionInMeters(
Expand Down Expand Up @@ -266,10 +302,20 @@ public CatalogRecord convert(JsonNode doc) {
record.getResourceTemporalExtentDateRange().stream().map(range -> {
DctPeriodOfTimeBuilder periodOfTime = DctPeriodOfTime.builder();
if (StringUtils.isNotEmpty(range.getGte())) {
periodOfTime.startDate(toDate(range.getGte()));
periodOfTime.startDate(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(range.getGte())
));
}
if (StringUtils.isNotEmpty(range.getLte())) {
periodOfTime.endDate(toDate(range.getLte()));
periodOfTime.endDate(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(range.getLte())
));
}
return DctTemporal.builder()
.periodOfTime(periodOfTime.build())
Expand All @@ -278,17 +324,22 @@ public CatalogRecord convert(JsonNode doc) {

record.getLinks().stream().forEach(link -> {
DcatDistributionBuilder dcatDistributionBuilder = DcatDistribution.builder()
.title(listOfNullable(link.getName()))
.description(listOfNullable(link.getDescription()))
.title(listOfNullable(new RdfLiteral(
languageAlpha2,
null,
link.getName())))
.description(listOfNullable(new RdfLiteral(
languageAlpha2,
null,
link.getDescription())))
// TODO <dcat:accessService rdf:parseType="Resource">...
// TODO: representation technique = gmd:MD_SpatialRepresentationTypeCode?
.representationTechnique(Subject.builder()
.skosConcept(SkosConcept.builder()
.prefLabel(link.getProtocol()).build()).build());

// TODO: depending on function/protocol build page/accessUrl/downloadUrl
dcatDistributionBuilder.accessUrl(link.getUrl());

dcatDistributionBuilder.accessUrl(new RdfResource(null, link.getUrl()));
datasetBuilder.distribution(listOfNullable(DcatDistributionContainer.builder()
.distribution(dcatDistributionBuilder.build()).build()));
});
Expand All @@ -299,15 +350,53 @@ public CatalogRecord convert(JsonNode doc) {
.contact(VcardContact.builder()
.title(contact.getOrganisation())
.role(contact.getRole())
.hasEmail(contact.getEmail()).build()).build()
.hasEmail(new RdfResource(
null,
"mailto://" + contact.getEmail())).build()).build()
).collect(Collectors.toList()));

datasetBuilder.publisher(
record.getContactForResource().stream().filter(contact ->
contact.getRole().equalsIgnoreCase("owner"))
.map(contact ->
DctPublisher.builder().organization(
FoafOrganization.builder()
.name(contact.getOrganisation())
.build()).build()
).collect(Collectors.toList()));


datasetBuilder.accessRights(
record.getConstraints().stream()
.map(constraint ->
DctAccessRights.builder()
.rightsStatement(
new RightsStatement(
constraint.getLink(),
null,
constraint.getDefaultText())
)
.build()
).collect(Collectors.toList())
);


dcatDataset = datasetBuilder.build();

catalogRecord = CatalogRecord.builder()
.identifier(listOfNullable(record.getMetadataIdentifier()))
.created(toDate(record.getCreateDate()))
.modified(toDate(record.getChangeDate()))
.created(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(record.getCreateDate())
))
.modified(
new RdfLiteral(
null,
"xsd:dateTime",
toDateTimeString(record.getChangeDate())
))
.language(listOfNullable(new RdfResource(null,
"http://publications.europa.eu/resource/authority/language/"
+ language.toUpperCase())))
Expand All @@ -322,11 +411,12 @@ public CatalogRecord convert(JsonNode doc) {
return catalogRecord;
}

private static Date toDate(String date) {
private static String toDateTimeString(String date) {
try {
return Date.from(
Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse(
date.length() == 10 ? date + "T00:00:00" : date)));
return LocalDateTime.parse(
date.length() == 10 ? date + "T00:00:00" : date,
DateTimeFormatter.ISO_DATE_TIME)
.format(DateTimeFormatter.ISO_DATE_TIME);
} catch (Exception e) {
e.printStackTrace();
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
public abstract class Base {

@XmlElement(namespace = DCT_URI)
List<String> title = new ArrayList();
List<RdfLiteral> title = new ArrayList();

@XmlElement(namespace = DCT_URI)
List<String> description = new ArrayList();
List<RdfLiteral> description = new ArrayList();
/**
* A unique identifier of the item.
*/
Expand All @@ -54,7 +54,7 @@ public abstract class Base {


@XmlElement(namespace = DCT_URI)
Date created;
RdfLiteral created;

/**
* The date of listing (i.e. formal recording) of the corresponding dataset or service in the
Expand All @@ -64,7 +64,7 @@ public abstract class Base {
* of the dataset itself.</p>
*/
@XmlElement(namespace = DCT_URI)
Date issued;
RdfLiteral issued;

/**
* Most recent date on which the catalog entry was changed, updated or modified.
Expand All @@ -73,7 +73,7 @@ public abstract class Base {
* description of the dataset, and not the date of the dataset itself.</p>
*/
@XmlElement(namespace = DCT_URI)
Date modified;
RdfLiteral modified;


// Can be a LinguisticSystem
Expand All @@ -97,5 +97,5 @@ public abstract class Base {
* A type of organisation that acts as a publisher.
*/
@XmlElement(namespace = DCT_URI)
List<FoafOrganization> publisher = new ArrayList();
List<DctPublisher> publisher = new ArrayList();
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public class Dataset extends Resource {
@XmlElement(namespace = FOAF_URI)
List<DcatDocument> page;

/**
/**f
* An available distribution of the dataset.
*/
@XmlElement(namespace = DCAT_URI)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package org.fao.geonet.index.model.dcat2;


import static org.fao.geonet.index.model.dcat2.Namespaces.ADMS_URI;
import static org.fao.geonet.index.model.dcat2.Namespaces.DCATAP_URI;
import static org.fao.geonet.index.model.dcat2.Namespaces.DCAT_URI;
Expand Down Expand Up @@ -47,14 +46,14 @@ public class DcatDistribution {
*/
@NonNull
@XmlElement(name = "accessURL", namespace = DCAT_URI)
String accessUrl;
RdfResource accessUrl;

/**
* The URL of the downloadable file in a given format. E.g. CSV file or RDF file. The format is
* indicated by the distribution's dct:format and/or dcat:mediaType
*/
@XmlElement(name = "downloadURL", namespace = DCAT_URI)
List<String> downloadUrl = new ArrayList();
List<RdfResource> downloadUrl = new ArrayList();

/**
* A data service that gives access to the distribution of the dataset.
Expand All @@ -66,13 +65,13 @@ public class DcatDistribution {
* A name given to the distribution.
*/
@XmlElement(namespace = DCT_URI)
List<String> title = new ArrayList();
List<RdfLiteral> title = new ArrayList();

/**
* A free-text account of the distribution.
*/
@XmlElement(namespace = DCT_URI)
List<String> description = new ArrayList();
List<RdfLiteral> description = new ArrayList();

@XmlElement(namespace = ADMS_URI)
Subject representationTechnique;
Expand Down Expand Up @@ -134,7 +133,7 @@ public class DcatDistribution {
* A rights statement that concerns how the distribution is accessed.
*/
@XmlElement(namespace = DCAT_URI)
List<DcatAccessRights> accessRights = new ArrayList();
List<DctAccessRights> accessRights = new ArrayList();


/**
Expand Down Expand Up @@ -166,7 +165,7 @@ public class DcatDistribution {
* Information about rights held in and over the distribution.
*/
@XmlElement(namespace = DCAT_URI)
List<DcatAccessRights> rights = new ArrayList();
List<DctAccessRights> rights = new ArrayList();

@XmlElement(namespace = RDFS_URI)
List<String> comment = new ArrayList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@NoArgsConstructor
@Data
@Builder
public class DcatAccessRights {
public class DctAccessRights {

@XmlElement(name = "RightsStatement", namespace = DCT_URI)
RightsStatement rightsStatement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
public class DctPeriodOfTime {

@XmlElement(namespace = DCAT_URI)
Date startDate;
RdfLiteral startDate;

@XmlElement(namespace = DCAT_URI)
Date endDate;
RdfLiteral endDate;
}
Loading

0 comments on commit 46c3944

Please sign in to comment.