diff --git a/ckanext/dcat/codelists/__init__.py b/ckanext/dcat/codelists/__init__.py new file mode 100644 index 00000000..43737cd4 --- /dev/null +++ b/ckanext/dcat/codelists/__init__.py @@ -0,0 +1,8 @@ + +from .extract import extract +from pathlib import Path + +high_value_dataset_category = extract(Path(__file__).parent / 'high-value-dataset-category.rdf') + + +__all__ = ['high_value_dataset_category'] diff --git a/ckanext/dcat/codelists/extract.py b/ckanext/dcat/codelists/extract.py new file mode 100644 index 00000000..521c3e22 --- /dev/null +++ b/ckanext/dcat/codelists/extract.py @@ -0,0 +1,116 @@ +''' +Converts EU RDF descriptions of codelists to ckanext-scheming choices. + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Meteorological + Meteorología + Meteoroloģijas datu kopas + Data meteoroloġika + Meteorologische data + Meteorologiska data + ... + 3 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 3 + + + + +to: + + { + "label": { + "en": "Meteorological", + "ga": "Meit\u00e9areola\u00edoch", + "mt": "Data meteorolo\u0121ika" + }, + "value": "http://data.europa.eu/bna/c_164e0bf5" + }, + + +These are suitable for inclusion in the schema.json. + +''' + +import rdflib +import rdflib.parser + +from rdflib.namespace import Namespace, RDF, SKOS + +from pathlib import Path +import xml +import json +from functools import lru_cache + +from ckan.plugins import toolkit + +import logging +log = logging.getLogger(__name__) + + +EUVOC = Namespace("http://publications.europa.eu/ontology/euvoc#") +# filter out variants of languages, en_GB doesn't match en. +LANGS = set(l.split('_')[0] for l in toolkit.aslist(toolkit.config.get('ckan.locales_offered', ['en']))) + + +class Codelist: + def __init__(self, choices, scheme): + self.choices = choices + self.scheme = scheme + self.choices_map = {elt['value']:elt['label'] for elt in choices} + log.debug(LANGS) + def labels(self, val): + return self.choices_map.get(val, {}) + +@lru_cache(None) +def extract(f:Path): + + g = rdflib.ConjunctiveGraph() + try: + g.parse(data=f.read_text(), format='xml') + # Apparently there is no single way of catching exceptions from all + # rdflib parsers at once, so if you use a new one and the parsing + # exceptions are not cached, add them here. + # PluginException indicates that an unknown format was passed. + except (SyntaxError, xml.sax.SAXParseException, + rdflib.plugin.PluginException, TypeError) as e: + raise Exception(e) + + choices = {} + + for subject in g.subjects(RDF.type, SKOS.Concept): + labels = {l.language: str(l) for l in g.objects(subject, SKOS.prefLabel) if l.language in LANGS } + try: + order = list(g.objects(subject, EUVOC.order))[0] + except KeyError: + order = str(subject) + + choice = {"label": labels, + "value": str(subject)} + + choices[order] = choice + + ordered_choices = [v for k,v in sorted(choices.items())] + + scheme = None + for subject in g.subjects(RDF.type, SKOS.ConceptScheme): + scheme = str(subject) + + return Codelist(ordered_choices, scheme) + + +def write_json(): + for path in Path(__file__).parent.glob('*.rdf'): + data = extract(path) + dest = path.parent / (path.stem + '.json') + with open (dest, 'w') as f: + json.dump(data.choices, f, indent=2) + + +#print(json.dumps(ordered_choices, indent=2)) + + + diff --git a/ckanext/dcat/codelists/high-value-dataset-category.rdf b/ckanext/dcat/codelists/high-value-dataset-category.rdf new file mode 100644 index 00000000..93e0f7cc --- /dev/null +++ b/ckanext/dcat/codelists/high-value-dataset-category.rdf @@ -0,0 +1,226 @@ + + + + + 2019-07-06 + 2023-09-05 + 2023-09-27 + 2023-09-07 + High-value dataset categories + + High-value dataset categories + 1.0 + + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Метеорологични данни + Meteorologie + Meteorologiske data + Meteorologie + Μετεωρολογικές πληροφορίες + Meteorological + Meteorología + Meteoroloogiateave + Säätiedot + Météorologiques + Meitéareolaíoch + Meteorološki podatci + Meteorológiai adatok + Dati meteorologici + Meteorologiniai duomenys + Meteoroloģijas datu kopas + Data meteoroloġika + Meteorologische data + Dane meteorologiczne + Meteorológicas + Domeniul meteorologic + Meteorológia + Meteorološki podatki + Meteorologiska data + 3 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 3 + + + + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Дружества и собственост на дружествата + Společnosti a vlastnictví společností + Virksomheder og virksomhedsejerskab + Unternehmen und Eigentümerschaft von Unternehmen + Εταιρείες και ιδιοκτησιακό καθεστώς εταιρειών + Companies and company ownership + Sociedades y propiedad de sociedades + Äriühingud ja äriühingu omandisuhted + Yritys- ja yritysten omistustiedot + Entreprises et propriété d'entreprises + Cuideachtaí agus úinéireacht cuideachtaí + Trgovačka društva i vlasništvo nad trgovačkim društvima + Vállalati és vállalattulajdonosi adatok + Dati relativi alle imprese e alla proprietà delle imprese + Bendrovės ir bendrovių valdymas nuosavybės teise + Uzņēmumi un uzņēmumu īpašumtiesības + Data dwar il-kumpanniji u l-proprjetà tal-kumpanniji + Bedrijven en eigendom van bedrijven + Dane dotyczące przedsiębiorstw i ich własności + Empresas e propriedade de empresas + Domeniul Societăți și structura de proprietate a societăților + Spoločnosti a vlastníctvo spoločností + Družbe in lastništvo družb + Företag och företagsägande + 5 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 5 + + + + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Геопространствени данни + Geoprostorové údaje + Geospatiale data + Georaum + Γεωχωρικές πληροφορίες + Geospatial + Geoespacial + Georuumilised andmed + Paikkatiedot + Géospatiales + Geospásúil + Geoprostorni podatci + Térinformatikai adatok + Dati geospaziali + Geoerdviniai duomenys + Ģeotelpisko datu kopas + Data ġeospazjali + Geospatiale data + Dane geoprzestrzenne + Geoespaciais + Domeniul geospațial + Geopriestorové údaje + Geoprostorski podatki + Geospatiala data + 1 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 1 + + + + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Мобилност + Mobilita + Mobilitet + Mobilität + Κινητικότητα + Mobility + Movilidad + Liikuvus + Liikkuvuustiedot + Mobilité + Soghluaisteacht + Mobilnost + Mobilitási adatok + Dati relativi alla mobilità + Judumas + Mobilitāte + Data dwar il-mobbiltà + Mobiliteit + Dane dotyczące mobilności + Mobilidade + Domeniul Mobilitate + Mobilita + Mobilnost + Rörlighet + 6 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 6 + + + + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Наблюдение на Земята и околната среда + Země a životní prostředí + Jordobservation og miljø + Erdbeobachtung und Umwelt + Γεωσκόπηση και περιβάλλον + Earth observation and environment + Observación de la Tierra y medio ambiente + Maa seire ja keskkond + Maan havainnointi ja ympäristö + Observation de la terre et environnement + Faire na cruinne agus an comhshaol + Promatranje Zemlje i okoliš + Földmegfigyelési és környezeti adatok + Dati relativi all'osservazione della terra e all'ambiente + Žemės stebėjimas ir aplinka + Zemes novērošana un vide + Data dwar l-osservazzjoni tad-dinja u l-ambjent + Aardobservatie en milieu + Dane dotyczące obserwacji Ziemi i środowiska + Observação da Terra e do ambiente + Domeniul Observarea Pământului și mediu + Pozorovanie Zeme a životné prostredie + Opazovanje zemlje in okolje + Jordobservation och miljö + 2 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 2 + + + + + + 2019-07-06 + 2023-09-05 + 2023-09-13 + + Статистика + Statistika + Statistik + Statistik + Στατιστικές + Statistics + Estadística + Statistika + Tilastotiedot + Statistiques + Staidreamh + Statistički podatci + Statisztikák + Dati statistici + Statistika + Statistika + Data statistika + Statistiek + Dane statystyczne + Estatísticas + Domeniul statistic + Štatistika + Statistični podatki + Statistik + 4 + data sets as described in Commission Implementing Regulation (EU) 2023/138 of 21 December 2022 laying down a list of specific high-value datasets and the arrangements for their publication and re-use, Annex, Section 4 + + + + + \ No newline at end of file diff --git a/ckanext/dcat/profiles.py b/ckanext/dcat/profiles.py index 450166b0..acc6896a 100644 --- a/ckanext/dcat/profiles.py +++ b/ckanext/dcat/profiles.py @@ -21,6 +21,7 @@ from ckan.plugins import toolkit from ckan.lib.munge import munge_tag from ckanext.dcat.utils import resource_uri, publisher_uri_organization_fallback, DCAT_EXPOSE_SUBCATALOGS, DCAT_CLEAN_TAGS +from . import codelists DCT = Namespace("http://purl.org/dc/terms/") DCAT = Namespace("http://www.w3.org/ns/dcat#") @@ -34,6 +35,7 @@ GSP = Namespace('http://www.opengis.net/ont/geosparql#') OWL = Namespace('http://www.w3.org/2002/07/owl#') SPDX = Namespace('http://spdx.org/rdf/terms#') +ELI= Namespace('http://data.europa.eu/eli/ontology#') GEOJSON_IMT = 'https://www.iana.org/assignments/media-types/application/vnd.geo+json' @@ -727,12 +729,17 @@ def _add_triples_from_dict(self, _dict, subject, items, list_value=False, date_value=False): for item in items: - key, predicate, fallbacks, _type = item + try: + key, predicate, fallbacks, _type, _class = item + except ValueError: + key, predicate, fallbacks, _type = item + _class=None self._add_triple_from_dict(_dict, subject, predicate, key, fallbacks=fallbacks, list_value=list_value, date_value=date_value, - _type=_type) + _type=_type, + _class=_class) def _add_triple_from_dict(self, _dict, subject, predicate, key, fallbacks=None, @@ -740,7 +747,8 @@ def _add_triple_from_dict(self, _dict, subject, predicate, key, date_value=False, _type=Literal, _datatype=None, - value_modifier=None): + value_modifier=None, + _class=None): ''' Adds a new triple to the graph with the provided parameters @@ -756,6 +764,8 @@ def _add_triple_from_dict(self, _dict, subject, predicate, key, If `list_value` or `date_value` are True, then the value is treated as a list or a date respectively (see `_add_list_triple` and `_add_date_triple` for details. + + `_class` is the optional RDF class of the entity being added. ''' value = self._get_dict_value(_dict, key) if not value and fallbacks: @@ -769,7 +779,7 @@ def _add_triple_from_dict(self, _dict, subject, predicate, key, value = value_modifier(value) if value and list_value: - self._add_list_triple(subject, predicate, value, _type, _datatype) + self._add_list_triple(subject, predicate, value, _type, _datatype, _class=_class) elif value and date_value: self._add_date_triple(subject, predicate, value, _type) elif value: @@ -782,8 +792,10 @@ def _add_triple_from_dict(self, _dict, subject, predicate, key, else: object = _type(value) self.g.add((subject, predicate, object)) + if _class: + self.g.add((object, RDF.type, _class)) - def _add_list_triple(self, subject, predicate, value, _type=Literal, _datatype=None): + def _add_list_triple(self, subject, predicate, value, _type=Literal, _datatype=None, _class=None): ''' Adds as many triples to the graph as values @@ -802,8 +814,10 @@ def _add_list_triple(self, subject, predicate, value, _type=Literal, _datatype=N else: object = _type(item) self.g.add((subject, predicate, object)) + if _class: + self.g.add((object, RDF.type, _class)) - def _add_date_triple(self, subject, predicate, value, _type=Literal): + def _add_date_triple(self, subject, predicate, value, _type=Literal): #UNDONE -- add class here??, looks like we're already possibly tagging? ''' Adds a new triple with a date object @@ -908,6 +922,40 @@ def _get_or_create_spatial_ref(self, dataset_dict, dataset_ref): self.g.add((dataset_ref, DCT.spatial, spatial_ref)) return spatial_ref + def _add_from_codelist(self, _dict, subject, predicate, key, + codelist, + _type=URIRefOrLiteral, + list_value=False, + fallbacks=False, + value_modifier=False): + ''' Add an item from a codelist, stored in rdf in the codelists directory ''' + + value = self._get_dict_value(_dict, key) + if not value and fallbacks: + for fallback in fallbacks: + value = self._get_dict_value(_dict, fallback) + if value: + break + + if value and callable(value_modifier): + value = value_modifier(value) + + def add(item): + ref = _type(item) + self.g.add((ref, RDF.type, SKOS.Concept)) + self.g.add((ref, SKOS.inScheme, URIRef(codelist.scheme))) + self.g.add((subject, predicate, ref)) + for lang, label in codelist.labels(item).items(): + _label_ref = Literal(label, lang=lang) + self.g.add((ref, SKOS.prefLabel, _label_ref)) + + if list_value: + items = self._read_list_value(value) + for item in items: + add(item) + else: + add(value) + # Public methods for profiles to implement def parse_dataset(self, dataset_dict, dataset_ref): @@ -1355,103 +1403,110 @@ def graph_from_dataset(self, dataset_dict, dataset_ref): # Resources for resource_dict in dataset_dict.get('resources', []): + self.graph_from_resource(g, dataset_ref, resource_dict, resource_license_fallback) + def graph_from_resource(self, g, dataset_ref, resource_dict, resource_license_fallback, distribution=None): + if distribution is None: distribution = CleanedURIRef(resource_uri(resource_dict)) - g.add((dataset_ref, DCAT.distribution, distribution)) + g.add((dataset_ref, DCAT.distribution, distribution)) - g.add((distribution, RDF.type, DCAT.Distribution)) + g.add((distribution, RDF.type, DCAT.Distribution)) - # Simple values - items = [ - ('name', DCT.title, None, Literal), - ('description', DCT.description, None, Literal), - ('status', ADMS.status, None, URIRefOrLiteral), - ('rights', DCT.rights, None, URIRefOrLiteral), - ('license', DCT.license, None, URIRefOrLiteral), - ('access_url', DCAT.accessURL, None, URIRef), - ('download_url', DCAT.downloadURL, None, URIRef), - ] + # Simple values + items = [ + ('name', DCT.title, None, Literal), + ('description', DCT.description, None, Literal), + ('status', ADMS.status, None, URIRefOrLiteral), + ('rights', DCT.rights, None, URIRefOrLiteral), + ('license', DCT.license, None, URIRefOrLiteral, DCT.LicenseDocument), + ('access_url', DCAT.accessURL, None, URIRef), + ('download_url', DCAT.downloadURL, None, URIRef), + ] - self._add_triples_from_dict(resource_dict, distribution, items) + self._add_triples_from_dict(resource_dict, distribution, items) - # Lists - items = [ - ('documentation', FOAF.page, None, URIRefOrLiteral), - ('language', DCT.language, None, URIRefOrLiteral), - ('conforms_to', DCT.conformsTo, None, Literal), - ] - self._add_list_triples_from_dict(resource_dict, distribution, items) - - # Set default license for distribution if needed and available - if resource_license_fallback and not (distribution, DCT.license, None) in g: - g.add((distribution, DCT.license, URIRefOrLiteral(resource_license_fallback))) - - # Format - mimetype = resource_dict.get('mimetype') - fmt = resource_dict.get('format') - - # IANA media types (either URI or Literal) should be mapped as mediaType. - # In case format is available and mimetype is not set or identical to format, - # check which type is appropriate. - if fmt and (not mimetype or mimetype == fmt): - if ('iana.org/assignments/media-types' in fmt - or not fmt.startswith('http') and '/' in fmt): - # output format value as dcat:mediaType instead of dct:format - mimetype = fmt - fmt = None - else: - # Use dct:format - mimetype = None + # Lists + items = [ + ('documentation', FOAF.page, None, URIRefOrLiteral), + ('language', DCT.language, None, URIRefOrLiteral), + ('conforms_to', DCT.conformsTo, None, Literal), + ] + self._add_list_triples_from_dict(resource_dict, distribution, items) - if mimetype: - g.add((distribution, DCAT.mediaType, - URIRefOrLiteral(mimetype))) + # Set default license for distribution if needed and available + if resource_license_fallback and not (distribution, DCT.license, None) in g: + _ref = URIRefOrLiteral(resource_license_fallback) + g.add((_ref, RDF.type, DCT.LicenseDocument)) + g.add((distribution, DCT.license, _ref)) - if fmt: - g.add((distribution, DCT['format'], - URIRefOrLiteral(fmt))) + # Format + mimetype = resource_dict.get('mimetype') + fmt = resource_dict.get('format') + + # IANA media types (either URI or Literal) should be mapped as mediaType. + # In case format is available and mimetype is not set or identical to format, + # check which type is appropriate. + if fmt and (not mimetype or mimetype == fmt): + if ('iana.org/assignments/media-types' in fmt + or not fmt.startswith('http') and '/' in fmt): + # output format value as dcat:mediaType instead of dct:format + mimetype = fmt + fmt = None + else: + # Use dct:format + mimetype = None + if mimetype: + g.add((distribution, DCAT.mediaType, + URIRefOrLiteral(mimetype))) - # URL fallback and old behavior - url = resource_dict.get('url') - download_url = resource_dict.get('download_url') - access_url = resource_dict.get('access_url') - # Use url as fallback for access_url if access_url is not set and download_url is not equal - if url and not access_url: - if (not download_url) or (download_url and url != download_url): - self._add_triple_from_dict(resource_dict, distribution, DCAT.accessURL, 'url', _type=URIRef) + if fmt: + g.add((distribution, DCT['format'], + URIRefOrLiteral(fmt))) - # Dates - items = [ - ('issued', DCT.issued, ['created'], Literal), - ('modified', DCT.modified, ['metadata_modified'], Literal), - ] - self._add_date_triples_from_dict(resource_dict, distribution, items) + # URL fallback and old behavior + url = resource_dict.get('url') + download_url = resource_dict.get('download_url') + access_url = resource_dict.get('access_url') + # Use url as fallback for access_url if access_url is not set and download_url is not equal + if url and not access_url: + if (not download_url) or (download_url and url != download_url): + self._add_triple_from_dict(resource_dict, distribution, DCAT.accessURL, 'url', _type=URIRef) - # Numbers - if resource_dict.get('size'): - try: - g.add((distribution, DCAT.byteSize, - Literal(float(resource_dict['size']), - datatype=XSD.decimal))) - except (ValueError, TypeError): - g.add((distribution, DCAT.byteSize, - Literal(resource_dict['size']))) - # Checksum - if resource_dict.get('hash'): - checksum = BNode() - g.add((checksum, RDF.type, SPDX.Checksum)) - g.add((checksum, SPDX.checksumValue, - Literal(resource_dict['hash'], - datatype=XSD.hexBinary))) + # Dates + items = [ + ('issued', DCT.issued, ['created'], Literal), + ('modified', DCT.modified, ['metadata_modified'], Literal), + ] - if resource_dict.get('hash_algorithm'): - g.add((checksum, SPDX.algorithm, - URIRefOrLiteral(resource_dict['hash_algorithm']))) + self._add_date_triples_from_dict(resource_dict, distribution, items) - g.add((distribution, SPDX.checksum, checksum)) + # Numbers + if resource_dict.get('size'): + try: + g.add((distribution, DCAT.byteSize, + Literal(float(resource_dict['size']), + datatype=XSD.decimal))) + except (ValueError, TypeError): + g.add((distribution, DCAT.byteSize, + Literal(resource_dict['size']))) + # Checksum + if resource_dict.get('hash'): + checksum = BNode() + g.add((checksum, RDF.type, SPDX.Checksum)) + g.add((checksum, SPDX.checksumValue, + Literal(resource_dict['hash'], + datatype=XSD.hexBinary))) + + if resource_dict.get('hash_algorithm'): + g.add((checksum, SPDX.algorithm, + URIRefOrLiteral(resource_dict['hash_algorithm']))) + + g.add((distribution, SPDX.checksum, checksum)) + + return distribution def graph_from_catalog(self, catalog_dict, catalog_ref): @@ -1595,22 +1650,25 @@ def parse_dataset(self, dataset_dict, dataset_ref): resource_dict['access_services'] = json.dumps(access_service_list) return dataset_dict - + def graph_from_dataset(self, dataset_dict, dataset_ref): # call super method super(EuropeanDCATAP2Profile, self).graph_from_dataset(dataset_dict, dataset_ref) # Lists - for key, predicate, fallbacks, type, datatype in ( - ('temporal_resolution', DCAT.temporalResolution, None, Literal, XSD.duration), - ('is_referenced_by', DCT.isReferencedBy, None, URIRefOrLiteral, None), - ('applicable_legislation', DCATAP.applicableLegislation, None, URIRefOrLiteral, None), - ('hvd_category', DCATAP.hvdCategory, None, URIRefOrLiteral, None), + for key, predicate, fallbacks, _type, datatype, _class in ( + ('temporal_resolution', DCAT.temporalResolution, None, Literal, XSD.duration, None), + ('is_referenced_by', DCT.isReferencedBy, None, URIRefOrLiteral, None, None), + ('applicable_legislation', DCATAP.applicableLegislation, None, URIRefOrLiteral, None, ELI.LegalResource), ): self._add_triple_from_dict(dataset_dict, dataset_ref, predicate, key, list_value=True, - fallbacks=fallbacks, _type=type, _datatype=datatype) - + fallbacks=fallbacks, _type=_type, _datatype=datatype, _class=_class) + + self._add_from_codelist(dataset_dict, dataset_ref, DCATAP.hvdCategory, 'hvd_category', + codelists.high_value_dataset_category, + list_value=True) + # Temporal start = self._get_dataset_value(dataset_dict, 'temporal_start') end = self._get_dataset_value(dataset_dict, 'temporal_end') @@ -1648,67 +1706,67 @@ def graph_from_dataset(self, dataset_dict, dataset_ref): except (ValueError, TypeError): self.g.add((dataset_ref, DCAT.spatialResolutionInMeters, Literal(value))) - # Resources - for resource_dict in dataset_dict.get('resources', []): - distribution = CleanedURIRef(resource_uri(resource_dict)) + def graph_from_resource(self, g, dataset_ref, resource_dict, resource_license_fallback, distribution=None): + distribution = super().graph_from_resource(g, dataset_ref, resource_dict, resource_license_fallback, distribution) - # Simple values - items = [ - ('availability', DCATAP.availability, None, URIRefOrLiteral), - ('compress_format', DCAT.compressFormat, None, URIRefOrLiteral), - ('package_format', DCAT.packageFormat, None, URIRefOrLiteral) - ] + # Simple values + items = [ + ('availability', DCATAP.availability, None, URIRefOrLiteral), + ('compress_format', DCAT.compressFormat, None, URIRefOrLiteral), + ('package_format', DCAT.packageFormat, None, URIRefOrLiteral) + ] - self._add_triples_from_dict(resource_dict, distribution, items) + self._add_triples_from_dict(resource_dict, distribution, items) - # Lists - items = [ - ('applicable_legislation', DCATAP.applicableLegislation, None, URIRefOrLiteral), - ] - self._add_list_triples_from_dict(resource_dict, distribution, items) + # Lists + items = [ + ('applicable_legislation', DCATAP.applicableLegislation, None, URIRefOrLiteral), + ] + self._add_list_triples_from_dict(resource_dict, distribution, items) - try: - access_service_list = json.loads(resource_dict.get('access_services', '[]')) - # Access service - for access_service_dict in access_service_list: - - access_service_uri = access_service_dict.get('uri') - if access_service_uri: - access_service_node = CleanedURIRef(access_service_uri) - else: - access_service_node = BNode() - # Remember the (internal) access service reference for referencing in - # further profiles - access_service_dict['access_service_ref'] = str(access_service_node) - - self.g.add((distribution, DCAT.accessService, access_service_node)) - - self.g.add((access_service_node, RDF.type, DCAT.DataService)) - - # Simple values - items = [ - ('availability', DCATAP.availability, None, URIRefOrLiteral), - ('license', DCT.license, None, URIRefOrLiteral), - ('access_rights', DCT.accessRights, None, URIRefOrLiteral), - ('title', DCT.title, None, Literal), - ('endpoint_description', DCAT.endpointDescription, None, Literal), - ('description', DCT.description, None, Literal), - ] - - self._add_triples_from_dict(access_service_dict, access_service_node, items) + try: + access_service_list = json.loads(resource_dict.get('access_services', '[]')) + # Access service + for access_service_dict in access_service_list: - # Lists - items = [ - ('endpoint_url', DCAT.endpointURL, None, URIRefOrLiteral), - ('serves_dataset', DCAT.servesDataset, None, URIRefOrLiteral), - ] - self._add_list_triples_from_dict(access_service_dict, access_service_node, items) - - if access_service_list: - resource_dict['access_services'] = json.dumps(access_service_list) - except ValueError: - pass + access_service_uri = access_service_dict.get('uri') + if access_service_uri: + access_service_node = CleanedURIRef(access_service_uri) + else: + access_service_node = BNode() + # Remember the (internal) access service reference for referencing in + # further profiles + access_service_dict['access_service_ref'] = str(access_service_node) + + self.g.add((distribution, DCAT.accessService, access_service_node)) + + self.g.add((access_service_node, RDF.type, DCAT.DataService)) + + # Simple values + items = [ + ('availability', DCATAP.availability, None, URIRefOrLiteral), + ('license', DCT.license, None, URIRefOrLiteral), + ('access_rights', DCT.accessRights, None, URIRefOrLiteral), + ('title', DCT.title, None, Literal), + ('endpoint_description', DCAT.endpointDescription, None, Literal), + ('description', DCT.description, None, Literal), + ] + + self._add_triples_from_dict(access_service_dict, access_service_node, items) + + # Lists + items = [ + ('endpoint_url', DCAT.endpointURL, None, URIRefOrLiteral), + ('serves_dataset', DCAT.servesDataset, None, URIRefOrLiteral), + ] + self._add_list_triples_from_dict(access_service_dict, access_service_node, items) + + if access_service_list: + resource_dict['access_services'] = json.dumps(access_service_list) + except ValueError: + pass + return distribution def graph_from_catalog(self, catalog_dict, catalog_ref): @@ -1716,6 +1774,14 @@ def graph_from_catalog(self, catalog_dict, catalog_ref): super(EuropeanDCATAP2Profile, self).graph_from_catalog(catalog_dict, catalog_ref) +class EuropeanDCATAPHVD220Profile(EuropeanDCATAP2Profile): + ''' Read only catalog output for the HVD Profile, that only includes HVD resources ''' + def graph_from_resource(self, g, dataset_ref, resource_dict, resource_license_fallback, distribution=None): + if 'http://data.europa.eu/eli/reg_impl/2023/138/oj' in \ + self._read_list_value(self._get_dataset_value(resource_dict, 'applicable_legislation')): + return super().graph_from_resource(g, dataset_ref, resource_dict, resource_license_fallback, distribution) + + class SchemaOrgProfile(RDFProfile): ''' An RDF profile based on the schema.org Dataset diff --git a/ckanext/dcat/tests/shaql/README.md b/ckanext/dcat/tests/shaql/README.md new file mode 100644 index 00000000..9fb26dc9 --- /dev/null +++ b/ckanext/dcat/tests/shaql/README.md @@ -0,0 +1 @@ +These directories have SHAQL shapes to validate the DCAT compliance. \ No newline at end of file diff --git a/ckanext/dcat/tests/shaql/hvd/LICENSE.md b/ckanext/dcat/tests/shaql/hvd/LICENSE.md new file mode 100644 index 00000000..706653c9 --- /dev/null +++ b/ckanext/dcat/tests/shaql/hvd/LICENSE.md @@ -0,0 +1,5 @@ +This directory was retrieved from https://github.com/SEMICeu/DCAT-AP/ + +Licence from Upstream: +Copyright © 2023 European Union. All material in this repository (https://github.com/SEMICeu/DCAT-AP/) is published under the licence CC-BY 4.0, unless explicitly otherwise mentioned. + diff --git a/ckanext/dcat/tests/shaql/hvd/README.md b/ckanext/dcat/tests/shaql/hvd/README.md new file mode 100644 index 00000000..4809da85 --- /dev/null +++ b/ckanext/dcat/tests/shaql/hvd/README.md @@ -0,0 +1,4 @@ +https://semiceu.github.io/DCAT-AP/releases/2.2.0-hvd/html/hvd-SHACL-base.ttl +https://semiceu.github.io/DCAT-AP/releases/2.2.0-hvd/html/hvd-SHACL-ranges.ttl +https://semiceu.github.io/DCAT-AP/releases/2.2.0-hvd/html/hvd-SHACL-full.ttl + diff --git a/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-base.ttl b/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-base.ttl new file mode 100644 index 00000000..7cadcc13 --- /dev/null +++ b/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-base.ttl @@ -0,0 +1,566 @@ +@prefix dc: . +@prefix dcat: . +@prefix foaf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix shacl: . +@prefix skos: . +@prefix vcard: . +@prefix xsd: . + + rdfs:member , + , + , + , + , + , + , + , + , + , + , + , + , + , + . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + ; + shacl:targetClass dcat:CatalogRecord . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:name "primary topic"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path foaf:primaryTopic; + "The expected value for primary topic is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:minCount 1; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "Minimally 1 values are expected for primary topic"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:maxCount 1; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "Maximally 1 values allowed for primary topic"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + ; + shacl:targetClass dcat:Catalog . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.dataset"; + shacl:description "A Dataset that is part of the Catalogue."@en; + shacl:name "dataset"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:dataset; + "The expected value for dataset is a rdfs:Resource (URI or blank node)"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.record"; + shacl:description "A Catalogue Record that is part of the Catalogue"@en; + shacl:name "record"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:record; + "The expected value for record is a rdfs:Resource (URI or blank node)"@en . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.service"; + shacl:description "A site or end-point (Data Service) that is listed in the Catalogue."@en; + shacl:name "service"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:service; + "The expected value for service is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dcat:Resource . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass skos:Concept . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + shacl:targetClass dcat:DataService . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointURL"; + shacl:description "The root location or primary endpoint of the service (an IRI)."@en; + shacl:name "endpoint URL"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:endpointURL; + "The expected value for endpoint URL is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for HVD category is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointdescription"; + shacl:description "A description of the services available via the end-points, including their operations, parameters etc."@en; + shacl:name "endpoint description"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:endpointDescription; + "The expected value for endpoint description is a rdfs:Resource (URI or blank node)"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:minCount 1; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "Minimally 1 values are expected for contact point"@en . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointURL"; + shacl:description "The root location or primary endpoint of the service (an IRI)."@en; + shacl:minCount 1; + shacl:name "endpoint URL"@en; + shacl:path dcat:endpointURL; + "Minimally 1 values are expected for endpoint URL"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:minCount 1; + shacl:name "documentation"@en; + shacl:path foaf:Page; + "Minimally 1 values are expected for documentation"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:name "documentation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path foaf:Page; + "The expected value for documentation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:name "contact point"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:contactPoint; + "The expected value for contact point is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:description "A licence under which the Data service is made available."@en; + shacl:maxCount 1; + shacl:name "licence"@en; + shacl:path dc:license; + "Maximally 1 values allowed for licence"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.rights"; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:rights; + "The expected value for rights is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:name "serves dataset"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:servesDataset; + "The expected value for serves dataset is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:minCount 1; + shacl:name "serves dataset"@en; + shacl:path dcat:servesDataset; + "Minimally 1 values are expected for serves dataset"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:description "A licence under which the Data service is made available."@en; + shacl:name "licence"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:license; + "The expected value for licence is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:minCount 1; + shacl:name "HVD category"@en; + shacl:path ; + "Minimally 1 values are expected for HVD category"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + , + , + , + , + ; + shacl:targetClass dcat:Dataset . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.conformsto"; + shacl:description "An implementing rule or other specification."@en; + shacl:name "conforms to"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:conformsTo; + "The expected value for conforms to is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:description "An available Distribution for the Dataset."@en; + shacl:minCount 1; + shacl:name "dataset distribution"@en; + shacl:path dcat:distribution; + "Minimally 1 values are expected for dataset distribution"@en . + + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD Category"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for HVD Category is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Dataset."@en; + shacl:name "contact point"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:contactPoint; + "The expected value for contact point is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:minCount 1; + shacl:name "HVD Category"@en; + shacl:path ; + "Minimally 1 values are expected for HVD Category"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:description "An available Distribution for the Dataset."@en; + shacl:name "dataset distribution"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:distribution; + "The expected value for dataset distribution is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + , + , + , + , + ; + shacl:targetClass dcat:Distribution . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessservice"; + shacl:description "A data service that gives access to the distribution of the dataset"@en; + shacl:name "access service"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:accessService; + "The expected value for access service is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.linkedschemas"; + shacl:description "An established schema to which the described Distribution conforms."@en; + shacl:name "linked schemas"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:conformsTo; + "The expected value for linked schemas is a rdfs:Resource (URI or blank node)"@en . + + + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:maxCount 1; + shacl:name "licence"@en; + shacl:path dc:license; + "Maximally 1 values allowed for licence"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessURL"; + shacl:description "A URL that gives access to a Distribution of the Dataset."@en; + shacl:name "access URL"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:accessURL; + "The expected value for access URL is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.rights"; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:rights; + "The expected value for rights is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessURL"; + shacl:description "A URL that gives access to a Distribution of the Dataset."@en; + shacl:minCount 1; + shacl:name "access URL"@en; + shacl:path dcat:accessURL; + "Minimally 1 values are expected for access URL"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:name "licence"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:license; + "The expected value for licence is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass foaf:Document . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + , + , + , + ; + shacl:targetClass vcard:Kind . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.email"; + shacl:description """A email address via which contact can be made."""@en; + shacl:name "email"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path vcard:hasEmail; + "The expected value for email is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.contactpage"; + shacl:description "A webpage that either allows to make contact (i.e. a webform) or the information contains how to get into contact. "@en; + shacl:name "contact page"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path vcard:hasURL; + "The expected value for contact page is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.contactpage"; + shacl:description "A webpage that either allows to make contact (i.e. a webform) or the information contains how to get into contact. "@en; + shacl:maxCount 1; + shacl:name "contact page"@en; + shacl:path vcard:hasURL; + "Maximally 1 values allowed for contact page"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.email"; + shacl:description """A email address via which contact can be made."""@en; + shacl:maxCount 1; + shacl:name "email"@en; + shacl:path vcard:hasEmail; + "Maximally 1 values allowed for email"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:LicenseDocument . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass rdfs:Literal . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass rdfs:Resource . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:RightsStatement . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:Standard . + + + + rdfs:seeAlso "https://semiceu.github.io/uri.semic.eu-generated/DCAT-AP/releases/2.2.0-hvd/#Kind"; + shacl:description """It is recommended to provide at least either an email or a contact form from e.g. a service desk. """@en; + shacl:or ( + [ + shacl:path vcard:hasEmail; + shacl:minCount 1 ; + ] + [ + shacl:path vcard:hasURL; + shacl:minCount 1 ; + ] + ) ; + a shacl:NodeShape ; + shacl:targetClass vcard:Kind ; + shacl:severity shacl:Warning ; + "It is recommended to provide at least either an email or a contact form from e.g. a service desk. "@en . + + + + rdfs:seeAlso "https://semiceu.github.io/uri.semic.eu-generated/DCAT-AP/releases/2.2.0-hvd/#c3"; + shacl:description """It is mandatory to provide legal information."""@en; + shacl:or ( + [ + shacl:path dc:license; + shacl:minCount 1 ; + ] + [ + shacl:path dc:rights; + shacl:minCount 1 ; + ] + ) ; + a shacl:NodeShape ; + shacl:targetClass dcat:Distribution; + "It is mandatory to provide legal information."@en . + + rdfs:seeAlso "https://semiceu.github.io/uri.semic.eu-generated/DCAT-AP/releases/2.2.0-hvd/#c3"; + shacl:description """It is mandatory to provide legal information."""@en; + shacl:or ( + [ + shacl:path dc:license; + shacl:minCount 1 ; + ] + [ + shacl:path dc:rights; + shacl:minCount 1 ; + ] + ) ; + a shacl:NodeShape ; + shacl:targetClass dcat:DataService; + "It is mandatory to provide legal information."@en . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdf:type owl:Ontology ; + owl:imports . + + + a shacl:NodeShape ; + rdfs:comment "HVD Category Restriction" ; + rdfs:label "HVD Category Restriction" ; + shacl:property [ + shacl:hasValue ; + shacl:minCount 1 ; + shacl:nodeKind shacl:IRI ; + shacl:path skos:inScheme + ] . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDcategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + shacl:node ; + "The range of HVD category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + shacl:node ; + "The range of HVD category must be of type ."@en . diff --git a/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-full.ttl b/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-full.ttl new file mode 100644 index 00000000..b5bf7b9b --- /dev/null +++ b/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-full.ttl @@ -0,0 +1,712 @@ +@prefix dc: . +@prefix dcat: . +@prefix foaf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix shacl: . +@prefix skos: . +@prefix vcard: . +@prefix xsd: . + + rdfs:member , + , + , + , + , + , + , + , + , + , + , + , + , + , + . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + ; + shacl:targetClass dcat:CatalogRecord . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:name "primary topic"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path foaf:primaryTopic; + "The expected value for primary topic is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:minCount 1; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "Minimally 1 values are expected for primary topic"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:class dcat:Resource; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "The range of primary topic must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:maxCount 1; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "Maximally 1 values allowed for primary topic"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + ; + shacl:targetClass dcat:Catalog . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.dataset"; + shacl:description "A Dataset that is part of the Catalogue."@en; + shacl:name "dataset"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:dataset; + "The expected value for dataset is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.record"; + shacl:class dcat:CatalogRecord; + shacl:description "A Catalogue Record that is part of the Catalogue"@en; + shacl:name "record"@en; + shacl:path dcat:record; + "The range of record must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.record"; + shacl:description "A Catalogue Record that is part of the Catalogue"@en; + shacl:name "record"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:record; + "The expected value for record is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.dataset"; + shacl:class dcat:Dataset; + shacl:description "A Dataset that is part of the Catalogue."@en; + shacl:name "dataset"@en; + shacl:path dcat:dataset; + "The range of dataset must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.service"; + shacl:class dcat:DataService; + shacl:description "A site or end-point (Data Service) that is listed in the Catalogue."@en; + shacl:name "service"@en; + shacl:path dcat:service; + "The range of service must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.service"; + shacl:description "A site or end-point (Data Service) that is listed in the Catalogue."@en; + shacl:name "service"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:service; + "The expected value for service is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dcat:Resource . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass skos:Concept . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + shacl:targetClass dcat:DataService . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:class dcat:Dataset; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:name "serves dataset"@en; + shacl:path dcat:servesDataset; + "The range of serves dataset must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:class skos:Concept; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + "The range of HVD category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointURL"; + shacl:description "The root location or primary endpoint of the service (an IRI)."@en; + shacl:name "endpoint URL"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:endpointURL; + "The expected value for endpoint URL is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for HVD category is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointdescription"; + shacl:description "A description of the services available via the end-points, including their operations, parameters etc."@en; + shacl:name "endpoint description"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:endpointDescription; + "The expected value for endpoint description is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:class foaf:Document; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:name "documentation"@en; + shacl:path foaf:Page; + "The range of documentation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:minCount 1; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "Minimally 1 values are expected for contact point"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:class ; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:name "applicable legislation"@en; + shacl:path ; + "The range of applicable legislation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:class vcard:Kind; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "The range of contact point must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointURL"; + shacl:description "The root location or primary endpoint of the service (an IRI)."@en; + shacl:minCount 1; + shacl:name "endpoint URL"@en; + shacl:path dcat:endpointURL; + "Minimally 1 values are expected for endpoint URL"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:minCount 1; + shacl:name "documentation"@en; + shacl:path foaf:Page; + "Minimally 1 values are expected for documentation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.rights"; + shacl:class dc:RightsStatement; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:path dc:rights; + "The range of rights must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:name "documentation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path foaf:Page; + "The expected value for documentation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:name "contact point"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:contactPoint; + "The expected value for contact point is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:description "A licence under which the Data service is made available."@en; + shacl:maxCount 1; + shacl:name "licence"@en; + shacl:path dc:license; + "Maximally 1 values allowed for licence"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.rights"; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:rights; + "The expected value for rights is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:name "serves dataset"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:servesDataset; + "The expected value for serves dataset is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:class dc:LicenseDocument; + shacl:description "A licence under which the Data service is made available."@en; + shacl:name "licence"@en; + shacl:path dc:license; + "The range of licence must be of type ."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:minCount 1; + shacl:name "serves dataset"@en; + shacl:path dcat:servesDataset; + "Minimally 1 values are expected for serves dataset"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:description "A licence under which the Data service is made available."@en; + shacl:name "licence"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:license; + "The expected value for licence is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:minCount 1; + shacl:name "HVD category"@en; + shacl:path ; + "Minimally 1 values are expected for HVD category"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + shacl:targetClass dcat:Dataset . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.conformsto"; + shacl:description "An implementing rule or other specification."@en; + shacl:name "conforms to"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:conformsTo; + "The expected value for conforms to is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:class dcat:Distribution; + shacl:description "An available Distribution for the Dataset."@en; + shacl:name "dataset distribution"@en; + shacl:path dcat:distribution; + "The range of dataset distribution must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:description "An available Distribution for the Dataset."@en; + shacl:minCount 1; + shacl:name "dataset distribution"@en; + shacl:path dcat:distribution; + "Minimally 1 values are expected for dataset distribution"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:class ; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:name "applicable legislation"@en; + shacl:path ; + "The range of applicable legislation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.contactpoint"; + shacl:class vcard:Kind; + shacl:description "Contact information that can be used for sending comments about the Dataset."@en; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "The range of contact point must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:class skos:Concept; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD Category"@en; + shacl:path ; + "The range of HVD Category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD Category"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for HVD Category is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Dataset."@en; + shacl:name "contact point"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:contactPoint; + "The expected value for contact point is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:minCount 1; + shacl:name "HVD Category"@en; + shacl:path ; + "Minimally 1 values are expected for HVD Category"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.conformsto"; + shacl:class dc:Standard; + shacl:description "An implementing rule or other specification."@en; + shacl:name "conforms to"@en; + shacl:path dc:conformsTo; + "The range of conforms to must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:description "An available Distribution for the Dataset."@en; + shacl:name "dataset distribution"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:distribution; + "The expected value for dataset distribution is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + shacl:targetClass dcat:Distribution . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.linkedschemas"; + shacl:class dc:Standard; + shacl:description "An established schema to which the described Distribution conforms."@en; + shacl:name "linked schemas"@en; + shacl:path dc:conformsTo; + "The range of linked schemas must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessservice"; + shacl:description "A data service that gives access to the distribution of the dataset"@en; + shacl:name "access service"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:accessService; + "The expected value for access service is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.linkedschemas"; + shacl:description "An established schema to which the described Distribution conforms."@en; + shacl:name "linked schemas"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:conformsTo; + "The expected value for linked schemas is a rdfs:Resource (URI or blank node)"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:class ; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:name "applicable legislation"@en; + shacl:path ; + "The range of applicable legislation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessservice"; + shacl:class dcat:DataService; + shacl:description "A data service that gives access to the distribution of the dataset"@en; + shacl:name "access service"@en; + shacl:path dcat:accessService; + "The range of access service must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.rights"; + shacl:class dc:RightsStatement; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:path dc:rights; + "The range of rights must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:maxCount 1; + shacl:name "licence"@en; + shacl:path dc:license; + "Maximally 1 values allowed for licence"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessURL"; + shacl:description "A URL that gives access to a Distribution of the Dataset."@en; + shacl:name "access URL"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:accessURL; + "The expected value for access URL is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.rights"; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:rights; + "The expected value for rights is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:class dc:LicenseDocument; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:name "licence"@en; + shacl:path dc:license; + "The range of licence must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessURL"; + shacl:description "A URL that gives access to a Distribution of the Dataset."@en; + shacl:minCount 1; + shacl:name "access URL"@en; + shacl:path dcat:accessURL; + "Minimally 1 values are expected for access URL"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:name "licence"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:license; + "The expected value for licence is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass foaf:Document . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + , + , + , + ; + shacl:targetClass vcard:Kind . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.email"; + shacl:description """A email address via which contact can be made."""@en; + shacl:name "email"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path vcard:hasEmail; + "The expected value for email is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.contactpage"; + shacl:description "A webpage that either allows to make contact (i.e. a webform) or the information contains how to get into contact. "@en; + shacl:name "contact page"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path vcard:hasURL; + "The expected value for contact page is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.contactpage"; + shacl:description "A webpage that either allows to make contact (i.e. a webform) or the information contains how to get into contact. "@en; + shacl:maxCount 1; + shacl:name "contact page"@en; + shacl:path vcard:hasURL; + "Maximally 1 values allowed for contact page"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.email"; + shacl:description """A email address via which contact can be made."""@en; + shacl:maxCount 1; + shacl:name "email"@en; + shacl:path vcard:hasEmail; + "Maximally 1 values allowed for email"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:LicenseDocument . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass rdfs:Literal . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass rdfs:Resource . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:RightsStatement . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:Standard . + + + + rdfs:seeAlso "https://semiceu.github.io/uri.semic.eu-generated/DCAT-AP/releases/2.2.0-hvd/#Kind"; + shacl:description """It is recommended to provide at least either an email or a contact form from e.g. a service desk. """@en; + shacl:or ( + [ + shacl:path vcard:hasEmail; + shacl:minCount 1 ; + ] + [ + shacl:path vcard:hasURL; + shacl:minCount 1 ; + ] + ) ; + a shacl:NodeShape ; + shacl:targetClass vcard:Kind ; + shacl:severity shacl:Warning ; + "It is recommended to provide at least either an email or a contact form from e.g. a service desk. "@en . + + + + rdfs:seeAlso "https://semiceu.github.io/uri.semic.eu-generated/DCAT-AP/releases/2.2.0-hvd/#c3"; + shacl:description """It is mandatory to provide legal information."""@en; + shacl:or ( + [ + shacl:path dc:license; + shacl:minCount 1 ; + ] + [ + shacl:path dc:rights; + shacl:minCount 1 ; + ] + ) ; + a shacl:NodeShape ; + shacl:targetClass dcat:Distribution; + "It is mandatory to provide legal information."@en . + + rdfs:seeAlso "https://semiceu.github.io/uri.semic.eu-generated/DCAT-AP/releases/2.2.0-hvd/#c3"; + shacl:description """It is mandatory to provide legal information."""@en; + shacl:or ( + [ + shacl:path dc:license; + shacl:minCount 1 ; + ] + [ + shacl:path dc:rights; + shacl:minCount 1 ; + ] + ) ; + a shacl:NodeShape ; + shacl:targetClass dcat:DataService; + "It is mandatory to provide legal information."@en . + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdf:type owl:Ontology ; + owl:imports . + + + a shacl:NodeShape ; + rdfs:comment "HVD Category Restriction" ; + rdfs:label "HVD Category Restriction" ; + shacl:property [ + shacl:hasValue ; + shacl:minCount 1 ; + shacl:nodeKind shacl:IRI ; + shacl:path skos:inScheme + ] . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDcategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + shacl:node ; + "The range of HVD category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + shacl:node ; + "The range of HVD category must be of type ."@en . diff --git a/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-ranges.ttl b/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-ranges.ttl new file mode 100644 index 00000000..5c956a5a --- /dev/null +++ b/ckanext/dcat/tests/shaql/hvd/hvd-SHACL-ranges.ttl @@ -0,0 +1,618 @@ +@prefix dc: . +@prefix dcat: . +@prefix foaf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix shacl: . +@prefix skos: . +@prefix vcard: . +@prefix xsd: . + + rdfs:member , + , + , + , + , + , + , + , + , + , + , + , + , + , + . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + + ; + shacl:targetClass dcat:CatalogRecord . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:name "primary topic"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path foaf:primaryTopic; + "The expected value for primary topic is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:minCount 1; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "Minimally 1 values are expected for primary topic"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:class dcat:Resource; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "The range of primary topic must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#CatalogueRecord.primarytopic"; + shacl:description "A link to the Dataset, Data service or Catalog described in the record."@en; + shacl:maxCount 1; + shacl:name "primary topic"@en; + shacl:path foaf:primaryTopic; + "Maximally 1 values allowed for primary topic"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + , + , + ; + shacl:targetClass dcat:Catalog . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.dataset"; + shacl:description "A Dataset that is part of the Catalogue."@en; + shacl:name "dataset"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:dataset; + "The expected value for dataset is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.record"; + shacl:class dcat:CatalogRecord; + shacl:description "A Catalogue Record that is part of the Catalogue"@en; + shacl:name "record"@en; + shacl:path dcat:record; + "The range of record must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.record"; + shacl:description "A Catalogue Record that is part of the Catalogue"@en; + shacl:name "record"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:record; + "The expected value for record is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.dataset"; + shacl:class dcat:Dataset; + shacl:description "A Dataset that is part of the Catalogue."@en; + shacl:name "dataset"@en; + shacl:path dcat:dataset; + "The range of dataset must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.service"; + shacl:class dcat:DataService; + shacl:description "A site or end-point (Data Service) that is listed in the Catalogue."@en; + shacl:name "service"@en; + shacl:path dcat:service; + "The range of service must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Catalogue.service"; + shacl:description "A site or end-point (Data Service) that is listed in the Catalogue."@en; + shacl:name "service"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:service; + "The expected value for service is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dcat:Resource . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass skos:Concept . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + , + , + , + , + , + , + ; + shacl:targetClass dcat:DataService . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:class dcat:Dataset; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:name "serves dataset"@en; + shacl:path dcat:servesDataset; + "The range of serves dataset must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:class skos:Concept; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + "The range of HVD category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointURL"; + shacl:description "The root location or primary endpoint of the service (an IRI)."@en; + shacl:name "endpoint URL"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:endpointURL; + "The expected value for endpoint URL is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for HVD category is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointdescription"; + shacl:description "A description of the services available via the end-points, including their operations, parameters etc."@en; + shacl:name "endpoint description"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:endpointDescription; + "The expected value for endpoint description is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:class foaf:Document; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:name "documentation"@en; + shacl:path foaf:Page; + "The range of documentation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:minCount 1; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "Minimally 1 values are expected for contact point"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:class ; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:name "applicable legislation"@en; + shacl:path ; + "The range of applicable legislation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:class vcard:Kind; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "The range of contact point must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.endpointURL"; + shacl:description "The root location or primary endpoint of the service (an IRI)."@en; + shacl:minCount 1; + shacl:name "endpoint URL"@en; + shacl:path dcat:endpointURL; + "Minimally 1 values are expected for endpoint URL"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:minCount 1; + shacl:name "documentation"@en; + shacl:path foaf:Page; + "Minimally 1 values are expected for documentation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.rights"; + shacl:class dc:RightsStatement; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:path dc:rights; + "The range of rights must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.documentation"; + shacl:description "A page that provides additional information about the Data Service."@en; + shacl:name "documentation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path foaf:Page; + "The expected value for documentation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Data Service."@en; + shacl:name "contact point"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:contactPoint; + "The expected value for contact point is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:description "A licence under which the Data service is made available."@en; + shacl:maxCount 1; + shacl:name "licence"@en; + shacl:path dc:license; + "Maximally 1 values allowed for licence"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.rights"; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:rights; + "The expected value for rights is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:name "serves dataset"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:servesDataset; + "The expected value for serves dataset is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Data Service."@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:class dc:LicenseDocument; + shacl:description "A licence under which the Data service is made available."@en; + shacl:name "licence"@en; + shacl:path dc:license; + "The range of licence must be of type ."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.servesdataset"; + shacl:description "This property refers to a collection of data that this data service can distribute."@en; + shacl:minCount 1; + shacl:name "serves dataset"@en; + shacl:path dcat:servesDataset; + "Minimally 1 values are expected for serves dataset"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.licence"; + shacl:description "A licence under which the Data service is made available."@en; + shacl:name "licence"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:license; + "The expected value for licence is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:minCount 1; + shacl:name "HVD category"@en; + shacl:path ; + "Minimally 1 values are expected for HVD category"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + , + , + , + , + ; + shacl:targetClass dcat:Dataset . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.conformsto"; + shacl:description "An implementing rule or other specification."@en; + shacl:name "conforms to"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:conformsTo; + "The expected value for conforms to is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:class dcat:Distribution; + shacl:description "An available Distribution for the Dataset."@en; + shacl:name "dataset distribution"@en; + shacl:path dcat:distribution; + "The range of dataset distribution must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:description "An available Distribution for the Dataset."@en; + shacl:minCount 1; + shacl:name "dataset distribution"@en; + shacl:path dcat:distribution; + "Minimally 1 values are expected for dataset distribution"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:class ; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:name "applicable legislation"@en; + shacl:path ; + "The range of applicable legislation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.contactpoint"; + shacl:class vcard:Kind; + shacl:description "Contact information that can be used for sending comments about the Dataset."@en; + shacl:name "contact point"@en; + shacl:path dcat:contactPoint; + "The range of contact point must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:class skos:Concept; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD Category"@en; + shacl:path ; + "The range of HVD Category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD Category"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for HVD Category is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.contactpoint"; + shacl:description "Contact information that can be used for sending comments about the Dataset."@en; + shacl:name "contact point"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:contactPoint; + "The expected value for contact point is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDCategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:minCount 1; + shacl:name "HVD Category"@en; + shacl:path ; + "Minimally 1 values are expected for HVD Category"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.conformsto"; + shacl:class dc:Standard; + shacl:description "An implementing rule or other specification."@en; + shacl:name "conforms to"@en; + shacl:path dc:conformsTo; + "The range of conforms to must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Dataset."@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.datasetdistribution"; + shacl:description "An available Distribution for the Dataset."@en; + shacl:name "dataset distribution"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:distribution; + "The expected value for dataset distribution is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:property + , + , + , + , + ; + shacl:targetClass dcat:Distribution . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:name "applicable legislation"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path ; + "The expected value for applicable legislation is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.linkedschemas"; + shacl:class dc:Standard; + shacl:description "An established schema to which the described Distribution conforms."@en; + shacl:name "linked schemas"@en; + shacl:path dc:conformsTo; + "The range of linked schemas must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessservice"; + shacl:description "A data service that gives access to the distribution of the dataset"@en; + shacl:name "access service"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:accessService; + "The expected value for access service is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.linkedschemas"; + shacl:description "An established schema to which the described Distribution conforms."@en; + shacl:name "linked schemas"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:conformsTo; + "The expected value for linked schemas is a rdfs:Resource (URI or blank node)"@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:class ; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:name "applicable legislation"@en; + shacl:path ; + "The range of applicable legislation must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessservice"; + shacl:class dcat:DataService; + shacl:description "A data service that gives access to the distribution of the dataset"@en; + shacl:name "access service"@en; + shacl:path dcat:accessService; + "The range of access service must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.rights"; + shacl:class dc:RightsStatement; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:path dc:rights; + "The range of rights must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:maxCount 1; + shacl:name "licence"@en; + shacl:path dc:license; + "Maximally 1 values allowed for licence"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessURL"; + shacl:description "A URL that gives access to a Distribution of the Dataset."@en; + shacl:name "access URL"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dcat:accessURL; + "The expected value for access URL is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.rights"; + shacl:description "A statement that specifies rights associated with the Distribution."@en; + shacl:name "rights"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:rights; + "The expected value for rights is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The legislation that mandates the creation or management of the Distribution"@en; + shacl:minCount 1; + shacl:name "applicable legislation"@en; + shacl:path ; + "Minimally 1 values are expected for applicable legislation"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:class dc:LicenseDocument; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:name "licence"@en; + shacl:path dc:license; + "The range of licence must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.accessURL"; + shacl:description "A URL that gives access to a Distribution of the Dataset."@en; + shacl:minCount 1; + shacl:name "access URL"@en; + shacl:path dcat:accessURL; + "Minimally 1 values are expected for access URL"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.licence"; + shacl:description "A licence under which the Distribution is made available."@en; + shacl:name "licence"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path dc:license; + "The expected value for licence is a rdfs:Resource (URI or blank node)"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass foaf:Document . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass vcard:Kind . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.email"; + shacl:description """A email address via which contact can be made."""@en; + shacl:name "email"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path vcard:hasEmail; + "The expected value for email is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.contactpage"; + shacl:description "A webpage that either allows to make contact (i.e. a webform) or the information contains how to get into contact. "@en; + shacl:name "contact page"@en; + shacl:nodeKind shacl:BlankNodeOrIRI; + shacl:path vcard:hasURL; + "The expected value for contact page is a rdfs:Resource (URI or blank node)"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.contactpage"; + shacl:description "A webpage that either allows to make contact (i.e. a webform) or the information contains how to get into contact. "@en; + shacl:maxCount 1; + shacl:name "contact page"@en; + shacl:path vcard:hasURL; + "Maximally 1 values allowed for contact page"@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Kind.email"; + shacl:description """A email address via which contact can be made."""@en; + shacl:maxCount 1; + shacl:name "email"@en; + shacl:path vcard:hasEmail; + "Maximally 1 values allowed for email"@en . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:LicenseDocument . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass rdfs:Literal . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass rdfs:Resource . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:RightsStatement . + + a shacl:NodeShape; + shacl:closed false; + shacl:targetClass dc:Standard . + + + + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Distribution.applicablelegislation"; + shacl:description "The applicable legislation must be set to the HVD IR ELI."@en; + shacl:path ; + shacl:hasValue ; + "The applicable legislation must be set to the HVD IR ELI."@en . + + + rdf:type owl:Ontology ; + owl:imports . + + + a shacl:NodeShape ; + rdfs:comment "HVD Category Restriction" ; + rdfs:label "HVD Category Restriction" ; + shacl:property [ + shacl:hasValue ; + shacl:minCount 1 ; + shacl:nodeKind shacl:IRI ; + shacl:path skos:inScheme + ] . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#Dataset.HVDcategory"; + shacl:description "The HVD category to which this Dataset belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + shacl:node ; + "The range of HVD category must be of type ."@en . + + rdfs:seeAlso "https://semiceu.github.io//DCAT-AP/releases/2.2.0-hvd#DataService.HVDcategory"; + shacl:description "The HVD category to which this Data Service belongs."@en; + shacl:name "HVD category"@en; + shacl:path ; + shacl:node ; + "The range of HVD category must be of type ."@en . diff --git a/ckanext/dcat/utils.py b/ckanext/dcat/utils.py index 9500c87e..81421121 100644 --- a/ckanext/dcat/utils.py +++ b/ckanext/dcat/utils.py @@ -431,11 +431,15 @@ def read_catalog_page(_format): if _profiles: _profiles = _profiles.split(',') + fq = toolkit.request.params.get('fq') + if _profiles and 'euro_dcat_ap_hvd_220' in _profiles: + fq = 'extras_applicable_legislation:"http://data.europa.eu/eli/reg_impl/2023/138/oj"' + data_dict = { 'page': toolkit.request.params.get('page'), 'modified_since': toolkit.request.params.get('modified_since'), 'q': toolkit.request.params.get('q'), - 'fq': toolkit.request.params.get('fq'), + 'fq': fq, 'format': _format, 'profiles': _profiles, } diff --git a/setup.py b/setup.py index fda14619..b74ad09d 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,13 @@ install_requires=[ # -*- Extra requirements: -*- ], + extras_require={ + 'dev': [ + # ttll shaql validation of dcat schemas, + 'pyshacl==0.19.1', # version pinned for rdflib + ] + }, + entry_points=''' [ckan.plugins] @@ -43,6 +50,7 @@ [ckan.rdf.profiles] euro_dcat_ap=ckanext.dcat.profiles:EuropeanDCATAPProfile euro_dcat_ap_2=ckanext.dcat.profiles:EuropeanDCATAP2Profile + euro_dcat_ap_hvd_220=ckanext.dcat.profiles:EuropeanDCATAPHVD220Profile schemaorg=ckanext.dcat.profiles:SchemaOrgProfile [babel.extractors]