Repository: Informasjonsforvaltning/fdk-rdf-parser

Issue:
ny assosiativ relasjon fra skos-ap-no v2.0.3
ref https://data.norge.no/specification/skos-ap-no-begrep#Begrep-er-fra-begrep-i og https://data.norge.no/specification/skos-ap-no-begrep#Assosiativ-begrepsrelasjon

- predikat for angivelse av assosiativ relasjon endres fra `skosno:assosiativRelasjon` til `skosno:isFromConceptIn`
- type endres fra `skosno:AssosiativRelasjon` til `skosno:AssociativeConceptRelation` (har ikke effekt i parse-kode)
- predikat for assosiert begrep endres fra `skos:related` til `skosno:hasToConcept`
- predikat for tilhørende tekst endres fra `dct:description` til `skosno:relationRole` (løst av https://github.com/Informasjonsforvaltning/fdk-rdf-parser/pull/292)

````
<etBegrep> a skos:Concept ;
  skosno:isFromConceptIn [ a skosno:AssociativeConceptRelation ;
    skosno:relationRole "årsak-virkning"@nb ;
    skosno:hasToConcept <etAnnetBegrep> ;
  ] .
````
er ekvivalent med dette fra gammel skos-ap-no:
````
<etBegrep> a skos:Concept ;
  skosno:assosiativRelasjon [ a skosno:AssosiativRelasjon ;
    dct:description "årsak-virkning"@nb ;
    skos:related <etAnnetBegrep> ;
  ] .
````

tldr: det er to ting som må endres:
- predikat for angivelse av assosiert relasjon må støtte både `skosno:assosiativRelasjon` og `skosno:isFromConceptIn`
- predikat for angivelse av det relaterte begrepet skal være `skos:related` for gammel skos og `skosno:hasToConcept` for ny skos

Discussion:
github-actions[bot]: ```
Warning: poetry-plugin-export will not be installed by default in a future version of Poetry.
In order to avoid a breaking change and make your automation forward-compatible, please install poetry-plugin-export explicitly. See https://python-poetry.org/docs/plugins/#using-plugins for details on how to install a plugin.
To disable this warning run 'poetry config warnings.export false'.
The `--dev` option is deprecated, use the `--with dev` notation instead.
+==============================================================================+

                                   /$$$$$$            /$$
                                  /$$__  $$          | $$
               /$$$$$$$  /$$$$$$ | $$  \__//$$$$$$  /$$$$$$   /$$   /$$
              /$$_____/ |____  $$| $$$$   /$$__  $$|_  $$_/  | $$  | $$
             |  $$$$$$   /$$$$$$$| $$_/  | $$$$$$$$  | $$    | $$  | $$
              \____  $$ /$$__  $$| $$    | $$_____/  | $$ /$$| $$  | $$
              /$$$$$$$/|  $$$$$$$| $$    |  $$$$$$$  |  $$$$/|  $$$$$$$
             |_______/  \_______/|__/     \_______/   \___/   \____  $$
                                                              /$$  | $$
                                                             |  $$$$$$/
      by safetycli.com                                        \______/

+==============================================================================+

 REPORT 

  Safety is using PyUp's free open-source vulnerability database. This
data is 30 days old and limited. 
  For real-time enhanced vulnerability data, fix recommendations, severity
reporting, cybersecurity support, team and project policy management and more
sign up at https://pyup.io or email sales@pyup.io

  Safety v3.1.0 is scanning for Vulnerabilities...
  Scanning dependencies in your files:

  -> /tmp/tmpmoxvqdlv

  Using open-source vulnerability database
  Found and scanned 72 packages
  Timestamp 2024-05-23 12:08:11
  0 vulnerabilities reported
  0 vulnerabilities ignored

+==============================================================================+

 No known security vulnerabilities found.

+==============================================================================+

  Safety is using PyUp's free open-source vulnerability database. This
data is 30 days old and limited. 
  For real-time enhanced vulnerability data, fix recommendations, severity
reporting, cybersecurity support, team and project policy management and more
sign up at https://pyup.io or email sales@pyup.io

+==============================================================================+
```
<!-- Sticky Pull Request CommentSafety result -->

Patch:
diff --git a/src/fdk_rdf_parser/parse_functions/concept.py b/src/fdk_rdf_parser/parse_functions/concept.py
index c20652a..cb07846 100644
--- a/src/fdk_rdf_parser/parse_functions/concept.py
+++ b/src/fdk_rdf_parser/parse_functions/concept.py
@@ -260,7 +260,9 @@ def parse_associative_relation(
         description=value_translations(
             graph, associative_relation_ref, skosno_uri("relationRole")
         ),
-        related=object_value(graph, associative_relation_ref, SKOS.related),
+        related=object_value(
+            graph, associative_relation_ref, skosno_uri("hasToConcept")
+        ),
     )
 
 
@@ -268,16 +270,18 @@ def extract_associative_relations(
     graph: Graph, concept_uri: URIRef
 ) -> Optional[List[AssociativeRelation]]:
     associative_relations = []
-    for associative_relation_ref in graph.objects(
-        concept_uri, skosno_uri("assosiativRelasjon")
-    ):
-        if has_value_on_predicate(
-            graph, associative_relation_ref, skosno_uri("relationRole")
+
+    if has_value_on_predicate(graph, concept_uri, skosno_uri("isFromConceptIn")):
+        for associative_relation_ref in graph.objects(
+            concept_uri, skosno_uri("isFromConceptIn")
         ):
             associative_relations.append(
                 parse_associative_relation(graph, associative_relation_ref)
             )
-        else:
+    else:
+        for associative_relation_ref in graph.objects(
+            concept_uri, skosno_uri("assosiativRelasjon")
+        ):
             associative_relations.append(
                 parse_associative_relation_deprecated(graph, associative_relation_ref)
             )


Test patch:
diff --git a/tests/test_concept.py b/tests/test_concept.py
index 7b4dc47..0d0466a 100644
--- a/tests/test_concept.py
+++ b/tests/test_concept.py
@@ -81,13 +81,9 @@ def test_parse_concepts(mock_reference_data_client: Mock) -> None:
         skosxl:prefLabel    [ a                   skosxl:Label ;
                               skosxl:literalForm  "to"@nb
                             ] ;
-        skosno:assosiativRelasjon [ rdf:type                skosno:AssosiativRelasjon ;
+        skosno:isFromConceptIn    [ rdf:type                skosno:AssociativeConceptRelation ;
                                   skosno:relationRole       "RelationRole"@nb ;
-                                  skos:related  <http://begrepskatalogen/begrep/organisasjon>
-                                ] ;
-        skosno:assosiativRelasjon [ rdf:type                skosno:AssosiativRelasjon ;
-                                  dct:description         "Beskrivelse"@nb ;
-                                  skos:related  <http://begrepskatalogen/begrep/virksomhet>
+                                  skosno:hasToConcept  <http://begrepskatalogen/begrep/organisasjon>
                                 ] ;
         skosno:partitivRelasjon [ rdf:type                    skosno:PartitivRelasjon ;
                                   dct:description  "Inndelingskriterium"@nb ;
@@ -123,6 +119,9 @@ def test_parse_concepts(mock_reference_data_client: Mock) -> None:
         dct:modified       "2020-09-08"^^xsd:date ;
         dct:publisher      <https://data.brreg.no/enhetsregisteret/api/enheter/910258028> ;
         dct:subject        [ ] ;
+        skosno:assosiativRelasjon    [ rdf:type                skosno:AssosiativRelasjon ;
+                                       dct:description         "Beskrivelse"@nb ;
+                                       skos:related  <http://begrepskatalogen/begrep/virksomhet> ] ;
         euvoc:status       "status nb" , "status en"@en ;
         skosxl:altLabel    [ a                   skosxl:Label ;
                              skosxl:literalForm  "stabilisator"@nb
@@ -302,6 +301,11 @@ def test_parse_concepts(mock_reference_data_client: Mock) -> None:
                 ],
             ),
             definitions=[
+                Definition(
+                    text={"nb": "def-2"},
+                    targetGroup="https://data.norge.no/vocabulary/audience-type#public",
+                    sourceRelationship="https://data.norge.no/vocabulary/relationship-with-source-type#self-composed",
+                ),
                 Definition(
                     text={"nb": "def-1"},
                     sourceRelationship="https://data.norge.no/vocabulary/relationship-with-source-type#self-composed",
@@ -311,21 +315,12 @@ def test_parse_concepts(mock_reference_data_client: Mock) -> None:
                         )
                     ],
                 ),
-                Definition(
-                    text={"nb": "def-2"},
-                    targetGroup="https://data.norge.no/vocabulary/audience-type#public",
-                    sourceRelationship="https://data.norge.no/vocabulary/relationship-with-source-type#self-composed",
-                ),
             ],
             associativeRelation=[
                 AssociativeRelation(
                     description={"nb": "RelationRole"},
                     related="http://begrepskatalogen/begrep/organisasjon",
-                ),
-                AssociativeRelation(
-                    description={"nb": "Beskrivelse"},
-                    related="http://begrepskatalogen/begrep/virksomhet",
-                ),
+                )
             ],
             partitiveRelation=[
                 PartitiveRelation(
@@ -369,6 +364,12 @@ def test_parse_concepts(mock_reference_data_client: Mock) -> None:
             ),
             prefLabel={"nb": "midtbaneanker"},
             status={"nb": "status nb", "en": "status en"},
+            associativeRelation=[
+                AssociativeRelation(
+                    description={"nb": "Beskrivelse"},
+                    related="http://begrepskatalogen/begrep/virksomhet",
+                ),
+            ],
             altLabel=[{"nb": "stabilisator"}],
             definition=Definition(text={"nb": "ugyldig-audience-og-forholdtilkilde"}),
             definitions=[
@@ -501,10 +502,10 @@ def test_parse_concepts(mock_reference_data_client: Mock) -> None:
                 )
             ],
             seeAlso={
-                "http://begrepskatalogen/begrep/be5d8b8b-c3fb-11e9-8d53-005056825ca0",
                 "http://begrepskatalogen/begrep/20b2e2ab-9fe1-11e5-a9f8-e4115b280940",
-                "https://registrering-begrep-api.staging.fellesdatakatalog.digdir.no/910258028/3609b02d-72c5-47e0-a6b8-df0a503cf190",
                 "http://begrepskatalogen/begrep/20b2e2aa-9fe1-11e5-a9f8-e4115b280940",
+                "http://begrepskatalogen/begrep/be5d8b8b-c3fb-11e9-8d53-005056825ca0",
+                "https://registrering-begrep-api.staging.fellesdatakatalog.digdir.no/910258028/3609b02d-72c5-47e0-a6b8-df0a503cf190",
             },
             isReplacedBy={
                 "http://begrepskatalogen/begrep/be5d8b8b-c3fb-11e9-8d53-005056825ca0"