diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..dd0e7f9 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,52 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Kepler16b", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "enableNonRootDocker": "true", + "moby": "true" + }, + "ghcr.io/devcontainers/features/java:1": { + "installGradle": true, + "version": "17", + "jdkDistro": "ms", + "gradleVersion": "latest", + "mavenVersion": "latest", + "antVersion": "latest", + "groovyVersion": "latest" + } + }, + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + // Extensions below are for quality of life improvments + "eamodio.gitlens", + "esbenp.prettier-vscode", + "TabNine.tabnine-vscode", + "mhutchie.git-graph", + "wayou.vscode-todo-highlight", + "vscode-icons-team.vscode-icons", + "ms-azuretools.vscode-docker", + "firefox-devtools.vscode-firefox-debug", + // Extension below is for VSCode Gradle Plugin needed for OML Vision + "vscjava.vscode-gradle" + ] + } + } + + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.fuseki.ttl b/.fuseki.ttl index 1839cf6..e72fada 100644 --- a/.fuseki.ttl +++ b/.fuseki.ttl @@ -1,24 +1,46 @@ -@prefix fuseki: . -@prefix rdf: . -@prefix rdfs: . -@prefix tdb: . -@prefix ja: . -@prefix : <#> . +PREFIX : <#> +PREFIX fuseki: +PREFIX ja: +PREFIX tdb: -[] rdf:type fuseki:Server . +# Service 1: Assertions endpoint +:service1 a fuseki:Service ; + fuseki:name "tutorial2" ; + fuseki:dataset :assertions ; + fuseki:serviceQuery "" , "query", "sparql" ; + fuseki:serviceUpdate "" , "update" ; + fuseki:serviceReadWriteGraphStore "data" ; + . -<#service> rdf:type fuseki:Service ; - rdfs:label "Tutorial2" ; # Human readable label for dataset - fuseki:name "tutorial2" ; # Name of the dataset in the endpoint url - fuseki:serviceReadWriteGraphStore "data" ; # SPARQL Graph store protocol (read and write) - fuseki:endpoint [ fuseki:operation fuseki:query ; fuseki:name "sparql" ] ; # SPARQL query service - fuseki:endpoint [ fuseki:operation fuseki:shacl ; fuseki:name "shacl" ] ; # SHACL query service - fuseki:dataset <#dataset> . +# Service 2: Inference endpoint +:service2 a fuseki:Service ; + fuseki:name "tutorial2-inf" ; + fuseki:dataset :inferences ; + fuseki:serviceQuery "" , "query", "sparql" ; + fuseki:serviceUpdate "" , "update" ; + fuseki:serviceReadWriteGraphStore "data" ; + fuseki:serviceReadGraphStore "get" ; + . + +:inferences a ja:RDFDataset ; + ja:defaultGraph :inf_model ; + . -## In memory TDB with union graph. -<#dataset> rdf:type tdb:DatasetTDB ; - tdb:location "--mem--" ; - # Query timeout on this dataset (1s, 1000 milliseconds) - ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "1000" ] ; - # Make the default graph be the union of all named graphs. - tdb:unionDefaultGraph true . +:inf_model a ja:InfModel ; + ja:baseModel :baseModel ; + ja:reasoner [ + ja:reasonerURL ; + ja:rulesFrom ; + ] + . + +:baseModel a tdb:GraphTDB ; + tdb:graphName ; + tdb:dataset :assertions ; + . + +:assertions a tdb:DatasetTDB ; + # location is relative to the .fuseki folder + tdb:location "assertions" ; + tdb:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "1000" ] ; + . \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f33a02c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for more information: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://containers.dev/guide/dependabot + +version: 2 +updates: + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: weekly diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 0000000..ce0d3a7 --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,10 @@ +# Grab gitpod image +FROM gitpod/workspace-full + +# Set the user as gitpod +USER gitpod + +# Set the version to Java 17 +RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && \ + sdk install java 17.0.3-ms && \ + sdk default java 17.0.3-ms" \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml index bb635d8..5aff5ed 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -4,8 +4,17 @@ # Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart +# Docker image +image: + file: .gitpod.Dockerfile + +# Tasks to run tasks: - - init: sdk install java 17 - - init: ./gradlew build - + - init: ./gradlew owlLoad +# VSCode attributes +vscode: + extensions: + - https://github.com/microsoft/vscode-gradle/releases/download/3.12.7/vscjava.vscode-gradle-3.12.7.vsix + - https://github.com/opencaesar/oml-vision/releases/download/v0.2.0/oml-vision-v0.2.0.vsix + - https://github.com/opencaesar/oml-luxor/releases/download/2.4.0/oml-luxor-2.4.0.vsix diff --git a/build.gradle b/build.gradle index 399c386..30eb020 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,8 @@ task omlToOwl(type:io.opencaesar.oml2owl.Oml2OwlTask, group:"oml", dependsOn: do inputCatalogPath = file('catalog.xml') // OWL catalog outputCatalogPath = file('build/owl/catalog.xml') + // Generate rules + generateRules = true } /* @@ -117,7 +119,7 @@ task generateDocs(type: io.opencaesar.owl.doc.OwlDocTask, dependsOn: owlReason) * Start the headless Fuseki server * @seeAlso https://github.com/opencaesar/owl-tools/blob/master/owl-doc/README.md */ -task startFuseki(type: io.opencaesar.owl.fuseki.StartFusekiTask, group:"oml") { +task startFuseki(type: io.opencaesar.owl.fuseki.StartFusekiTask, group:"vision", dependsOn: owlReason) { configurationPath = file('.fuseki.ttl') outputFolderPath = file('.fuseki') webUI = true @@ -127,10 +129,22 @@ task startFuseki(type: io.opencaesar.owl.fuseki.StartFusekiTask, group:"oml") { * Stop the headless Fuseki server * @seeAlso https://github.com/opencaesar/owl-tools/blob/master/owl-fuseki/README.md */ -task stopFuseki(type: io.opencaesar.owl.fuseki.StopFusekiTask, group:"oml") { +task stopFuseki(type: io.opencaesar.owl.fuseki.StopFusekiTask, group:"vision") { outputFolderPath = file('.fuseki') } +/* + * A task to load an OWL catalog to a TDB-persisted Fuseki dataset endpoint + * @seeAlso https://github.com/opencaesar/owl-tools/blob/master/owl-load/README.md + */ +task owlLoadTdb(type:io.opencaesar.owl.load.OwlLoadTask, group:"oml", dependsOn: startFuseki) { + inputs.files(startFuseki.outputFolderPath) // rerun when fuseki restarts + catalogPath = file('build/owl/catalog.xml') + endpointURL = "http://localhost:3030/$dataset".toString() + fileExtensions = ['owl', 'ttl'] + iris = ["$rootIri".toString()] +} + /* * A task to load an OWL catalog to a Fuseki dataset endpoint * @seeAlso https://github.com/opencaesar/owl-tools/blob/master/owl-load/README.md @@ -138,13 +152,10 @@ task stopFuseki(type: io.opencaesar.owl.fuseki.StopFusekiTask, group:"oml") { task owlLoad(type:io.opencaesar.owl.load.OwlLoadTask, group:"oml", dependsOn: [owlReason, startFuseki]) { inputs.files(startFuseki.outputFolderPath) // rerun when fuseki restarts catalogPath = file('build/owl/catalog.xml') - endpointURL = "http://localhost:3030/$dataset".toString() + endpointURL = "http://localhost:3030/$dataset-inf".toString() fileExtensions = ['owl', 'ttl'] - iris = [ - "$rootIri/classes".toString(), - "$rootIri/properties".toString(), - "$rootIri/individuals".toString() - ] + iris = ["$rootIri/classes".toString(), "$rootIri/properties".toString()] + loadToDefaultGraph = true } /* @@ -153,7 +164,7 @@ task owlLoad(type:io.opencaesar.owl.load.OwlLoadTask, group:"oml", dependsOn: [o */ task owlQuery(type:io.opencaesar.owl.query.OwlQueryTask, group:"oml", dependsOn: owlLoad) { inputs.files(owlLoad.inputs.files) // rerun when the dataset changes - endpointURL = "http://localhost:3030/$dataset".toString() + endpointURL = "http://localhost:3030/$dataset-inf".toString() queryPath = file('src/sparql') resultPath = file('build/results') format = 'json' diff --git a/oml-vision-v0.2.0.vsix b/oml-vision-v0.2.0.vsix new file mode 100644 index 0000000..ade7a7f Binary files /dev/null and b/oml-vision-v0.2.0.vsix differ diff --git a/src/sparql/components.sparql b/src/sparql/components.sparql index 85a217f..a2ed31e 100644 --- a/src/sparql/components.sparql +++ b/src/sparql/components.sparql @@ -2,18 +2,18 @@ PREFIX base: PREFIX mission: PREFIX vim4: -SELECT DISTINCT ?c1_id ?c1_name ?c1_mass ?c2_id ?c2_name +SELECT DISTINCT ?iri ?c2Iri ?c1_id ?c1_name ?c1_mass ?c2_id ?c2_name WHERE { - ?c1 a mission:Component ; + ?iri a mission:Component ; base:hasIdentifier ?c1_id ; base:hasCanonicalName ?c1_name . OPTIONAL { - ?c1 base:isContainedIn ?c2 . - ?c2 base:hasIdentifier ?c2_id ; + ?iri base:isContainedIn ?c2Iri . + ?c2Iri base:hasIdentifier ?c2_id ; base:hasCanonicalName ?c2_name . } OPTIONAL { - ?c1_mass_mag vim4:characterizes ?c1 ; + ?c1_mass_mag vim4:characterizes ?iri ; vim4:hasDoubleNumber ?c1_mass . } } diff --git a/src/sparql/update.sparql b/src/sparql/update.sparql new file mode 100644 index 0000000..ecac747 --- /dev/null +++ b/src/sparql/update.sparql @@ -0,0 +1,11 @@ +PREFIX base: +PREFIX mission: +PREFIX components: +PREFIX vim4: + +INSERT DATA { + components:test a mission:Component ; + base:hasIdentifier "testID" ; + base:hasCanonicalName "testName" ; + base:contains components:orbiter-launch-system . +} diff --git a/src/vision/config/sparqlConfig.json b/src/vision/config/sparqlConfig.json new file mode 100644 index 0000000..62ca935 --- /dev/null +++ b/src/vision/config/sparqlConfig.json @@ -0,0 +1,5 @@ +{ + "queryEndpoint": "http://localhost:3030/tutorial2-inf/sparql", + "updateEndpoint": "http://localhost:3030/tutorial2-inf/update", + "pingEndpoint": "http://localhost:3030/$/ping" +} diff --git a/src/vision/sparql/components.sparql b/src/vision/sparql/components.sparql new file mode 100644 index 0000000..a2ed31e --- /dev/null +++ b/src/vision/sparql/components.sparql @@ -0,0 +1,20 @@ +PREFIX base: +PREFIX mission: +PREFIX vim4: + +SELECT DISTINCT ?iri ?c2Iri ?c1_id ?c1_name ?c1_mass ?c2_id ?c2_name +WHERE { + ?iri a mission:Component ; + base:hasIdentifier ?c1_id ; + base:hasCanonicalName ?c1_name . + OPTIONAL { + ?iri base:isContainedIn ?c2Iri . + ?c2Iri base:hasIdentifier ?c2_id ; + base:hasCanonicalName ?c2_name . + } + OPTIONAL { + ?c1_mass_mag vim4:characterizes ?iri ; + vim4:hasDoubleNumber ?c1_mass . + } +} +ORDER BY ?c1_id ?c2_id \ No newline at end of file diff --git a/src/vision/sparql/connections.sparql b/src/vision/sparql/connections.sparql new file mode 100644 index 0000000..b2d50fa --- /dev/null +++ b/src/vision/sparql/connections.sparql @@ -0,0 +1,12 @@ +PREFIX base: +PREFIX mission: + +SELECT DISTINCT ?c1_name ?c2_name +WHERE { + ?c1 a mission:Component ; + base:hasCanonicalName ?c1_name ; + mission:connectsTo [ + base:hasCanonicalName ?c2_name + ] +} +ORDER BY ?c1_name ?c2_name \ No newline at end of file diff --git a/src/vision/sparql/general-properties.sparql b/src/vision/sparql/general-properties.sparql new file mode 100644 index 0000000..094f0a5 --- /dev/null +++ b/src/vision/sparql/general-properties.sparql @@ -0,0 +1,13 @@ +PREFIX xsd: +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX base: + +select distinct ?anyIri ?id ?name +WHERE { + BIND(<${iri}> AS ?anyIri) + ?anyIri a owl:NamedIndividual ; + base:hasIdentifier ?id ; + base:hasCanonicalName ?name . +} \ No newline at end of file diff --git a/src/vision/sparql/missions-diagram.sparql b/src/vision/sparql/missions-diagram.sparql new file mode 100644 index 0000000..e100cdc --- /dev/null +++ b/src/vision/sparql/missions-diagram.sparql @@ -0,0 +1,23 @@ +PREFIX base: +PREFIX mission: + +SELECT DISTINCT ?m_id ?m_name +WHERE { + ?m a mission:Mission ; + base:hasIdentifier ?m_id ; + base:hasCanonicalName ?m_name ; +} +ORDER BY ?m_id + +# PREFIX oml: +# PREFIX dc: +# PREFIX base: +# PREFIX mission: + +# CONSTRUCT { +# ?mission dc:type oml:Concept ; +# mission:pursues ?objective . +# } +# WHERE { +# ?mission mission:pursues ?objective ; +# } \ No newline at end of file diff --git a/src/vision/sparql/missions.sparql b/src/vision/sparql/missions.sparql new file mode 100644 index 0000000..1483497 --- /dev/null +++ b/src/vision/sparql/missions.sparql @@ -0,0 +1,10 @@ +PREFIX base: +PREFIX mission: + +SELECT DISTINCT ?iri ?m_id ?m_name +WHERE { + ?iri a mission:Mission ; + base:hasIdentifier ?m_id ; + base:hasCanonicalName ?m_name ; +} +ORDER BY ?m_id ?o_id \ No newline at end of file diff --git a/src/vision/sparql/objectives-edge.sparql b/src/vision/sparql/objectives-edge.sparql new file mode 100644 index 0000000..afade7b --- /dev/null +++ b/src/vision/sparql/objectives-edge.sparql @@ -0,0 +1,15 @@ +PREFIX base: +PREFIX mission: + +SELECT DISTINCT ?m_id ?m_name ?o_id ?o_name +WHERE { + ?m a mission:Mission ; + base:hasIdentifier ?m_id ; + base:hasCanonicalName ?m_name ; + mission:pursues [ + a mission:Objective ; + base:hasIdentifier ?o_id ; + base:hasCanonicalName ?o_name + ] +} +ORDER BY ?o_id \ No newline at end of file diff --git a/src/vision/sparql/objectives.sparql b/src/vision/sparql/objectives.sparql new file mode 100644 index 0000000..a5754eb --- /dev/null +++ b/src/vision/sparql/objectives.sparql @@ -0,0 +1,14 @@ +PREFIX base: +PREFIX mission: + +SELECT DISTINCT ?iri ?o1_id ?o1_name ?o2_id ?o2_name +WHERE { + ?iri a mission:Objective ; + base:hasIdentifier ?o1_id ; + base:hasCanonicalName ?o1_name ; + base:aggregates [ + base:hasIdentifier ?o2_id ; + base:hasCanonicalName ?o2_name + ] +} +ORDER BY ?o1_id ?o2_id diff --git a/src/vision/sparql/requirements.sparql b/src/vision/sparql/requirements.sparql new file mode 100644 index 0000000..ab9c0e1 --- /dev/null +++ b/src/vision/sparql/requirements.sparql @@ -0,0 +1,20 @@ +PREFIX base: +PREFIX mission: +PREFIX oml: +PREFIX rdfs: + +SELECT DISTINCT ?iri ?r_id ?c_name ?i_name +WHERE { + ?iri a mission:Requirement ; + base:hasIdentifier ?r_id ; + mission:specifies [ + a mission:Presents ; + oml:hasSource [ + base:hasCanonicalName ?c_name + ] ; + oml:hasTarget [ + base:hasCanonicalName ?i_name + ] + ] +} +ORDER BY ?r_id ?c_name ?i_name \ No newline at end of file diff --git a/src/vision/viewpoints/diagrams/components.json b/src/vision/viewpoints/diagrams/components.json new file mode 100644 index 0000000..861daf3 --- /dev/null +++ b/src/vision/viewpoints/diagrams/components.json @@ -0,0 +1,29 @@ +{ + "components": { + "name": "Missions", + "queries": { + "connections": "components.sparql", + "edge": "components.sparql" + }, + "rowMapping": { + "id": "connections", + "name": "Components", + "labelFormat": "{c1_id} {c1_name}", + "nodeColor": "red", + "nodeTextColor": "white", + "nodeType": "default", + "edgeMatchKey": "c1_id" + }, + "edges": [ + { + "id": "edge", + "name": "Components", + "animated": true, + "labelFormat": "contains", + "legendItems": "{c1_name}", + "sourceKey": "c2_id", + "targetKey": "c1_id" + } + ] + } +} diff --git a/src/vision/viewpoints/pages.json b/src/vision/viewpoints/pages.json new file mode 100644 index 0000000..90d7df8 --- /dev/null +++ b/src/vision/viewpoints/pages.json @@ -0,0 +1,42 @@ +[ + { "title": "Home", "path": "/", "type": "home" }, + { + "title": "Kepler16b", + "type": "group", + "iconUrl": "https://nasa-jpl.github.io/stellar/icons/satellite.svg", + "children": [ + { + "title": "Objectives", + "type": "table", + "path": "objectives" + }, + { + "title": "Missions", + "type": "tree", + "path": "missions" + }, + { + "title": "Components", + "type": "diagram", + "path": "components" + }, + { + "title": "Connections", + "type": "table", + "path": "connections" + } + ] + }, + { + "title": "Requirements", + "type": "group", + "iconUrl": "https://nasa-jpl.github.io/stellar/icons/checklist_on_page.svg", + "children": [ + { + "title": "Requirements", + "type": "tree", + "path": "requirements" + } + ] + } +] diff --git a/src/vision/viewpoints/properties/propertyLayouts.json b/src/vision/viewpoints/properties/propertyLayouts.json new file mode 100644 index 0000000..03c3f9a --- /dev/null +++ b/src/vision/viewpoints/properties/propertyLayouts.json @@ -0,0 +1,84 @@ +{ + "pages": [ + { + "id": "general", + "label": "General", + "sparqlQuery": "general-properties.sparql", + "icon": "IconSettings", + "domainClass": "oml.iddInstance", + "preconditionExpression": "tablePath != \"PEL\" && tablePath != \"MEL\" && tablePath != \"wbs\"", + "groups": [ + { + "id": "instance", + "label": "Instance", + "domainClass": "oml.ConceptInstance", + "controls": [ + { + "type": "text", + "id": "id", + "label": "Label", + "helpExpression": "A label can provide a human-readable id for model objects that have assigned ids that might be less readable", + "isEnabledExpression": "aql:self.isEditable()", + "initialOperation": { + "firstModelOperations": { + "type": "tool:ChangeContext", + "browseExpression": "aql:self.oclAsType(oml::ConceptInstance).setPropertyValue('label'.rdfsIri(), newValue)" + } + } + }, + { + "type": "text", + "id": "anyIri", + "label": "IRI", + "readOnly": true, + "helpExpression": "This is the model-assigned element identifier. Every model element has this unique identifier" + }, + { + "type": "text", + "id": "name", + "label": "Name", + "required": true, + "helpExpression": "Lists zero or more model types that this instance specializes. Such supertypes carry inherited properties or relations in the model." + } + ] + } + ] + }, + { + "id": "functionFilters", + "label": "Function Filters", + "sparqlQuery": "functionFiltersProperties", + "icon": "IconFilter", + "domainClass": "oml.Element", + "preconditionExpression": "tablePath == 'function-list'", + "groups": [] + }, + { + "id": "assemblyFilters", + "label": "Assembly Filters", + "sparqlQuery": "assemblyFiltersProperties", + "icon": "IconFilter", + "domainClass": "oml.Element", + "preconditionExpression": "tablePath == 'assemblies'", + "groups": [] + }, + { + "id": "main", + "label": "Main", + "sparqlQuery": "requirement-properties.sparql", + "icon": "IconChecklist", + "domainClass": "", + "preconditionExpression": "", + "groups": [] + }, + { + "id": "semantic", + "label": "Semantic", + "sparqlQuery": "semanticProperties", + "icon": "IconLink", + "domainClass": "", + "preconditionExpression": "", + "groups": [] + } + ] +} \ No newline at end of file diff --git a/src/vision/viewpoints/tables/connections.json b/src/vision/viewpoints/tables/connections.json new file mode 100644 index 0000000..a15584b --- /dev/null +++ b/src/vision/viewpoints/tables/connections.json @@ -0,0 +1,21 @@ +{ + "connections": { + "name": "Connections", + "diagrams": { + "all-rows": "connections-diagram" + }, + "columnNames": { + "c1_name": "Connection 1 Name", + "c2_name": "Connection 2 Name" + }, + "queries": { + "c1_name": "connections.sparql", + "c2_name": "connections.sparql" + }, + "rowMapping": { + "id": "c1_name", + "name": "Connections", + "labelFormat": "Connection" + } + } +} diff --git a/src/vision/viewpoints/tables/objectives.json b/src/vision/viewpoints/tables/objectives.json new file mode 100644 index 0000000..0a7d0e5 --- /dev/null +++ b/src/vision/viewpoints/tables/objectives.json @@ -0,0 +1,22 @@ +{ + "objectives": { + "name": "Objectives", + "diagrams": { + "all-rows": "objectives-diagram" + }, + "columnNames": { + "o1_id": "Objective 1 ID", + "o1_name": "Objective 1 Name", + "o2_id": "Objective 2 ID", + "o2_name": "Objective 2 Name" + }, + "queries": { + "obj-query": "objectives.sparql" + }, + "rowMapping": { + "id": "obj-query", + "name": "Objectives", + "labelFormat": "Objective" + } + } +} diff --git a/src/vision/viewpoints/trees/missions.json b/src/vision/viewpoints/trees/missions.json new file mode 100644 index 0000000..da2f458 --- /dev/null +++ b/src/vision/viewpoints/trees/missions.json @@ -0,0 +1,16 @@ +{ + "missions": { + "name": "Missions", + "diagrams": { + "all-rows": "missions-diagram" + }, + "queries": { + "missions": "missions.sparql" + }, + "rowMapping": { + "id": "missions", + "name": "Missions", + "labelFormat": "{m_id} {m_name}" + } + } +} diff --git a/src/vision/viewpoints/trees/requirements.json b/src/vision/viewpoints/trees/requirements.json new file mode 100644 index 0000000..2f5a6aa --- /dev/null +++ b/src/vision/viewpoints/trees/requirements.json @@ -0,0 +1,23 @@ +{ + "requirements": { + "name": "Requirements Diagram", + "diagrams": { + "all-rows": "requirements-diagram" + }, + "queries": { + "req-query": "requirements.sparql" + }, + "rowMapping": { + "id": "req-query", + "name": "Requirements", + "labelFormat": "{r_id}", + "subRowMappings": [ + { + "id": "req-query", + "name": "Components", + "labelFormat": "C Name: {c_name}" + } + ] + } + } +}