Skip to content

Commit

Permalink
enabled layer to graph export in more formats than rdf
Browse files Browse the repository at this point in the history
  • Loading branch information
situx committed Feb 20, 2024
1 parent 78e100f commit aa2dd3b
Show file tree
Hide file tree
Showing 4 changed files with 279 additions and 314 deletions.
49 changes: 49 additions & 0 deletions tasks/processing/convertlayertask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

from ...util.export.data.exporter.layer.layerexporter import LayerExporter
from qgis.utils import iface
from qgis.core import Qgis,QgsTask, QgsMessageLog
from qgis.PyQt.QtWidgets import QMessageBox

MESSAGE_CATEGORY = 'ConvertLayerTask'

class ConvertLayerTask(QgsTask):

def __init__(self, description, layer, filename, vocabulary, literaltype, prefixes, dialog, progress):
super().__init__(description, QgsTask.CanCancel)
self.exception = None
self.progress = progress
self.filename = filename
self.prefixes=prefixes
self.vocabulary = vocabulary
self.layer= layer
self.literaltype = literaltype
self.dialog = dialog


def run(self):
fileext=self.filename[0][self.filename[0].rfind('.')+1:].upper()
ttlstring = LayerExporter.layerToTTLString(self.layer,
self.prefixes,
self.vocabulary, self.literaltype,
None, None, None, None, None, None)
QgsMessageLog.logMessage('Started task "{}"'.format(
fileext),
"Convert Layer Dialog", Qgis.Info)
with open(self.filename[0], 'w') as output_file:
LayerExporter.exportToFormat(ttlstring, output_file, self.filename[0], fileext,self.prefixes)
return True

def finished(self, result):
self.progress.close()
if result == True:
iface.messageBar().pushMessage("Exported layer successfully to " + str(self.filename[0]) + "!", "OK",
level=Qgis.Success)
msgBox = QMessageBox()
msgBox.setText("Layer converted to and saved as "+str(self.filename[0]))
msgBox.exec()
else:
msgBox = QMessageBox()
msgBox.setText("An error occurred while converting the layer converted to "+str(self.filename[0]))
msgBox.exec()


235 changes: 229 additions & 6 deletions util/export/data/exporter/layer/layerexporter.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,247 @@

import json
import uuid
import re

import urllib.parse
from ....srs.crsexporttools import ConvertCRS
from ..exporterutils import ExporterUtils
from .....layerutils import LayerUtils
from .....sparqlutils import SPARQLUtils
from qgis.core import Qgis,QgsTask, QgsMessageLog

from rdflib import Graph

class LayerExporter:


class LayerExporter:

@staticmethod
def exportToFormat(layer,format,prefixes):
layerToTTL=LayerUtils.layerToTTLString(layer,prefixes)
def exportToFormat(layerOrTTLString,file,filename,format,prefixes):
if isinstance(layerOrTTLString, str):
layerToTTL=layerOrTTLString
else:
layerToTTL=LayerUtils.layerToTTLString(layerOrTTLString,prefixes)
QgsMessageLog.logMessage(str(layerToTTL),"LayerExporter", Qgis.Info)
QgsMessageLog.logMessage("Format: "+str(format), "LayerExporter", Qgis.Info)
QgsMessageLog.logMessage("File: " + str(file), "LayerExporter", Qgis.Info)
g=Graph()
g.parse(layerToTTL)
g.parse(data=layerToTTL)
g.bind("suni","http://www.github.com/sparqlunicorn#")
if format in ExporterUtils.exportToFunction:
ExporterUtils.exportToFunction[format](g,None,None,None,format.lower())
if format not in ExporterUtils.rdfformats:
ExporterUtils.exportToFunction[format](g,file,None,None,format.lower())
else:
ExporterUtils.exportToFunction[format](g,filename,None,None,format.lower())




