diff --git a/README.md b/README.md index beab4b6..d9568ac 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,51 @@ # mscr-rmlgenerator -## Preconditions - 1. Iterator mappings must be one-to-one mappings i.e. only only one property is mapped for source and target. (Is this true?) +## Preconditions / limitations + 1. Iterator mappings must be one-to-one mappings i.e. only only one property is mapped for source and target AND there can be only one iterator mapping per NodeShape. The reason fro this is that there is currently no way of grouping other mappings under specific iterator mapping. TODO: Add examples (screenshots from MSCR). + 2. Subject source mapping must have only one target property (i.e. the generated subject source property) + 3. There can only be one pair of iterator/subject source mappings per SHACL shape. How significant restriction is this? + 4. If mapping include more than one source properties a mapping function must be specified. + +## Function calls + +sourceFunc +- default -> passThrough +- input: field to reference +- output: array of values in the order of source properties + +mappingFunc +- default -> passThrough +- input: array of values extracted from the source properties +- output: array of values. Exact output depends on the function. +targetFunc +- default -> passThrough +- input: array of values +- output: ? + +createArray +- create new array and add the value param +- return array + +addToArray +- add value param to the list provides through list param +- return array + +Example with two source properties. +``` +targetFunc( + mappingFunc( + addToArray( + value: + sourceFunc(valueParam: ) + ) + ) + ) +) +``` ## Pseudocode @@ -18,51 +62,218 @@ def getReferenceFormulationResource(sourceSchemaURI, inputGraph) JSON return new Resource(ql:JSONPath) -def getLogicalSourceData(g) +# Returns an ordered list of source propertyURIs that are used to reference of generate subject URIs for the given target shape +def getSubjectSourceMapping(inputGraph, targetShapeURI) + return queryResults(inputGraph, + select ?mappingURI + where + ?mappingURI a :Mapping + ?mappingURI :target/rdf:_1 ?target + ?target :id targetShapeURI + ?target :mscrType ?targetType . + filter(?targetType == "subject") + ) + +# Returns a list of values that represent all the iterator mappings in the crosswalk +def getIteratorData(g) return queryResults(g, - select ?targetProperty ?sourceProperty + select ?targetShapeURI ?sourcePropertyURI ?mappingURI where - ?mapping a :Mapping . - ?mapping :target/rdf:_1 ?target # see precondition 1 - ?mapping :source/rdf:_1 ?source - ?target :id ?targetShape . - ?source :id ?sourceProperty . - + ?mappingURI a :Mapping . + ?mappingURI :target/rdf:_1 ?target # see precondition 1 + ?mappingURI :source/rdf:_1/:id ?sourcePropertyURI + ?target :id ?targetShapeURI . ?target :mscrType ?targetType . filter(?targetType == "iterator") ) -def getLogicalSource(subjectURI, inputGraph, sourceSchemaURI) +def getLogicalSourceModel(subjectURI, inputGraph, sourceSchemaURI, sourcePropertyURI) logicalSource = new Graph() referenceFormulation = getReferenceFormulationResource(sourceSchemaURI, inputGraph) # create triples for RML LogicalSource - # What to add for rml:source? + iteratorPath = inputGraph.getPropertyValue(sourcePropertyURI, :instancePath) + + logicalSource.add(rml:referenceFormulation, referenceFormulation) + logicalSource.add(rml:iterator, iteratorPath) + # What to add for rml:source? + logicalSource.add(rml:source, ?????) return logicalSource + + +def createFunctionModel(functionValueTargetURI, functionToCallURI, paramDataList) + m = new Graph() + m.addRDF( + functionValueTargetURI, + fnml:functionValue, + [ + rr:predicateObjectMap [ + rr:predicate fno:executes; + rr:objectMap [ + rr:constant {functionToCallURI} + ]; + ]; + {for each paramData in paramDataList + rr:predicateObjectMap [ + rr:predicate {paramData.paramName}; + rr:objectMap {paramData.paramValueModel} + + ]; + } + ] + ) + return m +def createOuterFunctionModel(functionValueTargetURI, functionToCallURI, valueURI) + m = new Graph() + m.addRDF( + functionValueTargetURI, + fnml:functionValue, + [ + rr:predicateObjectMap [ + rr:predicate fno:executes; + rr:objectMap [ + rr:constant {functionToCallURI} + ]; + ]; + {for each paramData in paramDataList + rr:predicateObjectMap [ + rr:predicate :valueParameter + rr:objectMap {valueURI} + + ]; + } + ] + ) + return m + +def addSourceFuncModel(sourcePropertyInfoList, m) + latestFunctionURI = null + for(sourcePropertyInfo in sourcePropertyInfoList) + # create function call pair: source function + outer function + sourceFunctionURI = "mscr:func:passthrough" + if(sourcePropertyInfo.processing != null) + sourceFunctionURI = sourcePropertyInfo.processing.functionURI + params = sourcePropertyInfo.processing.params + + if(is first element in the sourcePropertyInfoList) { + outerFunctionURI = "mcsr:createArray" + } + else { + outerFunctionURI = "mcsr:addToArray" + } + sourceFunctionResource = generateFuncURI(sourcePropertyInfo.id, false) + outerFunctionResource = generateFuncURI(sourcePropertyInfo.id, true) + m.addModel(createFunctionModel(sourceFunctionResource, sourceFunctionURI, params)) + m.addModel(createOuterFunctionModel(outerFunctionResource, outerFunctionURI, sourceFunctionResource} + + latestFunctionURI = outerFunctionResource + return latestFunctionURI + +def addMappingFuncModel(mappingInfo, sourceFuncURI, m) + mappingFunctionURI = "mscr:func:passthrough" + if(mappingInfo.processing != null) + mappingFunctionURI = mappingInfo.processing.functionURI + mappingFunctionResource = generateFuncURI(mappingInfo.id) + m.addModel(createOuterFunctionModel(mappingFunctionResource, mappingFunctionURI, sourceFuncURI)) + return mappingFunctionResource + +def addTargetFuncModel(uri, targetPropertyInfoList, mappingFuncURI, m) + + for(targetPropertyInfo in targetPropertyInfoList) + functionURI = "mscr:func:passthrough" + if(targetPropertyInfo.processing != null) + functionURI = targetPropertyInfo.processing.functionURI + params = targetPropertyInfo.processing.params + m.addModel(createOuterFunctionModel(uri, functionURI, mappingFuncURI} -def getSubjectMap(subjectURI): -def getPredicateObjectMap(subjectURI): +def getProcessingModel(uri, inputGraph, mappingURI) + mappingInfo = getMappingInfo(mappingURI) + m = new Graph() + if(mappingInfo.processing == null && mappingInfo.source.filter(x: x.processing != null).isEmpty && mappingInfo.target.filter(x: x.processing != null).isEmpty) + # mapping does not include any kind of processing configuration + return null + + sourceFuncURI = addSourceFuncModel(mappingInfo.source, m) + mappingFuncURI = addMappingFuncModel(mappingInfo, sourceFuncURI, m) + addTargetFuncModel(uri, mappingInfo.target, mappingFuncURI, m) + return m + +def getSourcePropertyURIs(mappingURI, inputGraph) + return queryResults(inputGraph, + select ?sourcePropertyID + where + mappingURI :source/* ?sourceProperty + ?sourceProperty :id ?sourcePropertyID + ?sourceProperty :index ?index + order by ASC(?index) + ) + +# Return a graph that contains all information related to single subjectMap +def getSubjectMapModel(uri, targetShapeURI, inputGraph): + mappingURI = getSubjectSourceMapping(targetShapeURI, inputGraph) + subjectMap = new Graph() + + sourcePropertyURIs = getSourcePropertyURIs(mappingURI, inputGraph) + if(sourcePropertyURIs.isEmptyUI) + # case: blank node + else + subjectMap.addTriple(uri, rdf.type, rr:SubjectMap) + processingURI = getProcessingURI(...) + + processingModel = getProcessingModel(processingURI, inputGraph, mappingURI) + if(processingModel != null) + subjectMap.addModel(processingModel) + subjectMap.addTriple(uri, fnml:functionValue, processingURI) + else + if(sourcePropertyURIs.size() > 1) + throw new Exception("Subject source mapping without processing functions must have only one source") + sourcePath = inputGraph.getString(sourceProeprtyURIs.get(0) :instancePath) + subjectMap.addTriple(uri, rml:reference, sourcePath) + # add also rr:class ? + subjectMap.addTriple(uri, rr:tempType, rr:IRI) + return subjectMap + +# return mappingURIs for that have targets in target shape (excluding mappings to iterator and subject source) +def getPredicateObjectMapppings(targetShapeURI) + +def getPredicateObjectMapModel(subjectURI, targetShapeURI, inputGraph): + MappingMapper mapper = new MappingMapper(); + g = new Graph() + foreach(mappingURI in getPredicateObjectMapppings(targetShapeURI, inputGraph)) + mappingInfo = mapper.mapToMappingDTO(mappingURI, inputModel); + # do processing until mappingFunc + # foreach target doTargetProcessing(mappingFunc, targetIndex) + + def generateRMLFromMSCRGraph(inputGraph) + validate(inputGraph) # check if the preconditions hold sourceSchemaURI = getSourceSchemaURI(inputGraph) outputGraph = new Graph() - foreach(logicalSourceData in getLogicalSourceData(inputGraph)) - triplesMapURI = new Resource(getTriplesMapURI()) # blank node - logicalSourceURI = new Resource(getLogicalSourceURI()) - subjectMapURI = new Resource(getSubjectMapURI()) - predicateObjecMapURI = new Resource(getPredicateObjectMapURI()) + foreach(iteratorData in getIteratorData(inputGraph)) - targetShape = logicalSourceData.targetShape - sourceProperty = logicalSourceData.sourceProperty + triplesMapURI = getTriplesMapURI() + logicalSourceURI = getLogicalSourceURI() + subjectMapURI = getSubjectMapURI() + predicateObjecMapURI = getPredicateObjectMapURI() + + mappingURI = iteratorData.mappingURI + targetShapeURI = iteratorData.targetShapeURI + sourcePropertyURI = iteratorData.sourcePropertyURI - outputGraph.add(getLogicalSource(logicalSourceResource, inputGraph, sourceSchemaURI)) - outputGraph.add(rml:logicalSource, new Resource(logicalSourceURI)) + outputGraph.addModel(getLogicalSourceModel(logicalSourceURI, inputGraph, sourceSchemaURI, sourcePropertyURI)) + outputGraph.addTriple(triplesMapURI, rml:logicalSource, logicalSourceURI) - outputGraph.add(getSubjectMap(subjectMapURI)) - outputGraph.add(rr:subjectMap, new Resource(subjectMapURI)) + outputGraph.addModel( + getSubjectMapModel( + subjectMapURI + inputGraph + ) + ) + outputGraph.addTriple(triplesMapURI, rr:subjectMap, subjectMapURI) - outputGraph.add(getPredicateObjectMap(predicateObjectMapURI)) - outputGraph.add(rr:predicateObjectMap, new Resource(predicateObjectMapURI)) + outputGraph.addModel(getPredicateObjectMapModel(predicateObjectMapURI)) + outputGraph.addTriple(triplesMapURI, rr:predicateObjectMap, predicateObjectMapURI) return outputGraph ``` diff --git a/src/main/java/fi/csc/mscr/tranformation/rml/RMLGenerator2.java b/src/main/java/fi/csc/mscr/tranformation/rml/RMLGenerator2.java new file mode 100644 index 0000000..7d9cba5 --- /dev/null +++ b/src/main/java/fi/csc/mscr/tranformation/rml/RMLGenerator2.java @@ -0,0 +1,493 @@ +package fi.vm.yti.datamodel.api.v2.transformation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.vocabulary.RDF; +import org.topbraid.shacl.vocabulary.SH; + +import fi.vm.yti.datamodel.api.v2.dto.MSCR; +import fi.vm.yti.datamodel.api.v2.dto.MappingInfoDTO; +import fi.vm.yti.datamodel.api.v2.dto.NodeInfo; +import fi.vm.yti.datamodel.api.v2.mapper.MappingMapper; + +public class RMLGenerator2 { + + String nsRML = "http://semweb.mmlab.be/ns/rml#"; + String nsQL = "http://semweb.mmlab.be/ns/ql#"; + String nsRR = "http://www.w3.org/ns/r2rml#"; + String nsFNO = "https://w3id.org/function/ontology#"; + String nsFNML = "http://semweb.mmlab.be/ns/fnml#"; + String nsGREL = "http://users.ugent.be/~bjdmeest/function/grel.ttl#"; + + + + record IteratorData(String iteratorPropertyURI, String targetShapeURI, String sourcePropertyURI, String mappingURI) {} + + + private String generateRandomURI(String suffix, String prefix) { + return suffix + ":" + UUID.randomUUID().toString() + ":" + prefix; + } + public Model generateRMLFromMSCRGraph(Model inputModel, String crosswalkURI, String sourceSchemaURI) { + Model m = ModelFactory.createDefaultModel(); + List iterators = getIterators(inputModel); + for (IteratorData iteratorData : iterators) { + String triplesMapURI = generateRandomURI("triplesMap", ""); + String logicalSourceURI = generateRandomURI("logicalSource", ""); + String subjectMapURI = generateRandomURI("subjectMap", ""); + //String predicateObjecMapURI = generateRandomURI("", ""); + + Resource triplesMap = m.createResource(triplesMapURI); + triplesMap.addProperty(RDF.type, m.createResource(nsRR + "TriplesMap")); + + Resource logicalSource = addLogicalSourceModel(logicalSourceURI, inputModel, m, sourceSchemaURI, iteratorData.sourcePropertyURI); + triplesMap.addProperty(m.createProperty(nsRML + "logicalSource"), logicalSource); + + + Resource subjectMap = addSubjectMapModel(subjectMapURI, iteratorData.iteratorPropertyURI, iteratorData.targetShapeURI, inputModel, m); + triplesMap.addProperty(m.createProperty(nsRR + "subjectMap"), subjectMap); + + addPredicateObjectMapModel(triplesMap, inputModel, m, iteratorData.targetShapeURI); + + } + return m; + } + + record DatatypeInfo(Resource nodeKind, Resource datatype) {} + private DatatypeInfo getDataTypeInfo(Model inputModel, String targetShapeURI) { + Resource targetShape = inputModel.getResource(targetShapeURI); + Resource datatype = null; + if(targetShape.hasProperty(SH.datatype)) { + datatype = targetShape.getProperty(SH.datatype).getResource(); + } + Resource nodeKind = null; + if(targetShape.hasProperty(SH.nodeKind)) { + nodeKind = targetShape.getProperty(SH.nodeKind).getResource(); + } + return new DatatypeInfo(nodeKind, datatype); + } + + private void addDatatype(Model outputModel, Resource targetResource, Resource datatype, Resource nodeKind) { + if(datatype != null) { + targetResource.addProperty(outputModel.createProperty(nsRR+"datatype") , datatype); + targetResource.addProperty(outputModel.createProperty(nsRR+"termType") , outputModel.createProperty(nsRR+"Literal")); + } + else if(nodeKind != null) { + if(nodeKind.getURI().equals(SH.IRI.getURI())) { + targetResource.addProperty(outputModel.createProperty(nsRR+"termType") , outputModel.createProperty(nsRR+"IRI")); + } + } + + + } + private void addPredicateObjectMapModel(Resource triplesMap, Model inputModel, Model outputModel, String targetShapeURI) { + MappingMapper mapper = new MappingMapper(); + List mappings = getPredicateObjectMappings(inputModel, targetShapeURI); + for (Resource mappingResource : mappings) { + MappingInfoDTO mappingInfo = mapper.mapToMappingDTO(mappingResource.getURI(), inputModel); + if(mappingInfo.getProcessing() == null && + mappingInfo.getSource().stream().filter(NodeInfo::hasProcessing).collect(Collectors.toList()).isEmpty() && + mappingInfo.getTarget().stream().filter(NodeInfo::hasProcessing).collect(Collectors.toList()).isEmpty()) { + for (NodeInfo targetNode : mappingInfo.getTarget()) { + // there should be only one source property since there are no functions involved + Resource pom = outputModel.createResource(); + Literal sourcePath = inputModel.getResource(mappingInfo.getSource().get(0).getId()).getProperty(MSCR.instancePath).getLiteral(); + Resource pomObjectMap = outputModel.createResource(); + pomObjectMap.addProperty(outputModel.createProperty(nsRML+"reference"), outputModel.createLiteral(sourcePath.getString())); + pom.addProperty(outputModel.createProperty(nsRR+"objectMap"), pomObjectMap); + + Resource predicate = inputModel.getResource(targetNode.getId()).getPropertyResourceValue(SH.path); + pom.addProperty(outputModel.createProperty(nsRR+"predicate"), predicate); + + DatatypeInfo dti = getDataTypeInfo(inputModel, targetNode.getId()); + addDatatype(outputModel, pomObjectMap, dti.datatype, dti.nodeKind); + + triplesMap.addProperty(outputModel.createProperty(nsRR + "predicateObjectMap"), pom); + } + } + else { + Resource sourceFunc = addSourceFuncModel(outputModel, mappingInfo.getSource()); + Resource mappingFunc = addMappingFuncModel(outputModel, mappingInfo, sourceFunc); + + for (int targetIndex = 0; targetIndex < mappingInfo.getTarget().size(); targetIndex++) { + NodeInfo targetNode = mappingInfo.getTarget().get(targetIndex); + Resource targetFunc = addTargetFuncModel(outputModel, targetNode, targetIndex, mappingFunc); + + Resource pom = outputModel.createResource(); + pom.addProperty(outputModel.createProperty(nsRR+"objectMap"), targetFunc); + + Resource predicate = inputModel.getResource(targetNode.getId()).getPropertyResourceValue(SH.path); + pom.addProperty(outputModel.createProperty(nsRR+"predicate"), predicate); + + + DatatypeInfo dti = getDataTypeInfo(inputModel, targetNode.getId()); + addDatatype(outputModel, targetFunc, dti.datatype, dti.nodeKind); + + + triplesMap.addProperty(outputModel.createProperty(nsRR + "predicateObjectMap"), pom); + + } + } + + addPredicateObjectMapProcessing(triplesMap, mappingInfo, inputModel, outputModel); + } + } + private void addPredicateObjectMapProcessing(Resource triplesMap, MappingInfoDTO mappingInfo, Model inputModel, Model outputModel) { + Resource mappingFuncValue = null; + for (NodeInfo targetNode : mappingInfo.getTarget()) { + + } + + } + private List getPredicateObjectMappings(Model inputModel, String targetShapeURI) { + String q =""" +PREFIX rdf: +PREFIX : +prefix sh: +select ?mappingURI +where { + bind(URI("%s") as ?targetShape) + ?mappingURI a :Mapping . + ?mappingURI :target/(<>|!<>)*/:id ?targetPropertyURI . + bind(URI(?targetPropertyURI) as ?targetProperty) + ?targetShape sh:property ?targetProperty . +} + """.formatted(targetShapeURI); + QueryExecution qe = QueryExecutionFactory.create(q, inputModel); + ResultSet results = qe.execSelect(); + List list = new ArrayList(); + while(results.hasNext()) { + QuerySolution soln = results.next(); + Resource mapping = soln.get("mappingURI").asResource(); + list.add(mapping); + } + + return list; + } + private Resource addSubjectMapModel(String subjectMapURI, String targetShapeURI, String targetClass, Model inputModel, Model outputModel) { + String mappingURI = getSubjectSourceMapping(targetShapeURI, inputModel); + if(mappingURI == null) { + // no subject source mapping -> blank nodes + return null; + } + else { + MappingMapper mapper = new MappingMapper(); + MappingInfoDTO mappingInfo = mapper.mapToMappingDTO(mappingURI, inputModel); + // there should be only one + NodeInfo sourcePropertyInfo = mappingInfo.getSource().get(0); + Resource processingURI = addProcessingModel(outputModel, mappingInfo, 0); + if(processingURI == null) { + Resource subjectMap = outputModel.createResource(subjectMapURI); + Literal sourcePath = inputModel.getResource(sourcePropertyInfo.getId()).getProperty(MSCR.instancePath).getLiteral(); + subjectMap.addProperty(outputModel.createProperty(nsRML+"reference"), sourcePath); + subjectMap.addProperty(outputModel.createProperty(nsRR + "class"), outputModel.createResource(targetClass)); + subjectMap.addProperty(outputModel.createProperty(nsRR + "termType"), outputModel.createResource(nsRR + "IRI")); + return subjectMap; + } + else { + processingURI.addProperty(outputModel.createProperty(nsRR + "class"), outputModel.createResource(targetClass)); + + processingURI.addProperty(outputModel.createProperty(nsRR + "termType"), outputModel.createResource(nsRR + "IRI")); + return processingURI; + } + + } + } + + + private Resource addProcessingModel(Model outputModel, MappingInfoDTO mappingInfo, int targetIndex) { + if(mappingInfo.getProcessing() == null && + mappingInfo.getSource().stream().filter(NodeInfo::hasProcessing).collect(Collectors.toList()).isEmpty() && + mappingInfo.getTarget().stream().filter(NodeInfo::hasProcessing).collect(Collectors.toList()).isEmpty()) { + return null; + } + Resource sourceFunc = addSourceFuncModel(outputModel, mappingInfo.getSource()); + Resource mappingFunc = addMappingFuncModel(outputModel, mappingInfo, sourceFunc); + Resource targetFunc = addTargetFuncModel(outputModel, mappingInfo.getTarget().get(targetIndex), targetIndex, mappingFunc); + return targetFunc; + } + + private Resource addTargetFuncModel(Model outputModel, NodeInfo targetPropertyInfo, int targetIndex, Resource mappingFunc) { + String targetFunctionURI = null; + Map params = null; + if(targetPropertyInfo.getProcessing() != null) { + targetFunctionURI = targetPropertyInfo.getProcessing().getId(); + params = targetPropertyInfo.getProcessing().getParams(); + Resource outerFunctionResource = outputModel.createResource(generateRandomURI(targetPropertyInfo.getId(), ":outerfunc")); + + Resource function2Value = outputModel.createResource(); + outerFunctionResource.addProperty(outputModel.createProperty(nsFNML + "functionValue"), function2Value); + + Resource funcPom1_2 = outputModel.createResource(); + function2Value.addProperty(outputModel.createProperty(nsRR+"predicateObjectMap"), funcPom1_2); + funcPom1_2.addProperty(outputModel.createProperty(nsRR+"predicate"), outputModel.createResource(nsFNO+"executes")); + Resource funcPom1ObjectMap2 = outputModel.createResource(); + funcPom1ObjectMap2.addProperty(outputModel.createProperty(nsRR+"constant"), outputModel.createResource(targetFunctionURI)); + funcPom1_2.addProperty(outputModel.createProperty(nsRR+"objectMap"), funcPom1ObjectMap2); + + + Resource funcPom2_2 = outputModel.createResource(); + function2Value.addProperty(outputModel.createProperty(nsRR+"predicateObjectMap"), funcPom2_2); + funcPom2_2.addProperty(outputModel.createProperty(nsRR+"predicate"), outputModel.createResource(nsGREL+"anyObjectParam")); + funcPom2_2.addProperty(outputModel.createProperty(nsRR+"objectMap"), mappingFunc); + + if(params != null) { + for (String key : params.keySet()) { + if(key.equals("input")) { + continue; + } + Object value = params.get(key); + Resource funcPom = outputModel.createResource(); + function2Value.addProperty(outputModel.createProperty(nsRR+"predicateObjectMap"), funcPom); + funcPom.addProperty(outputModel.createProperty(nsRR+"predicate"), outputModel.createResource(key)); + Resource funcPomObjectMap = outputModel.createResource(); + funcPomObjectMap.addProperty(outputModel.createProperty(nsRR+"constant"), outputModel.createLiteral(value.toString())); + funcPom.addProperty(outputModel.createProperty(nsRR+"objectMap"), funcPomObjectMap); + + } + + } + return outerFunctionResource; + } + else { + return mappingFunc; + } + + + + + + + } + private Resource addMappingFuncModel(Model outputModel, MappingInfoDTO mappingInfo, Resource sourceFunctionResource) { + String mappingFunctionURI = null; + Map params = null; + if(mappingInfo.getProcessing() != null) { + mappingFunctionURI = mappingInfo.getProcessing().getId(); + params = mappingInfo.getProcessing().getParams(); + + Resource mappingFunctionResource = outputModel.createResource(mappingInfo.getPID() + ":func"); + //addOuterFunctionModel(outputModel, mappingFunctionResource, mappingFunctionURI, sourceFunctionResource, null); + Resource functionValue = outputModel.createResource(); + mappingFunctionResource.addProperty(outputModel.createProperty(nsFNML + "functionValue"), functionValue); + + Resource funcPom1 = outputModel.createResource(); + functionValue.addProperty(outputModel.createProperty(nsRR+"predicateObjectMap"), funcPom1); + funcPom1.addProperty(outputModel.createProperty(nsRR+"predicate"), outputModel.createResource(nsFNO+"executes")); + Resource funcPom1ObjectMap = outputModel.createResource(); + funcPom1ObjectMap.addProperty(outputModel.createProperty(nsRR+"constant"), outputModel.createResource(mappingFunctionURI)); + funcPom1.addProperty(outputModel.createProperty(nsRR+"objectMap"), funcPom1ObjectMap); + + Resource funcPom3 = outputModel.createResource(); + functionValue.addProperty(outputModel.createProperty(nsRR+"predicateObjectMap"), funcPom3); + funcPom3.addProperty(outputModel.createProperty(nsRR+"predicate"), outputModel.createResource(nsGREL+"p_param_a2")); + funcPom3.addProperty(outputModel.createProperty(nsRR+"objectMap"), sourceFunctionResource); + + if(params != null) { + for (String key : params.keySet()) { + if(key.equals("input")) { + continue; + } + Object value = params.get(key); + Resource funcPom = outputModel.createResource(); + functionValue.addProperty(outputModel.createProperty(nsRR+"predicateObjectMap"), funcPom); + funcPom.addProperty(outputModel.createProperty(nsRR+"predicate"), outputModel.createResource(key)); + Resource funcPomObjectMap = outputModel.createResource(); + funcPomObjectMap.addProperty(outputModel.createProperty(nsRR+"constant"), outputModel.createLiteral(value.toString())); + funcPom.addProperty(outputModel.createProperty(nsRR+"objectMap"), funcPomObjectMap); + + } + + } + return mappingFunctionResource; + } + else { + return sourceFunctionResource; + } + + + + } + private Resource addSourceFuncModel(Model outputModel, List source) { + Resource latestFunction = null; + for(int i = 0; i < source.size(); i++) { + NodeInfo sourcePropertyInfo = source.get(i); + String sourceFunctionURI = null; + Map params = null; + if(sourcePropertyInfo.getProcessing() != null) { + sourceFunctionURI = sourcePropertyInfo.getProcessing().getId(); + params = sourcePropertyInfo.getProcessing().getParams(); + } + + String outerFunctionURI = "http://users.ugent.be/~bjdmeest/function/grel.ttl#createArray"; + if(i > 0) { + outerFunctionURI = "http://users.ugent.be/~bjdmeest/function/grel.ttl#addToArray"; + } + Resource sourceFunctionResource = null; + Resource outerFunctionResource = outputModel.createResource(sourcePropertyInfo.getId() + ":" + source.hashCode() + ":outerfunc"); + if(sourceFunctionURI != null) { + sourceFunctionResource = outputModel.createResource(sourcePropertyInfo.getId() + ":" + source.hashCode() + ":func"); + addFunctionModel(outputModel, sourceFunctionResource, sourceFunctionURI, sourcePropertyInfo.getInstancePath(), params); + + } + else { + sourceFunctionResource = outputModel.createResource(); + sourceFunctionResource.addProperty(outputModel.createProperty(nsRML+"reference"), outputModel.createLiteral(sourcePropertyInfo.getInstancePath())); + + } + addOuterFunctionModel(outputModel, outerFunctionResource, outerFunctionURI, sourceFunctionResource, latestFunction); + + latestFunction = outerFunctionResource; + } + return latestFunction; + } + private void addOuterFunctionModel(Model m, Resource outerFunctionResource, String outerFunctionURI, Resource sourceFunctionResource, Resource prev) { + Resource functionValue = m.createResource(); + outerFunctionResource.addProperty(m.createProperty(nsFNML + "functionValue"), functionValue); + + Resource funcPom1 = m.createResource(); + functionValue.addProperty(m.createProperty(nsRR+"predicateObjectMap"), funcPom1); + funcPom1.addProperty(m.createProperty(nsRR+"predicate"), m.createResource(nsFNO+"executes")); + Resource funcPom1ObjectMap = m.createResource(); + funcPom1ObjectMap.addProperty(m.createProperty(nsRR+"constant"), m.createResource(outerFunctionURI)); + funcPom1.addProperty(m.createProperty(nsRR+"objectMap"), funcPom1ObjectMap); + + Resource funcPom2 = m.createResource(); + functionValue.addProperty(m.createProperty(nsRR+"predicateObjectMap"), funcPom2); + funcPom2.addProperty(m.createProperty(nsRR+"predicate"), m.createResource(nsGREL+"anyObjectParam")); + funcPom2.addProperty(m.createProperty(nsRR+"objectMap"), sourceFunctionResource); + + if(prev != null) { + Resource funcPom3 = m.createResource(); + functionValue.addProperty(m.createProperty(nsRR+"predicateObjectMap"), funcPom3); + funcPom3.addProperty(m.createProperty(nsRR+"predicate"), m.createResource(nsGREL+"p_param_a2")); + funcPom3.addProperty(m.createProperty(nsRR+"objectMap"), prev); + + } + //sourceFunctionResource.addProperty(m.createProperty(nsRR + "class"), targetOntologyClass); + //outerFunctionResource.addProperty(m.createProperty(nsRR + "termType"), m.createResource(nsRR + "IRI")); + + } + + private void addFunctionModel(Model m, Resource sourceFunctionResource, String sourceFunctionURI, + String instancePath, Map params) { + + Resource functionValue = m.createResource(); + sourceFunctionResource.addProperty(m.createProperty(nsFNML + "functionValue"), functionValue); + + Resource funcPom1 = m.createResource(); + functionValue.addProperty(m.createProperty(nsRR+"predicateObjectMap"), funcPom1); + funcPom1.addProperty(m.createProperty(nsRR+"predicate"), m.createResource(nsFNO+"executes")); + Resource funcPom1ObjectMap = m.createResource(); + funcPom1ObjectMap.addProperty(m.createProperty(nsRR+"constant"), m.createResource(sourceFunctionURI)); + funcPom1.addProperty(m.createProperty(nsRR+"objectMap"), funcPom1ObjectMap); + + + Resource funcPom2 = m.createResource(); + functionValue.addProperty(m.createProperty(nsRR+"predicateObjectMap"), funcPom2); + funcPom2.addProperty(m.createProperty(nsRR+"predicate"), m.createResource(nsGREL+"anyObjectParam")); + Resource funcPom2ObjectMap = m.createResource(); + funcPom2ObjectMap.addProperty(m.createProperty(nsRML+"reference"), m.createLiteral(instancePath)); + funcPom2.addProperty(m.createProperty(nsRR+"objectMap"), funcPom2ObjectMap); + + if(params != null) { + for (String key : params.keySet()) { + if(key.equals("input")) { + continue; + } + Object value = params.get(key); + Resource funcPom = m.createResource(); + functionValue.addProperty(m.createProperty(nsRR+"predicateObjectMap"), funcPom); + funcPom.addProperty(m.createProperty(nsRR+"predicate"), m.createResource(key)); + Resource funcPomObjectMap = m.createResource(); + funcPomObjectMap.addProperty(m.createProperty(nsRR+"constant"), m.createLiteral(value.toString())); + funcPom.addProperty(m.createProperty(nsRR+"objectMap"), funcPomObjectMap); + + } + + } + + //sourceFunctionResource.addProperty(m.createProperty(nsRR + "termType"), m.createResource(nsRR + "IRI")); + + } + private String getSubjectSourceMapping(String targetShapeURI, Model m) { + String q =""" +PREFIX rdf: +PREFIX : +select ?mappingURI +where { + ?mappingURI a :Mapping . + ?mappingURI :target/rdf:_1 ?target . + ?target :id ?targetShapeURI . + ?target :label ?targetLabel . + FILTER(?targetLabel=\"subject source\") +} + """; + QueryExecution qe = QueryExecutionFactory.create(q, m); + ResultSet results = qe.execSelect(); + if(!results.hasNext()) { + return null; + } + else { + return results.next().get("mappingURI").asResource().getURI(); + } + } + private Resource addLogicalSourceModel(String logicalSourceURI, Model inputModel, Model m, String sourceSchemaURI, + String sourcePropertyURI) { + + Resource logicalSource = m.createResource(logicalSourceURI); + logicalSource.addProperty(RDF.type, m.createResource(nsRML + "BaseSource")); + Resource referenceFormulation = m.createResource(nsQL + "JSONPath"); + logicalSource.addProperty(m.createProperty(nsRML + "referenceFormulation"), referenceFormulation); + logicalSource.addProperty(m.createProperty(nsRML + "source"), m.createLiteral("data/person.json")); + + Resource sourceProperty = inputModel.getResource(sourcePropertyURI); + Literal iteratorPath = sourceProperty.getProperty(MSCR.instancePath).getLiteral(); + logicalSource.addProperty(m.createProperty(nsRML + "iterator"), iteratorPath); + + return logicalSource; + } + private List getIterators(Model inputModel) { + String q =""" +PREFIX rdf: +PREFIX : +select ?targetShapeURI ?sourcePropertyURI ?mappingURI +where { + ?mappingURI a :Mapping . + ?mappingURI :target/rdf:_1 ?target . + ?mappingURI :source/rdf:_1/:id ?sourcePropertyURI . + ?target :id ?targetShapeURI . + ?target :label ?targetLabel . + FILTER(?targetLabel=\"iterator source\") +} + """; + QueryExecution qe = QueryExecutionFactory.create(q, inputModel); + ResultSet results = qe.execSelect(); + + List list = new ArrayList(); + while(results.hasNext()) { + QuerySolution soln = results.next(); + String targetShapeURI = soln.get("targetShapeURI").asLiteral().getString(); + String targetClass = targetShapeURI.substring(9); // TODO: remove this + list.add(new IteratorData( + targetShapeURI, + targetClass, + soln.get("sourcePropertyURI").asLiteral().getString(), + soln.get("mappingURI").asResource().getURI() + )); + } + + return list; + } +} diff --git a/src/main/java/fi/csc/mscr/tranformation/rml/functions/CustomFunctions.java b/src/main/java/fi/csc/mscr/tranformation/rml/functions/CustomFunctions.java new file mode 100644 index 0000000..ed939ec --- /dev/null +++ b/src/main/java/fi/csc/mscr/tranformation/rml/functions/CustomFunctions.java @@ -0,0 +1,37 @@ +package fi.csc.mscr.tranformation.rml.functions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CustomFunctions { + + public static String addSuffix(Object value, String suffix) { + return value + suffix; + } + + public static String addPrefix(Object value, String prefix) { + return prefix + value; + } + + public static List concat(List values, String delimiter) { + String result = String.join(delimiter, values); + return List.of(result); + } + + public static List split(List values, String delimiter) { + List result = Arrays.asList(values.get(0).toString().split(delimiter)); + return result; + } + + public static List createArray(Object s) { + List a = new ArrayList(); + a.add(s); + return a; + } + + public static List addToArray(List a, Object s) { + a.add(s.toString()); + return a; + } +} diff --git a/src/test/resources/crosswalk1-input.ttl b/src/test/resources/crosswalk1-input.ttl new file mode 100644 index 0000000..b0d2a25 --- /dev/null +++ b/src/test/resources/crosswalk1-input.ttl @@ -0,0 +1,615 @@ +@prefix iow: . +@prefix dcap: . +@prefix owl: . +@prefix sh: . +@prefix rdf: . +@prefix xsd: . +@prefix skos: . +@prefix dcterms: . +@prefix rdfs: . +@prefix sourceschema: . +@prefix shapes: . +@prefix dash: . +@prefix mscr: . + + + a ; + rdfs:label "tset"@en ; + dcterms:created "2025-01-23T10:00:48.658Z"^^xsd:dateTime ; + dcterms:identifier "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172" ; + dcterms:language "en" ; + dcterms:modified "2025-01-23T10:00:48.658Z"^^xsd:dateTime ; + dcap:preferredXMLNamespace ; + dcap:preferredXMLNamespacePrefix + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172" ; + iow:contentModified "2025-01-23T10:00:48.657Z"^^xsd:dateTime ; + iow:creator "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + iow:modifier "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + iow:stateModified "2025-01-23T10:00:48.657Z"^^xsd:dateTime ; + + ; + + "MSCR" ; + + "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + + ; + + "DRAFT" ; + + "DATA_CROSSWALK" ; + + ; + + "1" ; + + "PRIVATE" ; + owl:versionInfo "DRAFT" . + + + + . + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=c001bb3a-18e5-4309-86f2-cb23ccc3789e" ; + + ; + + "2025-01-23T10:01:14.829Z"^^ ; + + "" ; + + ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root" ; + + "Person" + ] + ] ; + + [ a ; + + [ + "iterator:https://shacl-play.sparna.fr/shapes/Person" ; + + "iterator source" ; + + + ] + ] . + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=5256cec5-1286-4157-b3a9-bfc38abf6c1f" ; + + ; + + "2025-01-23T10:35:30.272Z"^^ ; + + "" ; + + ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#concat" ; + + [ a ; + + [ + "input" ; + + "self" + ] ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#delimiterParameter" ; + + "/" + ] + ] + ] ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-lastName" ; + + "lastName" ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#addPrefix" ; + + [ a ; + + [ + "input" ; + + "self" + ] ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#prefixParameter" ; + + "http://example2.com/" + ] + ] + ] ; + + + ] ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-firstName" ; + + "firstName" ; + + + ] + ] ; + + [ a ; + + [ + "subject:https://shacl-play.sparna.fr/shapes/Person" ; + + "subject source" ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#addSuffix" ; + + [ a ; + + [ + "input" ; + + "self" + ] ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#suffixParameter" ; + + "/test" + ] + ] + ] ; + + + ] + ] . + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=4de10154-0228-484b-8bee-0dd7730c0a26" ; + + ; + + "2025-01-24T11:21:38.052Z"^^ ; + + "" ; + + ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-firstName" ; + + "firstName" ; + + + ] + ] ; + + [ a ; + + [ + "https://shacl-play.sparna.fr/shapes/Person_givenName" ; + + "givenName" ; + + + ] + ] . + + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=992bc267-ecc3-4a5d-b0ed-a505ca89b8bf" ; + + ; + + "2025-01-24T13:28:21.939Z"^^ ; + + "" ; + + ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#concat" ; + + [ a ; + + [ + "input" ; + + "self" + ] ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#delimiterParameter" ; + + ", " + ] + ] + ] ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-lastName" ; + + "lastName" ; + + + ] ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-firstName" ; + + "firstName" ; + + + ] + ] ; + + [ a ; + + [ + "https://shacl-play.sparna.fr/shapes/Person_name" ; + + "name" ; + + + ] + ] . + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=ec13355a-bfdf-46ac-bbd7-a7518c4fa847" ; + + ; + + "2025-01-24T18:23:34.6Z"^^ ; + + "" ; + + ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#split" ; + + [ a ; + + [ + "input" ; + + "self" + ] ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#delimiterParameter" ; + + "_" + ] + ] + ] ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-lastName" ; + + "lastName" ; + + + ] + ] ; + + [ a ; + + [ + "https://shacl-play.sparna.fr/shapes/Person_familyName" ; + + "familyName" ; + + + ] + ] . + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=9a36c787-2b66-44a2-ab94-81b81a2ede78" ; + + ; + + "2025-01-24T20:55:24.218Z"^^ ; + + "" ; + + ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#split" ; + + [ a ; + + [ + "input" ; + + "self" + ] ; + + [ + "http://users.ugent.be/~bjdmeest/function/grel.ttl#delimiterParameter" ; + + "_" + ] + ] + ] ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-lastName" ; + + "lastName" ; + + + ] + ] ; + + [ a ; + + [ + "https://shacl-play.sparna.fr/shapes/Person_givenName" ; + + "givenName" ; + + + ] ; + + [ + "https://shacl-play.sparna.fr/shapes/Person_familyName" ; + + "familyName" ; + + + ] + ] . + + + a ; + + "mscr:crosswalk:170c9c32-3b18-4ac1-853c-5a48aa1b3172@mapping=ebc31480-e9f4-4297-9488-36d6d3e18081" ; + + ; + + "2025-01-24T21:23:51.053Z"^^ ; + + "" ; + + ; + + [ a ; + + [ + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771#root-Root-age" ; + + "age" ; + + + ] + ] ; + + [ a ; + + [ + "https://shacl-play.sparna.fr/shapes/Person_age" ; + + "age" ; + + + ] + ] . + + + a ; + rdfs:comment ""@en ; + rdfs:label "person json"@en ; + dcterms:created "2025-01-23T09:59:54.712Z"^^xsd:dateTime ; + dcterms:identifier "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771" ; + dcterms:language "en" ; + dcterms:modified "2025-01-23T10:00:34.741Z"^^xsd:dateTime ; + dcap:preferredXMLNamespace ; + dcap:preferredXMLNamespacePrefix + "mscr:schema:b2973de1-f9e6-4778-9390-039a86cb0771" ; + iow:contentModified "2025-01-23T09:59:54.712Z"^^xsd:dateTime ; + iow:creator "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + iow:modifier "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + iow:stateModified "2025-01-23T09:59:54.712Z"^^xsd:dateTime ; + + ; + + "JSONSCHEMA" ; + + ; + + "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + + "DRAFT" ; + + "DATA_SCHEMA" ; + + "1" ; + + "PUBLIC" ; + owl:versionInfo "DRAFT" . + + + + + "en" ; + + sourceschema:root-Root . + +sourceschema:root-Root a ; + + "Person" ; + + true ; + + "Person" ; + mscr:instancePath + "$" ; + + sourceschema:root-Root-age , sourceschema:root-Root-lastName , sourceschema:root-Root-firstName . + +sourceschema:root-Root-age a ; + + ; + + "$.age" ; + + "$.age" ; + + ; + + "Age in years which must be equal to or greater than zero." ; + + "1"^^ ; + + "0"^^ ; + + "age" ; + + sourceschema:root-Root-age . + +sourceschema:root-Root-lastName a ; + + ; + + "$.lastName" ; + + "$.lastName" ; + + ; + + "The person's last name." ; + + "1"^^ ; + + "lastName" ; + + sourceschema:root-Root-lastName . + +sourceschema:root-Root-firstName a ; + + ; + + "$.firstName" ; + + "$.firstName" ; + + ; + + "The person's first name." ; + + "1"^^ ; + + "firstName" ; + + sourceschema:root-Root-firstName . + + + a ; + rdfs:comment ""@en ; + rdfs:label "person shapes"@en ; + dcterms:created "2025-01-23T10:00:13.084Z"^^xsd:dateTime ; + dcterms:identifier "mscr:schema:5b042ba6-58a4-4d8b-bac1-47fa40204a0d" ; + dcterms:language "en" ; + dcterms:modified "2025-01-23T10:00:23.454Z"^^xsd:dateTime ; + dcap:preferredXMLNamespace ; + dcap:preferredXMLNamespacePrefix + "mscr:schema:5b042ba6-58a4-4d8b-bac1-47fa40204a0d" ; + iow:contentModified "2025-01-23T10:00:13.084Z"^^xsd:dateTime ; + iow:creator "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + iow:modifier "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + iow:stateModified "2025-01-23T10:00:13.084Z"^^xsd:dateTime ; + + ; + + "SHACL" ; + + ; + + "4ce70937-6fa4-49af-a229-b5f10328adb8" ; + + "DRAFT" ; + + "DATA_SCHEMA" ; + + "1" ; + + "PUBLIC" ; + owl:versionInfo "DRAFT" . + + + + shapes:Person . + +shapes:Person a sh:NodeShape ; + rdfs:label "Person"@en ; + sh:property shapes:Person_familyName , shapes:Person_givenName , shapes:Person_name , shapes:Person_age ; + sh:targetClass . + +shapes:Person_familyName + sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "familyName"@en ; + sh:nodeKind sh:Literal ; + sh:path . + +shapes:Person_givenName + sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "givenName"@en ; + sh:nodeKind sh:Literal ; + sh:path . + +shapes:Person_name dash:propertyRole dash:LabelRole ; + sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "name"@en ; + sh:nodeKind sh:Literal ; + sh:path . + +shapes:Person_age dash:propertyRole dash:LabelRole ; + sh:datatype xsd:integer ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "age"@en ; + sh:nodeKind sh:Literal ; + sh:path . \ No newline at end of file diff --git a/src/test/resources/crosswalk1.json b/src/test/resources/crosswalk1.json new file mode 100644 index 0000000..b2745ca --- /dev/null +++ b/src/test/resources/crosswalk1.json @@ -0,0 +1,107 @@ +[ + { + "type": "mscr:dataMapping", + "source": [ + { + "id": "mscr:schema:5a14637d-f262-4b2b-b015-a832a4b4b58c#root-Root-root", + "processing": null, + "mscrType": "default" + } + ], + "predicate": null, + "target": [ + { + "id": "http://uri.suomi.fi/datamodel/ns/mscr#Person1Shape", + "processing": null, + "mscrType": "iterator" + } + ], + "processing": null, + "notes": "", + "isPartOf": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8", + "id": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8@mapping=bcf3e7a2-756f-4112-a896-177214766e57" + }, + { + "type": "mscr:dataMapping", + "source": [ + { + "id": "mscr:schema:5a14637d-f262-4b2b-b015-a832a4b4b58c#root-Root-root-Root-firstName", + "processing": { + "id": "addPrefix", + "params": { + "prefix": "http://ex.com/" + } + }, + "mscrType": "default", + "index": 0 + }, + { + "id": "mscr:schema:5a14637d-f262-4b2b-b015-a832a4b4b58c#root-Root-root-Root-lastName", + "processing": null, + "mscrType": "default", + "index": 1 + } + ], + "predicate": null, + "target": [ + { + "id": "http://uri.suomi.fi/datamodel/ns/mscr#Person1Shape", + "processing": null, + "mscrType": "subject" + } + ], + "processing": { + "id": "concat", + "params": { + "separator": "/" + } + }, + "notes": "", + "isPartOf": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8", + "id": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8@mapping=bcf3e7a2-756f-4112-a896-177214766e57" + }, + { + "type": "mscr:dataMapping", + "source": [ + { + "id": "mscr:schema:5a14637d-f262-4b2b-b015-a832a4b4b58c#root-Root-root-Root-firstName", + "processing": null, + "mscrType": "default" + } + ], + "predicate": null, + "target": [ + { + "id": "mscr:schema:3a9d1aef-52ab-425c-90ec-2e15f9703ec9#28ad84b8471c0abdc37727a07b54a15c", + "processing": null, + "mscrType": "default" + } + ], + "processing": null, + "notes": "", + "isPartOf": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8", + "id": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8@mapping=107154e5-d282-47e9-86fc-eba6f97d3a12" + }, + { + "type": "mscr:dataMapping", + "source": [ + { + "id": "mscr:schema:5a14637d-f262-4b2b-b015-a832a4b4b58c#root-Root-root-Root-lastName", + "processing": null, + "mscrType": "default" + } + ], + "predicate": null, + "target": [ + { + "id": "mscr:schema:3a9d1aef-52ab-425c-90ec-2e15f9703ec9#88dc60d6f9d68169b18a30c9f52f5379", + "processing": null, + "mscrType": "default" + } + ], + "processing": null, + "notes": "", + "isPartOf": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8", + "id": "mscr:crosswalk:52d28f85-14d2-4127-8931-e9cb07074ba8@mapping=918d7337-9916-4c44-a2fa-61408f18fb7e" + } +] \ No newline at end of file diff --git a/src/test/resources/schemas/arrays-schema.json b/src/test/resources/schemas/arrays-schema.json new file mode 100644 index 0000000..0e9748f --- /dev/null +++ b/src/test/resources/schemas/arrays-schema.json @@ -0,0 +1,35 @@ +{ + "$id": "https://example.com/arrays.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Arrays of strings and objects", + "title": "Arrays", + "type": "object", + "properties": { + "fruits": { + "type": "array", + "items": { + "type": "string" + } + }, + "vegetables": { + "type": "array", + "items": { "$ref": "#/$defs/veggie" } + } + }, + "$defs": { + "veggie": { + "type": "object", + "required": [ "veggieName", "veggieLike" ], + "properties": { + "veggieName": { + "type": "string", + "description": "The name of the vegetable." + }, + "veggieLike": { + "type": "boolean", + "description": "Do I like this vegetable?" + } + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/schemas/arrays-schema.xsd b/src/test/resources/schemas/arrays-schema.xsd new file mode 100644 index 0000000..17214a1 --- /dev/null +++ b/src/test/resources/schemas/arrays-schema.xsd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/schemas/person-schema.json b/src/test/resources/schemas/person-schema.json new file mode 100644 index 0000000..a13fa0b --- /dev/null +++ b/src/test/resources/schemas/person-schema.json @@ -0,0 +1,23 @@ +{ + "$id": "https://example.com/person.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Person", + "type": "object", + "required": ["firstName", "lastName", "age"], + "additionalProperties": false, + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": "string", + "description": "The person's last name." + }, + "age": { + "description": "Age in years which must be equal to or greater than zero.", + "type": "integer", + "minimum": 0 + } + } +} \ No newline at end of file diff --git a/src/test/resources/schemas/person-schema.xsd b/src/test/resources/schemas/person-schema.xsd new file mode 100644 index 0000000..718d56c --- /dev/null +++ b/src/test/resources/schemas/person-schema.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/schemas/person-shapes.ttl b/src/test/resources/schemas/person-shapes.ttl new file mode 100644 index 0000000..8e7914f --- /dev/null +++ b/src/test/resources/schemas/person-shapes.ttl @@ -0,0 +1,44 @@ +@prefix dash: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix shapes: . +@prefix xsd: . + +shapes:Person_familyName + sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "familyName"@en ; + sh:nodeKind sh:Literal ; + sh:path . + +shapes:Person_givenName + sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "givenName"@en ; + sh:nodeKind sh:Literal ; + sh:path . + +shapes:Person_name dash:propertyRole dash:LabelRole ; + sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "name"@en ; + sh:nodeKind sh:Literal ; + sh:path . + +shapes:Person_age dash:propertyRole dash:LabelRole ; + sh:datatype xsd:integer ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "age"@en ; + sh:nodeKind sh:Literal ; + sh:path . + + +shapes:Person rdf:type sh:NodeShape ; + rdfs:label "Person"@en ; + sh:property shapes:Person_familyName , shapes:Person_givenName , shapes:Person_name, shapes:Person_age ; + sh:targetClass . \ No newline at end of file diff --git a/src/test/resources/schemas/shapes.ttl b/src/test/resources/schemas/shapes.ttl new file mode 100644 index 0000000..03472ac --- /dev/null +++ b/src/test/resources/schemas/shapes.ttl @@ -0,0 +1,23 @@ +@prefix mscr: . +@prefix rdf: . +@prefix rdfs: . +@prefix schemaorg: . +@prefix sh: . +@prefix xsd: . +@prefix dct: . + +mscr:Person1Shape a sh:NodeShape ; + rdfs:label "Person1" ; + sh:property + [ + sh:name "first name" ; + sh:datatype xsd:string ; + sh:path mscr:firstname ; + sh:maxCount 1 ; + ], + [ + sh:name "last name" ; + sh:datatype xsd:string ; + sh:path mscr:lastname ; + sh:maxCount 1 ; + ] .