Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #22

Merged
merged 5 commits into from
Feb 13, 2025
Merged

Dev #22

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Test

on: [push, pull_request]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.9', '3.12']
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry update
- name: Build ocp2kg
run: |
poetry install --with test
- name: Test with pytest
run: |
poetry run pytest
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ RDF following the [OWL Change Ontology](https://w3id.org/def/och) model.
# How to run it?

```bash
python3 -m pip install -r requirements
python3 evol_kg.py -c path_to_change_kg.nt -m path_to_old_mapping.rml.ttl -o path_to_new_ontology.ttl -n path_output_mappings.rml.ttl
python3 -m pip install ocp2kg
python3 -m ocp2kg -c path_to_change_kg.nt -m path_to_old_mapping.rml.ttl -o path_to_new_ontology.ttl -n path_output_mappings.rml.ttl
```

Options:
Expand Down
34 changes: 34 additions & 0 deletions src/ocp2kg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from rdflib import URIRef, Graph
from .constants import *
from .evol_kg import *

def propagate(change_data, output_mappings, review_mappings, ontology=Graph()):
changes_order = (OCH_ADD_CLASS, OCH_ADD_SUBCLASS, OCH_ADD_OBJECT_PROPERTY, OCH_ADD_DATA_PROPERTY, OCH_REMOVE_CLASS,
OCH_REMOVE_SUBCLASS, OCH_REMOVE_OBJECT_PROPERTY, OCH_REMOVE_DATA_PROPERTY)

# ToDo: removing subclass action needs to be implemented
for change_type in changes_order:

q = f' SELECT DISTINCT ?change WHERE {{ ' \
f' ?change {RDF_TYPE} {URIRef(change_type)} . }}'

for change_result in change_data.query(q):
if URIRef(change_type) == URIRef(OCH_ADD_CLASS):
add_class(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_CLASS):
remove_class(change_result["change"],change_data, output_mappings, review_mappings, ontology)
elif URIRef(change_type) == URIRef(OCH_ADD_SUBCLASS):
add_super_class(change_result["change"],change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_SUBCLASS):
remove_super_class(change_result["change"],change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_ADD_OBJECT_PROPERTY):
add_object_property(change_result["change"],change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_OBJECT_PROPERTY):
remove_object_property(change_result["change"],change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_ADD_DATA_PROPERTY):
add_data_property(change_result["change"],change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_DATA_PROPERTY):
remove_data_property(change_result["change"],change_data, output_mappings)

logger.info("Changes propagated over the mapping rules, writing results...")
return output_mappings
35 changes: 4 additions & 31 deletions src/ocp2kg/__main__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

from rdflib import Graph, URIRef, Variable

from . import propagate
import yatter
from ruamel.yaml import YAML
import argparse
from ruamel.yaml import YAML
from .evol_kg import *

def define_args():
Expand Down Expand Up @@ -33,36 +33,9 @@ def define_args():

review_mappings = Graph()

changes_order = (OCH_ADD_CLASS, OCH_ADD_SUBCLASS, OCH_ADD_OBJECT_PROPERTY, OCH_ADD_DATA_PROPERTY, OCH_REMOVE_CLASS,
OCH_REMOVE_SUBCLASS, OCH_REMOVE_OBJECT_PROPERTY, OCH_REMOVE_DATA_PROPERTY)

# ToDo: removing subclass action needs to be implemented
for change_type in changes_order:

q = f' SELECT DISTINCT ?change WHERE {{ ' \
f' ?change {RDF_TYPE} {URIRef(change_type)} . }}'

for change_result in change_data.query(q):
if URIRef(change_type) == URIRef(OCH_ADD_CLASS):
add_class(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_CLASS):
remove_class(change_result["change"],change_data, ontology, output_mappings, review_mappings)
elif URIRef(change_type) == URIRef(OCH_ADD_SUBCLASS):
add_super_class(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_SUBCLASS):
remove_super_class(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_ADD_OBJECT_PROPERTY):
add_object_property(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_OBJECT_PROPERTY):
remove_object_property(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_ADD_DATA_PROPERTY):
add_data_property(change_result["change"], change_data, output_mappings)
elif URIRef(change_type) == URIRef(OCH_REMOVE_DATA_PROPERTY):
remove_data_property(change_result["change"], change_data, output_mappings)

logger.info("Changes propagated over the mapping rules, writing results...")
new_mapping = propagate(change_data, output_mappings, review_mappings,review_mappings, ontology)

output_mappings.serialize(destination=args.new_mappings_path)
new_mapping.serialize(destination=args.new_mappings_path)
review_mappings.serialize(destination="review_mappings.ttl")
yarrrml_content = yatter.inverse_translation(output_mappings)
with open(args.new_mappings_path.replace(".ttl", ".yml"), "wb") as f:
Expand Down
91 changes: 10 additions & 81 deletions src/ocp2kg/evol_kg.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
from rdflib import Graph, URIRef, Variable
from rdflib import Variable
from .constants import *

import yatter
from constants import *
from ruamel.yaml import YAML
import argparse
import pprint


# ---------------------------------------------------------------------------------------------------------------------------

def add_class(change):
def add_class(change, change_data, output_mappings):
"""
Adds a class defined in the change KG into the output_mappings.
If there is a TriplesMap that creates instances of that class, the TriplesMap is not created
Expand Down Expand Up @@ -48,7 +44,7 @@ def add_class(change):


# ---------------------------------------------------------------------------------------------------------------------------
def remove_class(change):
def remove_class(change,change_data, output_mappings, review_mappings, ontology):
"""
Remove a class defined in the change KG into the output_mappings.
If there is a TriplesMap that creates instances of that class, the TriplesMap and associated POM are removed.
Expand Down Expand Up @@ -202,7 +198,7 @@ def remove_class(change):

# ---------------------------------------------------------------------------------------------------------------------------------

def add_super_class(change):
def add_super_class(change,change_data, output_mappings):
"""
Adds a superclass and its properties into the TriplesMap that instantiate the subclass .
Args:
Expand Down Expand Up @@ -284,7 +280,7 @@ def add_super_class(change):


# --------------------------------------------------------------------------------------------------------------
def remove_super_class(change):
def remove_super_class(change,change_data, output_mappings):
"""
Removes superclass and its properties from the TriplesMap that instantiate the subclass .
Args:
Expand Down Expand Up @@ -362,7 +358,7 @@ def remove_super_class(change):
output_mappings.update(remove_super_class_pom_query)


def add_object_property(change):
def add_object_property(change,change_data, output_mappings):
"""
Adds an object property to the TriplesMap indicated in the domain. For a change in the predicate object map the domain, property and range additions are needed.
Args:
Expand Down Expand Up @@ -403,7 +399,7 @@ def add_object_property(change):


# --------------------------------------------------------------------------------------------------------------------------------------------------
def remove_object_property(change):
def remove_object_property(change, change_data, output_mappings):
"""
Removes the object property indicated in the change as property from its domain. For a change in the predicate object map the domain, property and range additions are needed.
Args:
Expand Down Expand Up @@ -448,7 +444,7 @@ def remove_object_property(change):


# -------------------------------------------------------------------------------------------------------------------------
def add_data_property(change):
def add_data_property(change,change_data, output_mappings):
"""
Adds a data property to the TriplesMap indicated in the domain. For a change in the predicate object map the domain, property and range additions are needed.
Args:
Expand Down Expand Up @@ -484,7 +480,7 @@ def add_data_property(change):


# -----------------------------------------------------------------------------------------------------------------------------------
def remove_data_property(change):
def remove_data_property(change,change_data, output_mappings):
"""
Removes the data property indicated in the change as property from its domain. For a change in the predicate object map the domain, property and range additions are needed.
Args:
Expand Down Expand Up @@ -525,70 +521,3 @@ def remove_data_property(change):


# -------------------------------------------------------------------------------------------------------------


def define_args():
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--changes_kg_path", required=True, help="Change KG following the Change Ontology")
parser.add_argument("-m", "--old_mapping_path", required=True, help="Old version of the mappings in RML")
parser.add_argument("-o", "--ontology_path", required=False, help="New version of the ontology")
parser.add_argument("-n", "--new_mappings_path", required=True, help="Output path for the generated mapping")
parser.add_argument("-y", "--yarrrml", nargs=argparse.OPTIONAL, required=False, help="Mappings are also converted into YARRRML")
return parser


if __name__ == "__main__":
logger.info("Starting the propagation of changes over the mapping rules")
args = define_args().parse_args()
change_data = Graph().parse(args.changes_kg_path, format="ttl")

if args.old_mapping_path.endswith(".yml") or args.old_mapping_path.endswith(".yaml"):
logger.info("Loading old mapping rules from YARRRML using YATTER")
output_mappings = Graph()
yaml = YAML(typ='safe', pure=True)
output_mappings.parse(yatter.translate(yaml.load(open(args.old_mapping_path)), RML_URI), format="ttl")
else:
output_mappings = Graph().parse(args.old_mapping_path, format="ttl")

if args.ontology_path:
ontology = Graph().parse(args.ontology_path)

review_mappings = Graph()

changes_order = (OCH_ADD_CLASS, OCH_ADD_SUBCLASS, OCH_ADD_OBJECT_PROPERTY, OCH_ADD_DATA_PROPERTY, OCH_REMOVE_CLASS,
OCH_REMOVE_SUBCLASS, OCH_REMOVE_OBJECT_PROPERTY, OCH_REMOVE_DATA_PROPERTY)

# ToDo: removing subclass action needs to be implemented
for change_type in changes_order:

q = f' SELECT DISTINCT ?change WHERE {{ ' \
f' ?change {RDF_TYPE} {URIRef(change_type)} . }}'

for change_result in change_data.query(q):
if URIRef(change_type) == URIRef(OCH_ADD_CLASS):
add_class(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_REMOVE_CLASS):
remove_class(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_ADD_SUBCLASS):
add_super_class(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_REMOVE_SUBCLASS):
remove_super_class(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_ADD_OBJECT_PROPERTY):
add_object_property(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_REMOVE_OBJECT_PROPERTY):
remove_object_property(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_ADD_DATA_PROPERTY):
add_data_property(change_result["change"])
elif URIRef(change_type) == URIRef(OCH_REMOVE_DATA_PROPERTY):
remove_data_property(change_result["change"])

logger.info("Changes propagated over the mapping rules, writing results...")

output_mappings.serialize(destination=args.new_mappings_path)
review_mappings.serialize(destination="review_mappings.ttl")
yarrrml_content = yatter.inverse_translation(output_mappings)
with open(args.new_mappings_path.replace(".ttl", ".yml"), "wb") as f:
yaml = YAML()
yaml.default_flow_style = False
yaml.width = 3000
yaml.dump(yarrrml_content, f)
Loading
Loading