## Converts a QGIS layer to TTL with or without a given column mapping.
# @param self The object pointer.
# @param layer The layer to convert.
@staticmethod
def layerToTTLString(layer, prefixes, vocab="GeoSPARQL", literaltype=["WKT"], urilist=None, classurilist=None,
includelist=None, proptypelist=None,
valuemappings=None, valuequeries=None, exportNameSpace=None, exportIdCol=None,
exportSetClass=None):
fieldnames = [field.name() for field in layer.fields()]
# QgsMessageLog.logMessage("FIELDNAMES: "+str(fieldnames),
# MESSAGE_CATEGORY, Qgis.Info)
# QgsMessageLog.logMessage("FIELDNAMES: "+str(vocab),
# MESSAGE_CATEGORY, Qgis.Info)
ttlstring = set()
first = 0
if exportNameSpace == None or exportNameSpace == "":
namespace = "http://www.github.com/sparqlunicorn#"
else:
namespace = exportNameSpace
if exportIdCol == "":
idcol = "id"
else:
idcol = exportIdCol
classcol = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
curid = ""
if exportSetClass == None or exportSetClass == "":
curclassid = namespace + str(uuid.uuid4())
elif exportSetClass.startswith("http"):
curclassid = exportSetClass
else:
curclassid = urllib.parse.quote(exportSetClass)
layercrs = layer.crs()
ttlstring.add("<http://www.opengis.net/ont/crs/" + str(layercrs.authid()).replace(" ",
"_") + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.opengis.net/ont/crs/SpatialReferenceSystem> .\n")
ttlstring.add("<http://www.opengis.net/ont/crs/" + str(layercrs.authid()).replace(" ",
"_") + "> <http://www.opengis.net/ont/crs/asWKT> \"" + str(
layercrs.toWkt()).replace("\"", "\\\"") + "\"^^<http://www.opengis.net/ont/crs/wktLiteral> .\n")
ttlstring.add("<http://www.opengis.net/ont/crs/" + str(layercrs.authid()).replace(" ",
"_") + "> <http://www.opengis.net/ont/crs/asProj> \"" + str(
layercrs.toProj4()) + "\"^^<http://www.opengis.net/ont/crs/proj4Literal> .\n")
ccrs = ConvertCRS()
ttlstring = ccrs.convertCRSFromWKTStringSet(layercrs.toWkt(), ttlstring)
init = True
for f in layer.getFeatures():
geom = f.geometry()
if idcol not in fieldnames:
curid = namespace + str(uuid.uuid4())
elif not str(f[idcol]).startswith("http"):
curid = namespace + str(f[idcol])
else:
curid = f[idcol]
if classcol not in fieldnames:
ttlstring.add(
"<" + str(curid) + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <" + curclassid + "> .\n")
if first == 0:
ttlstring.add("<" + str(
curclassid) + "> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#Feature> .\n")
ttlstring.add("<" + str(
curclassid) + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n")
else:
curclassid = f["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"]
ttlstring = LayerUtils.exportGeometryType(curid, geom, vocab, literaltype, init, ttlstring)
if init:
init = False
fieldcounter = -1
for propp in fieldnames:
fieldcounter += 1
# if fieldcounter>=len(fieldnames):
# fieldcounter=0
if includelist != None and fieldcounter < len(includelist) and includelist[fieldcounter] == False:
continue
prop = propp
print(str(fieldcounter))
print(str(urilist) + "\n")
print(str(classurilist) + "\n")
print(str(includelist) + "\n")
if urilist != None and urilist[fieldcounter] != "":
print(urilist)
if not urilist[fieldcounter].startswith("http"):
print("Does not start with http")
prop = urllib.parse.quote(urilist[fieldcounter])
else:
prop = urilist[fieldcounter]
print("New Prop from list: " + str(prop))
if prop == "id":
continue
if not prop.startswith("http"):
prop = namespace + prop
if prop == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" and "http" in str(f[propp]):
ttlstring.add(
"<" + str(f[propp]) + "> <" + str(prop) + "> <http://www.w3.org/2002/07/owl#Class> .\n")
ttlstring.add("<" + str(f[
propp]) + "> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#Feature> .\n")
ttlstring.add("<" + str(curid) + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <" + str(
f[propp]) + "> .\n")
# elif urilist!=None and fieldcounter<len(urilist) and urilist[fieldcounter]!="":
# ttlstring+="<"+curid+"> <"+prop+"> <"+str(f[propp])+"> .\n"
# if first<10:
# ttlstring+="<"+prop+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .\n"
# ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#domain> <"+curclassid+"> .\n"
# if classurilist[fieldcounter]!="":
# ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#range> <"+classurilist[fieldcounter]+"> .\n"
elif prop == "http://www.w3.org/2000/01/rdf-schema#label" or prop == "http://www.w3.org/2000/01/rdf-schema#comment" or (
proptypelist != None and proptypelist[fieldcounter] == "AnnotationProperty"):
ttlstring.add("<" + curid + "> <" + prop + "> \"" + str(f[propp]).replace('"',
'\\"') + "\"^^<http://www.w3.org/2001/XMLSchema#string> .\n")
if first < 10:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#AnnotationProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
elif not f[propp] or f[propp] == None or f[propp] == "":
continue
elif proptypelist != None and proptypelist[fieldcounter] == "SubClass":
ttlstring.add(
"<" + curid + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <" + str(f[propp]) + "> .\n")
ttlstring.add(
"<" + curid + "> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <" + curclassid + "> .\n")
if first < 10:
ttlstring.add("<" + str(f[
propp]) + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n")
elif valuequeries != None and propp in valuequeries:
# ttlstring += ""
results = SPARQLUtils.executeQuery(valuequeries[propp][1], "".join(
prefixes + valuequeries[propp][0].replace("%%" + propp + "%%", "\"" + str(f[propp]) + "\"")))
ttlstring.add(
"<" + curid + "> <" + prop + "> <" + results["results"]["bindings"][0]["item"]["value"] + "> .")
if first < 10:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
if classurilist[fieldcounter] != "":
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#range> <" + classurilist[
fieldcounter] + "> .\n")
elif valuemappings != None and propp in valuemappings and f[propp] in valuemappings[propp]:
ttlstring.add("<" + curid + "> <" + prop + "> <" + str(valuemappings[propp][f[propp]]) + "> .\n")
if first < 10:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
if classurilist[fieldcounter] != "":
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#range> <" + classurilist[
fieldcounter] + "> .\n")
elif "http" in str(f[propp]) or (
proptypelist != None and proptypelist[fieldcounter] == "ObjectProperty"):
ttlstring.add("<" + curid + "> <" + prop + "> <" + str(f[propp]) + "> .\n")
if first < 10:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
if classurilist != None and fieldcounter < len(classurilist) and classurilist[
fieldcounter] != "":
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#range> <" + classurilist[
fieldcounter] + "> .\n")
elif re.match(r'^-?\d+$', str(f[propp])):
ttlstring.add("<" + curid + "> <" + prop + "> \"" + str(
f[propp]) + "\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n")
if first < 10:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2001/XMLSchema#integer> .\n")
elif re.match(r'^-?\d+(?:\.\d+)?$', str(f[propp])):
ttlstring.add("<" + curid + "> <" + prop + "> \"" + str(
f[propp]) + "\"^^<http://www.w3.org/2001/XMLSchema#double> .\n")
if first:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2001/XMLSchema#double> .\n")
else:
ttlstring.add("<" + curid + "> <" + prop + "> \"" + str(f[propp]).replace('"',
'\\"') + "\"^^<http://www.w3.org/2001/XMLSchema#string> .\n")
if first < 10:
ttlstring.add(
"<" + prop + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#domain> <" + curclassid + "> .\n")
ttlstring.add(
"<" + prop + "> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2001/XMLSchema#string> .\n")
if first < 10:
first = first + 1
return ccrs.ttlhead + "".join(ttlstring)


@staticmethod
def layerToDot(layer, prefixes, urilist=None, classurilist=None, includelist=None, proptypelist=None,
valuemappings=None, valuequeries=None,exportNameSpace=None,exportIdCol=None,exportSetClass=None):
ttlstring=LayerUtils.layerToTTLString(layer, prefixes, urilist, classurilist, includelist, proptypelist,
valuemappings, valuequeries,exportNameSpace,exportIdCol,exportSetClass)
#g=Graph()
#g.parse(data=ttlstring,format="ttl")
#stream = io.StringIO()
#rdf2dot(g, stream)
return ""#stream.getvalue()

@staticmethod
def layerToGraphML(layer):
fieldnames = [field.name() for field in layer.fields()]
Expand Down
2 changes: 1 addition & 1 deletion util/export/data/exporter/rdf/graphexporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def convertTTLToGEXF(g,file,subjectstorender,classlist=None,formatt="gexf"):
for tup in g.predicate_objects(sub):
if isinstance(tup[1],Literal):
if str(tup[1]) not in uriToNodeId:
file.write("<node id=\"" + str(nodecounter) + "\" value=\""+str(str(tup[1]).replace("<","&lt;").replace(">","&gt;").replace("&","&amp;"))+"\" label=\"" + str(str(tup[1]).replace("<","&lt;").replace(">","&gt;").replace("&","&amp;")) + "\">\n")
file.write("<node id=\"" + str(nodecounter) + "\" value=\""+str(str(tup[1]).replace("<","&lt;").replace(">","&gt;").replace("&","&amp;").replace("\"","'"))+"\" label=\"" + str(str(tup[1]).replace("<","&lt;").replace(">","&gt;").replace("&","&amp;").replace("\"","'")) + "\">\n")
if str(tup[0]) == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type":
file.write("<viz:color r=\"255\" g=\"165\" b=\"0\"/>\n")
else:
Expand Down
Loading

0 comments on commit aa2dd3b

Please sign in to comment.