├── index.js ├── .npmignore ├── .eslintrc ├── src ├── utils │ ├── warn.js │ ├── capitalize.js │ ├── isNil.js │ ├── castArrayShape.js │ ├── isIri.js │ ├── invariant.js │ └── getIriLocalName.js ├── graph │ ├── ensureResourceExistance.js │ ├── memorize.js │ └── traversal.js ├── graphql │ ├── isGraphqlList.js │ ├── getGraphqlPolymorphicObjectType.js │ ├── getGraphqlScalarType.js │ ├── getRelayConnectionDefinitions.js │ ├── getGraphqlName.js │ ├── getGraphqlScalarResolver.js │ ├── getGraphqlInterfaces.js │ ├── getGraphqlObjectType.js │ ├── getGraphqlInterfaceType.js │ ├── getGraphqlTypeResolver.js │ ├── getGraphqlDescription.js │ ├── getGraphqlPolymorphicScalarType.js │ ├── getGraphqlFieldConfigMap.js │ ├── getGraphqlFieldConfig.js │ └── getGraphqlObjectResolver.js ├── constants.js ├── ArrayKeyedMap.js ├── requireGraphqlRelay.js ├── scalars.js └── SemanticGraph.js ├── README.md ├── test ├── utils │ ├── mockResolvers.js │ └── commonTurtlePrefixes.js └── index.js ├── examples ├── README.md ├── foaf │ ├── package.json │ ├── index.js │ └── foaf.ttl ├── basic │ ├── package.json │ ├── resolvers.js │ ├── index.js │ ├── ontology.ttl │ ├── data.js │ └── schema.graphql └── relay │ ├── package.json │ ├── ontology.ttl │ ├── resolvers.js │ ├── data.js │ └── index.js ├── .gitignore ├── .travis.yml ├── LICENSE ├── package.json ├── TODO.md ├── CHANGELOG.md └── ontologies ├── rdfs.ttl ├── rdf.ttl └── owl.ttl /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src/SemanticGraph'); 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | gitignore/ 2 | examples/ 3 | scripts/ 4 | TODO.md 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "nelson", 3 | "rules": { 4 | "import/no-unresolved": [2, { "ignore": ["graphql"] }] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/warn.js: -------------------------------------------------------------------------------- 1 | function warn(message) { 2 | console.warn(`[semantic-graphql] ${message}`); 3 | } 4 | 5 | module.exports = warn; 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Semantic GraphQL 2 | 3 | *UNMAINTAINED:* [Go to the new repo location](https://github.com/dherault/semantic-graphql) for issues and pull requests. 4 | -------------------------------------------------------------------------------- /src/utils/capitalize.js: -------------------------------------------------------------------------------- 1 | function capitalize(string) { 2 | return string.charAt(0).toUpperCase() + string.slice(1); 3 | } 4 | 5 | module.exports = capitalize; 6 | -------------------------------------------------------------------------------- /src/utils/isNil.js: -------------------------------------------------------------------------------- 1 | function isNil(value) { 2 | return typeof value === 'undefined' || value === null || (Array.isArray(value) && !value.length); 3 | } 4 | 5 | module.exports = isNil; 6 | -------------------------------------------------------------------------------- /src/utils/castArrayShape.js: -------------------------------------------------------------------------------- 1 | function castArrayShape(value, shouldBeArray = true) { 2 | const isArray = Array.isArray(value); 3 | 4 | return shouldBeArray ? 5 | isArray ? value : [value] : 6 | isArray ? value[0] : value; 7 | } 8 | 9 | module.exports = castArrayShape; 10 | -------------------------------------------------------------------------------- /test/utils/mockResolvers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | resolveSourceId: () => null, 3 | resolveSourceTypes: () => null, 4 | resolveSourcePropertyValue: () => null, 5 | resolveResource: () => null, 6 | resolveResources: () => null, 7 | resolveResourcesByPredicate: () => null, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | ## Basic 4 | 5 | A simple example of a working setup. 6 | 7 | ## Foaf 8 | 9 | Does not resolve data, simply shows how the FOAF ontology gets converted into a GraphQL schema. 10 | 11 | ## Relay 12 | 13 | Displays how to use Relay with the library. 14 | -------------------------------------------------------------------------------- /test/utils/commonTurtlePrefixes.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | @prefix owl: . 3 | @prefix rdf: . 4 | @prefix rdfs: . 5 | @prefix xsd: . 6 | @prefix : . 7 | `; 8 | -------------------------------------------------------------------------------- /src/utils/isIri.js: -------------------------------------------------------------------------------- 1 | function isIri(iri) { 2 | // According to: https://tools.ietf.org/html/rfc3987#section-2 3 | // IRI = scheme ":" ihier-part [ "?" iquery ] [ "#" ifragment ] 4 | // every IRI requires a scheme followed by ":". 5 | return typeof iri === 'string' && iri.includes(':'); 6 | } 7 | 8 | module.exports = isIri; 9 | -------------------------------------------------------------------------------- /src/graph/ensureResourceExistance.js: -------------------------------------------------------------------------------- 1 | const invariant = require('../utils/invariant'); 2 | 3 | function ensureResourceExistance(fn) { 4 | return (g, iri) => { 5 | invariant(typeof g[iri] === 'object', `Could not find the following resource: ${iri}`); 6 | 7 | return fn(g, iri); 8 | }; 9 | } 10 | 11 | module.exports = ensureResourceExistance; 12 | -------------------------------------------------------------------------------- /src/graph/memorize.js: -------------------------------------------------------------------------------- 1 | // Caches the result of a function in the graph 2 | // Allows user override 3 | // Makes sure the a (deterministic/pure) function is not called twice with the same args 4 | function memorize(fn, key) { 5 | return (g, iri) => typeof g[iri][key] !== 'undefined' ? g[iri][key] : g[iri][key] = fn(g, iri); 6 | } 7 | 8 | module.exports = memorize; 9 | -------------------------------------------------------------------------------- /src/graphql/isGraphqlList.js: -------------------------------------------------------------------------------- 1 | const { rdfType, owlFunctionalProperty } = require('../constants'); 2 | const memorize = require('../graph/memorize'); 3 | 4 | function isGraphqlList(g, iri) { 5 | return g[iri].isRelayConnection || !(g[iri][rdfType] && g[iri][rdfType].includes(owlFunctionalProperty)); 6 | } 7 | 8 | module.exports = memorize(isGraphqlList, 'isGraphqlList'); 9 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlPolymorphicObjectType.js: -------------------------------------------------------------------------------- 1 | const { rdfsResource } = require('../constants'); 2 | const getGraphqlInterfaceType = require('./getGraphqlInterfaceType'); 3 | 4 | function getGraphqlPolymorphicObjectType(g/*, ranges*/) { 5 | // TODO 6 | return getGraphqlInterfaceType(g, rdfsResource); 7 | } 8 | 9 | module.exports = getGraphqlPolymorphicObjectType; 10 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlScalarType.js: -------------------------------------------------------------------------------- 1 | const { graphqlScalarTypes } = require('../scalars'); 2 | const getIriLocalName = require('../utils/getIriLocalName'); 3 | 4 | function getGraphqlScalarType(g, iri) { 5 | const type = graphqlScalarTypes[getIriLocalName(iri)]; 6 | 7 | if (!type) throw new Error(`getGraphqlScalarType ${iri})`); 8 | 9 | return type; 10 | } 11 | 12 | module.exports = getGraphqlScalarType; 13 | -------------------------------------------------------------------------------- /src/utils/invariant.js: -------------------------------------------------------------------------------- 1 | // Inspired by Facebook's invariant 2 | // https://github.com/facebook/react/blob/v0.13.3/src/vendor/core/invariant.js 3 | function invariant(condition, message) { 4 | if (!condition) { 5 | const error = new Error(message); 6 | 7 | error.name = 'Invariant Violation'; 8 | Error.captureStackTrace(error, invariant); // Remove this function's frame from the stack 9 | 10 | throw error; 11 | } 12 | } 13 | 14 | module.exports = invariant; 15 | -------------------------------------------------------------------------------- /examples/foaf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "semantic-graphql-example-foaf", 3 | "description": "", 4 | "version": "0.0.0", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node --preserve-symlinks index.js", 8 | "watch": "nodemon --watch ../../ --exec \"npm start\"", 9 | "//note": "preserve-symlinks because of https://github.com/npm/npm/issues/5875" 10 | }, 11 | "author": "David Hérault (https://github.com/dherault)", 12 | "license": "MIT", 13 | "dependencies": { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "semantic-graphql-example-basic", 3 | "version": "0.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "node --preserve-symlinks index.js", 7 | "watch": "nodemon --watch ../../ --exec \"npm start\"", 8 | "//note": "preserve-symlinks because of https://github.com/npm/npm/issues/5875" 9 | }, 10 | "author": "David Hérault (https://github.com/dherault)", 11 | "license": "MIT", 12 | "dependencies": { 13 | "express": "^4.14.1", 14 | "express-graphql": "^0.6.2" 15 | }, 16 | "description": "" 17 | } 18 | -------------------------------------------------------------------------------- /examples/relay/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "semantic-graphql-example-basic", 3 | "version": "0.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "node --preserve-symlinks index.js", 7 | "watch": "nodemon --watch ../../ --exec \"npm start\"", 8 | "//note": "preserve-symlinks because of https://github.com/npm/npm/issues/5875" 9 | }, 10 | "author": "David Hérault (https://github.com/dherault)", 11 | "license": "MIT", 12 | "dependencies": { 13 | "express": "^4.14.1", 14 | "express-graphql": "^0.6.2" 15 | }, 16 | "description": "" 17 | } 18 | -------------------------------------------------------------------------------- /src/graphql/getRelayConnectionDefinitions.js: -------------------------------------------------------------------------------- 1 | const requireGraphqlRelay = require('../requireGraphqlRelay'); 2 | const memorize = require('../graph/memorize'); 3 | const ensureResourceExistance = require('../graph/ensureResourceExistance'); 4 | const getGraphqlObjectType = require('./getGraphqlObjectType'); 5 | 6 | function getRelayConnectionDefinitions(g, iri) { 7 | if (g.config.relay) { 8 | return requireGraphqlRelay().connectionDefinitions({ 9 | nodeType: getGraphqlObjectType(g, iri), 10 | }); 11 | } 12 | } 13 | 14 | module.exports = ensureResourceExistance(memorize(getRelayConnectionDefinitions, 'relayConnectionDefinitions')); 15 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlName.js: -------------------------------------------------------------------------------- 1 | const getIriLocalName = require('../utils/getIriLocalName'); 2 | const memorize = require('../graph/memorize'); 3 | const capitalize = require('../utils/capitalize'); 4 | 5 | // GraphQL-safe name for GraphQL types 6 | function getGraphqlName(g, iri) { 7 | const { prefixes } = g.config; 8 | const localName = getIriLocalName(iri); 9 | const namespaceIri = iri.slice(0, -localName.length); 10 | 11 | const prefix = Object.keys(prefixes).find(key => prefixes[key] === namespaceIri) || ''; 12 | 13 | return capitalize(prefix + localName).replace(/\W/g, '_'); 14 | } 15 | 16 | module.exports = memorize(getGraphqlName, 'graphqlName'); 17 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlScalarResolver.js: -------------------------------------------------------------------------------- 1 | const isNil = require('../utils/isNil'); 2 | const castArrayShape = require('../utils/castArrayShape'); 3 | const isGraphqlList = require('./isGraphqlList'); 4 | 5 | function getGraphqlScalarResolver(g, iri) { 6 | const isList = isGraphqlList(g, iri); 7 | 8 | return (source, args, context, info) => Promise.resolve(g.resolvers.resolveSourcePropertyValue(source, iri, context, info)) 9 | // We try to return data that is consistant with the property definition 10 | // i.e. if it's a list, return an Array 11 | .then(result => isNil(result) ? isList ? [] : null : castArrayShape(result, isList)); 12 | } 13 | 14 | module.exports = getGraphqlScalarResolver; 15 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlInterfaces.js: -------------------------------------------------------------------------------- 1 | const { rdfsSubClassOf, rdfsResource } = require('../constants'); 2 | const { walkmap } = require('../graph/traversal'); 3 | const getGraphqlInterfaceType = require('./getGraphqlInterfaceType'); 4 | 5 | function getGraphqlInterfaces(g, iri) { 6 | const interfaces = []; 7 | 8 | // Find super-classes of the class and their super-classes 9 | walkmap(g, iri, rdfsSubClassOf) 10 | // Many universal properties, like label and comment, have rdfs:Resource in their domain 11 | .add(rdfsResource) 12 | .forEach(classIri => interfaces.push(getGraphqlInterfaceType(g, classIri))); 13 | 14 | if (g.config.relay) interfaces.push(g.nodeInterface); 15 | 16 | return interfaces; 17 | } 18 | 19 | module.exports = getGraphqlInterfaces; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | gitignore 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # nyc test coverage 20 | .nyc_output 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directories 32 | node_modules 33 | jspm_packages 34 | 35 | # Optional npm cache directory 36 | .npm 37 | 38 | # Optional REPL history 39 | .node_repl_history 40 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlObjectType.js: -------------------------------------------------------------------------------- 1 | const { GraphQLObjectType } = require('graphql'); 2 | const memorize = require('../graph/memorize'); 3 | const ensureResourceExistance = require('../graph/ensureResourceExistance'); 4 | const getGraphqlName = require('./getGraphqlName'); 5 | const getGraphqlDescription = require('./getGraphqlDescription'); 6 | 7 | function getGraphqlObjectType(g, iri) { 8 | 9 | return new GraphQLObjectType({ 10 | name: getGraphqlName(g, iri), 11 | description: getGraphqlDescription(g, iri), 12 | fields: () => require('./getGraphqlFieldConfigMap')(g, iri), // dynamic require to prevent require cycles 13 | interfaces: () => require('./getGraphqlInterfaces')(g, iri), 14 | }); 15 | } 16 | 17 | module.exports = ensureResourceExistance(memorize(getGraphqlObjectType, 'graphqlObjectType')); 18 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlInterfaceType.js: -------------------------------------------------------------------------------- 1 | const { GraphQLInterfaceType } = require('graphql'); 2 | const memorize = require('../graph/memorize'); 3 | const ensureResourceExistance = require('../graph/ensureResourceExistance'); 4 | const getGraphqlName = require('./getGraphqlName'); 5 | const getGraphqlTypeResolver = require('./getGraphqlTypeResolver'); 6 | 7 | function getGraphqlInterfaceType(g, iri) { 8 | 9 | return new GraphQLInterfaceType({ 10 | name: `${getGraphqlName(g, iri)}Interface`, 11 | description: `Interface for ${iri}`, 12 | fields: () => require('./getGraphqlFieldConfigMap')(g, iri), // dynamic require to prevent require cycles 13 | resolveType: getGraphqlTypeResolver(g, iri), 14 | }); 15 | } 16 | 17 | module.exports = ensureResourceExistance(memorize(getGraphqlInterfaceType, 'graphqlInterfaceType')); 18 | -------------------------------------------------------------------------------- /examples/relay/ontology.ttl: -------------------------------------------------------------------------------- 1 | @prefix owl: . 2 | @prefix rdfs: . 3 | @prefix xsd: . 4 | @prefix : . 5 | 6 | :Article 7 | a owl:Class ; 8 | rdfs:comment "An article that someone wrote about something" ; 9 | rdfs:label "Article" . 10 | 11 | :Comment 12 | a owl:Class ; 13 | rdfs:comment "A comment on an article" ; 14 | rdfs:label "Comment" . 15 | 16 | :hasComments 17 | a owl:ObjectProperty ; 18 | rdfs:comment "The comments about the article" ; 19 | rdfs:domain :Article ; 20 | rdfs:label "Has comments" ; 21 | rdfs:range :Comment . 22 | 23 | :text 24 | a owl:DatatypeProperty, owl:FunctionalProperty ; 25 | rdfs:comment "The content of a comment" ; 26 | rdfs:domain :Comment ; 27 | rdfs:label "Text" ; 28 | rdfs:range xsd:string . 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | - '6' 5 | after_success: 6 | - 'npm run coverage && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls' 7 | notifications: 8 | email: false 9 | slack: 10 | secure: ces1PxGB7wrw7rS3CUrsHNqMPF32gizJq72ToYJQXinOzaufS1Nux2JPmTPU1nJsRDqn5A5fA+eII9zilgKYvWpmvFsGvgRgF5I3E/M56+7SHdvE/a40vXZZ3OaPNfxjimfkyj+zsQOvdyHKLnOnFuP9zxgIwC8S3+fALrlnp6aD8mIC9WUWNjlCoqnAQa3d1hNNQKuRf3wH+PVVLrrKYxh2ix3jW6RFlb1o/PJ8MURwtenzLca2Cei6mzgeVsceAC7PZAZwRjUEDzHuhjbv2/Vi6MGW71WxpsIQKoijxRk9Ty9bytDiyC18vkCoxJHuJeKo7q23a1nvZR/9I7NG1oLkdXsCEJmtpeZWN08BV1vrc3bZRXaK3BOwcJ2FzLvGGDoDQhu9Zxo52ugGc02HhN/jJZD8eFRWccS4OujdtSfggb+4etDTC6rEuV1iY69hc0ljQ8HKdveDrb4a812ySGva33RBqjhHoyzUP3XRrwIYOUkxHkFvLHIBJLA/bUN/v5u/QqDneOxkSpEivW/dQhmFqa8NXw3XSZGShUG2ET/RVYEJzrxfGBKJqVM9fGG+laUySefT0KNarJVT5GuZwr34qnES7NNOApRMT5sxj7AUQHoce7Acpdek4GAVbFI3MTIxuQGScdHtLLCYcmpqPaTwziltaDG7PozPt6yl9fw= 11 | -------------------------------------------------------------------------------- /examples/relay/resolvers.js: -------------------------------------------------------------------------------- 1 | const data = require('./data'); 2 | const getIriLocalName = require('../../src/utils/getIriLocalName'); 3 | 4 | module.exports = { 5 | resolveSourceId(source) { 6 | return source.id; 7 | }, 8 | resolveSourcePropertyValue(source, iri) { 9 | return source[getIriLocalName(iri)]; 10 | }, 11 | resolveSourceTypes(source) { 12 | return `http://foo.com#${source.type}`; 13 | }, 14 | resolveResource(id) { 15 | console.log('resolveId', id); 16 | 17 | return data.find(n => n.id === id); 18 | }, 19 | resolveResources(ids) { 20 | console.log('resolveId', ids); 21 | 22 | return data.filter(n => ids.includes(n.id)); 23 | }, 24 | resolveResourcesByPredicate(types, iri, value) { 25 | const typesLocalNames = types.map(getIriLocalName); 26 | const localName = getIriLocalName(iri); 27 | 28 | console.log('resolvePredicate', typesLocalNames, localName, value); 29 | 30 | return data.filter(n => typesLocalNames.includes(n.type) && n[localName] === value); 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | const x = { 2 | rdfIri: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 3 | rdfsIri: 'http://www.w3.org/2000/01/rdf-schema#', 4 | xsdIri: 'http://www.w3.org/2001/XMLSchema#', 5 | owlIri: 'http://www.w3.org/2002/07/owl#', 6 | }; 7 | 8 | x.rdfType = `${x.rdfIri}type`; 9 | x.rdfsClass = `${x.rdfsIri}Class`; 10 | x.rdfsLiteral = `${x.rdfsIri}Literal`; 11 | x.rdfsResource = `${x.rdfsIri}Resource`; 12 | x.rdfsLabel = `${x.rdfsIri}label`; 13 | x.rdfsComment = `${x.rdfsIri}comment`; 14 | x.rdfsDomain = `${x.rdfsIri}domain`; 15 | x.rdfsRange = `${x.rdfsIri}range`; 16 | x.rdfsSubClassOf = `${x.rdfsIri}subClassOf`; 17 | x.rdfsSubPropertyOf = `${x.rdfsIri}subPropertyOf`; 18 | x.owlFunctionalProperty = `${x.owlIri}FunctionalProperty`; 19 | x.owlInverseOf = `${x.owlIri}inverseOf`; 20 | 21 | x._rdfType = `_${x.rdfType}`; 22 | x._rdfsDomain = `_${x.rdfsDomain}`; 23 | x._rdfsSubClassOf = `_${x.rdfsSubClassOf}`; 24 | x._rdfsSubPropertyOf = `_${x.rdfsSubPropertyOf}`; 25 | x._owlInverseOf = `_${x.owlInverseOf}`; 26 | 27 | module.exports = x; 28 | -------------------------------------------------------------------------------- /src/ArrayKeyedMap.js: -------------------------------------------------------------------------------- 1 | /* 2 | A Map that accepts unordered arrays of strings as its keys. 3 | 4 | const myMap = new ArrayKeyedMap(); 5 | myMap.set(['foo', 'bar'], 'somevalue'); 6 | myMap.get(['bar', 'foo']); // 'somevalue' 7 | */ 8 | 9 | const sep = Math.random().toString(); 10 | const hash = array => array.sort().join(sep); 11 | // const unhash = key => key.split(sep); 12 | 13 | class ArrayKeyedMap extends Map { 14 | 15 | get(array) { 16 | return super.get(hash(array)); 17 | } 18 | 19 | set(array, value) { 20 | return super.set(hash(array), value); 21 | } 22 | 23 | has(array) { 24 | return super.has(hash(array)); 25 | } 26 | 27 | /* 28 | delete(array) { 29 | return super.delete(hash(array)); 30 | } 31 | 32 | forEach(cb, thisArg) { 33 | return super.forEach((value, key, that) => cb(value, unhash(key), that), thisArg); 34 | } 35 | 36 | map(cb, thisArg) { 37 | return super.map((value, key, that) => cb(value, unhash(key), that), thisArg); 38 | } 39 | */ 40 | } 41 | 42 | module.exports = ArrayKeyedMap; 43 | -------------------------------------------------------------------------------- /src/requireGraphqlRelay.js: -------------------------------------------------------------------------------- 1 | let graphqlRelay; 2 | 3 | // optionalPeerDependencies still don't exist, so graphql-relay is a ghost dep 4 | // let's find it 5 | function requireGraphqlRelay() { 6 | if (graphqlRelay) return graphqlRelay; 7 | 8 | try { 9 | graphqlRelay = require('graphql-relay'); 10 | } 11 | catch (ex) { 12 | // Nothing 13 | } 14 | 15 | if (!graphqlRelay) { 16 | // Go up until graphql-relay is found 17 | // Inspired by https://www.npmjs.com/package/parent-require 18 | for (let parent = module.parent; parent && !graphqlRelay; parent = parent.parent) { 19 | try { 20 | graphqlRelay = parent.require('graphql-relay'); 21 | } 22 | catch (ex) { 23 | // Nothing 24 | } 25 | } 26 | 27 | // No pity 28 | if (!graphqlRelay) throw new Error('semantic-graphql was not able to find "graphql-relay" as a dependency of your project. Run "npm install graphql-relay" or set the "relay" option to false.'); 29 | } 30 | 31 | return graphqlRelay; 32 | } 33 | 34 | module.exports = requireGraphqlRelay; 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2019 David Hérault 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlTypeResolver.js: -------------------------------------------------------------------------------- 1 | const { _rdfsSubClassOf, rdfsResource } = require('../constants'); 2 | const isNil = require('../utils/isNil'); 3 | const castArrayShape = require('../utils/castArrayShape'); 4 | const { walkmap } = require('../graph/traversal'); 5 | const getGraphqlObjectType = require('./getGraphqlObjectType'); 6 | 7 | function getGraphqlTypeResolver(g, iri) { 8 | 9 | // We look for all sub-classes of this rdfs:Class 10 | const classes = [...walkmap(g, iri, _rdfsSubClassOf)]; 11 | const l = classes.length - 1; 12 | 13 | return (source, info) => Promise.resolve(g.resolvers.resolveSourceTypes(source, info)) 14 | .then(types => { 15 | // Everything is a rdfs:Resource, hence the fallback 16 | if (isNil(types)) return getGraphqlObjectType(g, rdfsResource); 17 | 18 | const typesArray = castArrayShape(types); 19 | 20 | // From last to first to return the most restrictive class 21 | for (let i = l; i >= 0; i--) { 22 | const classIri = classes[i]; 23 | 24 | if (typesArray.includes(classIri)) return getGraphqlObjectType(g, classIri); 25 | } 26 | 27 | // This is the case when iri === rdfsResource 28 | return getGraphqlObjectType(g, typesArray[0]); 29 | }); 30 | } 31 | 32 | module.exports = getGraphqlTypeResolver; 33 | -------------------------------------------------------------------------------- /examples/foaf/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { GraphQLSchema, GraphQLObjectType, printSchema } = require('graphql'); // eslint-disable-line import/no-extraneous-dependencies 4 | const SemanticGraph = require('../..'); 5 | 6 | const mockFunction = () => null; 7 | const resolvers = { 8 | resolveSourceId: mockFunction, 9 | resolveSourcePropertyValue: mockFunction, 10 | resolveSourceTypes: mockFunction, 11 | resolveResource: mockFunction, 12 | resolveResources: mockFunction, 13 | resolveResourcesByPredicate: mockFunction, 14 | }; 15 | 16 | // First we create a SemanticGraph 17 | const _ = new SemanticGraph(resolvers); 18 | 19 | // Then we add our triples 20 | _.parseFile(path.join(__dirname, './foaf.ttl')); 21 | 22 | console.log(`graph created: ${_}`); 23 | 24 | // Finally we can build our shema 25 | const schema = new GraphQLSchema({ 26 | query: new GraphQLObjectType({ 27 | name: 'Query', 28 | fields: { 29 | person: { 30 | type: _.getObjectType('http://xmlns.com/foaf/0.1/Person'), 31 | resolve: () => ({}), 32 | }, 33 | }, 34 | }), 35 | }); 36 | 37 | // Save schema in Schema language to disk 38 | fs.writeFileSync(path.join(__dirname, './foaf.graphql'), printSchema(schema)); 39 | console.log('Schema saved on disk'); 40 | -------------------------------------------------------------------------------- /examples/basic/resolvers.js: -------------------------------------------------------------------------------- 1 | const data = require('./data'); 2 | const getIriLocalName = require('../../src/utils/getIriLocalName'); 3 | 4 | module.exports = { 5 | resolveSourceId(source) { 6 | console.log('resolveSourceId', source.id); 7 | 8 | return source.id; 9 | }, 10 | resolveSourcePropertyValue(source, iri) { 11 | const localName = getIriLocalName(iri); 12 | 13 | console.log('resolveSourcePropertyValue', source.id, localName); 14 | 15 | return source[localName]; // The correct shape (array or not) will be cast 16 | }, 17 | resolveSourceTypes(source) { 18 | console.log('resolveSourceTypes', source.id, source.type); 19 | 20 | return `http://foo.com#${source.type}`; // Or an array of types 21 | }, 22 | resolveResource(id) { 23 | console.log('resolveResource', id); 24 | 25 | return data.find(n => n.id === id); 26 | }, 27 | resolveResources(ids) { 28 | console.log('resolveResources', ids); 29 | 30 | return data.filter(n => ids.includes(n.id)); 31 | }, 32 | resolveResourcesByPredicate(types, iri, value) { 33 | const typesLocalNames = types.map(getIriLocalName); 34 | const localName = getIriLocalName(iri); 35 | 36 | console.log('resolveResourcesByPredicate', typesLocalNames, localName, value); 37 | 38 | return data.filter(n => typesLocalNames.includes(n.type) && n[localName] === value); 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /src/graph/traversal.js: -------------------------------------------------------------------------------- 1 | const warn = require('../utils/warn'); 2 | 3 | // Possible bug: stack overflow 4 | 5 | // Both methods walk a graph: g 6 | // from a given vertex (:=startVertex): iri 7 | 8 | // Adds startVertex to the output 9 | // exits startVertex using a given edge: walkIri, and recurse on the result 10 | function walkmap(g, iri, walkIri, s = new Set()) { 11 | if (s.has(iri)) return s; // Prevents cycles 12 | if (!g[iri]) return warn(`Resource missing in graph: ${iri}`) || s; 13 | 14 | s.add(iri); 15 | 16 | if (g[iri][walkIri]) g[iri][walkIri].forEach(wIri => walkmap(g, wIri, walkIri, s)); 17 | 18 | return s; 19 | } 20 | 21 | // Adds vertices connected to startVertex by a given edge: lookIri, to the output 22 | // if the output is not empty returns the output 23 | // else exit startVertex using a given edge: walkIri, and recurse on the result 24 | function walklook(g, iri, walkIri, lookIri, s = new Set(), ws = new Set()) { 25 | if (ws.has(iri)) return s; // Prevents cycles 26 | if (!g[iri]) return warn(`Resource missing in graph: ${iri}`) || s; 27 | 28 | ws.add(iri); 29 | 30 | if (g[iri][lookIri]) g[iri][lookIri].forEach(lIri => s.add(lIri)); 31 | 32 | if (s.size) return s; 33 | 34 | if (g[iri][walkIri]) g[iri][walkIri].forEach(wIri => walklook(g, wIri, walkIri, lookIri, s, ws)); 35 | 36 | return s; 37 | } 38 | 39 | module.exports = { 40 | walkmap, 41 | walklook, 42 | }; 43 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlDescription.js: -------------------------------------------------------------------------------- 1 | const { isLiteral, getLiteralValue, getLiteralLanguage } = require('n3').Util; 2 | const { rdfsLabel, rdfsComment } = require('../constants'); 3 | const getIriLocalName = require('../utils/getIriLocalName'); 4 | const memorize = require('../graph/memorize'); 5 | 6 | const englishLocale = 'en'; 7 | const isLiteralWithLocale = locale => l => isLiteral(l) && getLiteralLanguage(l) === locale; 8 | 9 | function findValueForLocale(literals, locale) { 10 | if (!literals) return null; 11 | 12 | const literal = literals.find(isLiteralWithLocale(locale)) 13 | || literals.find(isLiteralWithLocale(englishLocale)) 14 | || literals[0]; 15 | 16 | return isLiteral(literal) ? getLiteralValue(literal) : null; 17 | } 18 | 19 | function getGraphqlDescription(g, iri) { 20 | // The default locale is "en", can be set with config.locale 21 | const { locale = englishLocale } = g.config; 22 | 23 | const label = findValueForLocale(g[iri][rdfsLabel], locale); 24 | const comment = findValueForLocale(g[iri][rdfsComment], locale); 25 | 26 | let description = label && getIriLocalName(iri) !== label ? label : ''; 27 | 28 | if (comment) { 29 | if (description) description += ' - '; 30 | 31 | description += comment; 32 | } 33 | 34 | if (description && !description.endsWith('.')) description += '.'; 35 | 36 | return description; 37 | } 38 | 39 | module.exports = memorize(getGraphqlDescription, 'graphqlDescription'); 40 | -------------------------------------------------------------------------------- /examples/relay/data.js: -------------------------------------------------------------------------------- 1 | const assignTypeAndId = type => x => Object.assign({ type, id: x.text }, x); 2 | 3 | const comments = [ 4 | { text: 'zeroth comment' }, 5 | { text: 'first comment' }, 6 | { text: 'second comment' }, 7 | { text: 'third comment' }, 8 | { text: 'fourth comment' }, 9 | { text: 'fifth comment' }, 10 | { text: 'sixth comment' }, 11 | { text: 'seventh comment' }, 12 | { text: 'eighth comment' }, 13 | { text: 'ninth comment' }, 14 | { text: 'tenth comment' }, 15 | { text: 'eleventh comment' }, 16 | { text: 'twelfth comment' }, 17 | { text: 'thirteenth comment' }, 18 | { text: 'fourteenth comment' }, 19 | { text: 'fifteenth comment' }, 20 | { text: 'sixteenth comment' }, 21 | { text: 'seventeenth comment' }, 22 | { text: 'eighteenth comment' }, 23 | { text: 'nineteenth comment' }, 24 | ].map(assignTypeAndId('Comment')); // type is useless for this example 25 | 26 | module.exports = [ 27 | { 28 | id: 'cool_article', 29 | type: 'Article', 30 | // The reference is usualy on the child, this can be done using owl:inverseOf 31 | // foo:hasComments owl:inverseOf foo:belongsToArticle (where foo:belongsToArticle has foo:Comment in its domain) 32 | // The lib would resolve foo:hasComments on foo:Article using the reference on foo:Comment instances 33 | // Here none of it is required since we just want to display how to handle relay connections 34 | hasComments: comments.map(c => c.id), 35 | }, 36 | ...comments, 37 | ]; 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "semantic-graphql", 3 | "version": "0.6.3", 4 | "description": "Create GraphQL schemas from RDF ontologies", 5 | "license": "MIT", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/nelson-ai/semantic-graphql.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/nelson-ai/semantic-graphql/issues" 13 | }, 14 | "homepage": "https://github.com/nelson-ai/semantic-graphql#readme", 15 | "engines": { 16 | "node": ">=6.9.1" 17 | }, 18 | "author": "David Hérault (https://github.com/dherault)", 19 | "contributors": [ 20 | "Austin Harris (https://github.com/Astn)" 21 | ], 22 | "scripts": { 23 | "test": "./node_modules/.bin/mocha --bail --check-leaks", 24 | "coverage": "./node_modules/.bin/istanbul cover _mocha -- --bail --check-leaks", 25 | "coverage:serve": "cd coverage/lcov-report && python -m SimpleHTTPServer", 26 | "coverage:all": "npm run coverage && npm run coverage:serve", 27 | "dev": "cd examples/basic && npm run watch" 28 | }, 29 | "devDependencies": { 30 | "chai": "^4.2.0", 31 | "coveralls": "^3.0.3", 32 | "eslint": "^5.15.1", 33 | "eslint-config-nelson": "^0.2.0", 34 | "eslint-plugin-import": "^2.16.0", 35 | "graphql": "^14.1.1", 36 | "graphql-relay": "^0.6.0", 37 | "istanbul": "^0.4.5", 38 | "mocha": "^6.0.2" 39 | }, 40 | "dependencies": { 41 | "n3": "^0.10.0" 42 | }, 43 | "peerDependencies": { 44 | "graphql": "^14.1.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/utils/getIriLocalName.js: -------------------------------------------------------------------------------- 1 | const pound = '#'; 2 | const slash = '/'; 3 | const colon = ':'; 4 | const memory = {}; 5 | 6 | function sliceOrFail(string, sep) { 7 | const array = string.split(sep); 8 | const l = array.length; 9 | 10 | return l < 2 ? null : array[l - 1]; 11 | } 12 | 13 | // Extracts the localName of an IRI 14 | // Algo inspired by http://rdf4j.org/javadoc/latest/org/eclipse/rdf4j/model/IRI.html 15 | function getIriLocalName(iri) { 16 | if (memory[iri]) return memory[iri]; // ! 17 | if (!(typeof iri === 'string' && iri.includes(colon))) throw new Error(`Given IRI "${iri}" is invalid`); 18 | 19 | let workingIri = iri; 20 | const protocolArray = iri.split('://'); 21 | 22 | if (protocolArray.length > 2) throw new Error(`Given IRI "${iri}" is invalid`); 23 | if (protocolArray.length > 1) workingIri = protocolArray[1]; 24 | 25 | const resPound = sliceOrFail(workingIri, pound); 26 | 27 | if (typeof resPound === 'string') { 28 | if (!resPound.length) throw new Error(`Given IRI "${iri}" is invalid`); 29 | 30 | return memory[iri] = resPound; 31 | } 32 | 33 | const resSlash = sliceOrFail(workingIri, slash); 34 | 35 | if (typeof resSlash === 'string') { 36 | if (!resSlash.length) throw new Error(`Given IRI "${iri}" is invalid`); 37 | 38 | return memory[iri] = resSlash; 39 | } 40 | const resColon = sliceOrFail(workingIri, colon); 41 | 42 | if (typeof resColon === 'string') { 43 | if (!resColon.length) throw new Error(`Given IRI "${iri}" is invalid`); 44 | 45 | return memory[iri] = resColon; 46 | } 47 | 48 | throw new Error(`Given IRI "${iri}" is invalid`); 49 | } 50 | 51 | module.exports = getIriLocalName; 52 | -------------------------------------------------------------------------------- /examples/relay/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { GraphQLSchema, GraphQLObjectType } = require('graphql'); // eslint-disable-line import/no-extraneous-dependencies 3 | const graphqlHTTP = require('express-graphql'); 4 | const express = require('express'); 5 | const SemanticGraph = require('../..'); 6 | 7 | const data = require('./data'); 8 | const resolvers = require('./resolvers'); 9 | 10 | // You should check the basic example first 11 | const _ = new SemanticGraph(resolvers, { relay: true }); 12 | 13 | console.log(`graph created: ${_}`); 14 | 15 | _.parseFile(path.join(__dirname, './ontology.ttl')); 16 | 17 | // Register connections 18 | // This will add the proper mechanics around the field (ie the connectionArgs and the connectionResolver) 19 | _['http://foo.com#hasComments'].isRelayConnection = true; 20 | 21 | // Any part of the field can still be overriden with 22 | // _['http://foo.com#hasComments'].graphqlFieldConfigExtension = { type: ..., resolve: ..., ...} 23 | // Or the field can be overriden entirely using 24 | // _['http://foo.com#hasComments'].graphqlFieldConfig = { type: ..., resolve: ..., ...} 25 | 26 | const schema = new GraphQLSchema({ 27 | query: new GraphQLObjectType({ 28 | name: 'Query', 29 | fields: { 30 | article: { 31 | type: _.getObjectType('http://foo.com#Article'), 32 | descriptions: 'A cool article with paginated comments', 33 | resolve: () => data[0], 34 | }, 35 | node: _.nodeField, 36 | }, 37 | }), 38 | }); 39 | 40 | express() 41 | .use('/graphql', graphqlHTTP({ 42 | schema, 43 | pretty: true, 44 | graphiql: true, 45 | })) 46 | .listen(3000, err => console.log(err || 'GraphQL endpoint listening on port 3000\n')); 47 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlPolymorphicScalarType.js: -------------------------------------------------------------------------------- 1 | const { GraphQLScalarType } = require('graphql'); 2 | const ArrayKeyedMap = require('../ArrayKeyedMap'); 3 | const getIriLocalName = require('../utils/getIriLocalName'); 4 | const { graphqlScalarTypes, graphqlScalarMethods } = require('../scalars'); 5 | 6 | const memory = new ArrayKeyedMap(); 7 | 8 | function getGraphqlPolymorphicScalarType(g, ranges) { 9 | if (memory.has(ranges)) return memory.get(ranges); 10 | 11 | // Polymorphic range: not cached, so we create it 12 | // NOTE: The current implementation uses the ordered ranges to pick the prefered type when 13 | // multiple types are available. (typically float and integer, string and id, etc...) 14 | const localNames = ranges.map(range => getIriLocalName(range)); 15 | const scalarTypes = localNames.map(localName => graphqlScalarTypes[localName]); 16 | 17 | if (scalarTypes.some(type => !type)) throw new Error(`Validate much? ranges: ${ranges}`); 18 | 19 | const scalarMethods = scalarTypes.map(type => graphqlScalarMethods.get(type)); 20 | 21 | // No exception thrown here, GraphQL takes care of it 22 | const coerce = value => { 23 | const correctMethods = scalarMethods.filter(({ isOfType }) => isOfType(value)); 24 | 25 | if (!correctMethods.length) return null; 26 | 27 | return correctMethods[0].coerce(value); // Favors precedence in graphqlScalarMethods 28 | }; 29 | 30 | const type = new GraphQLScalarType({ 31 | name: `Polymorphic_scalar_${localNames.join('_')}`, 32 | serialize: coerce, 33 | parseValue: coerce, 34 | parseLiteral: ast => scalarMethods 35 | .map(({ parseLiteral }) => parseLiteral(ast)) 36 | .filter(value => value !== null)[0] || null, // TODO: use find 37 | }); 38 | 39 | memory.set(ranges, type); 40 | 41 | return type; 42 | } 43 | 44 | module.exports = getGraphqlPolymorphicScalarType; 45 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # To do 2 | 3 | ## High 4 | 5 | - [ ] Fully sync resolvers 6 | - [ ] Add iri blacklist (userland?) 7 | - [ ] drop n3 support (requires semantic-toolkit) 8 | - [ ] support blank nodes 9 | - [ ] consider restrictions as classes (for now) 10 | - [ ] allow contracted iris on API (requires semantic-toolkit) 11 | 12 | ## Low 13 | 14 | - [ ] store only triples with useful predicates on Graph 15 | - [ ] support restrictions 16 | - [ ] Change SemanticGraph API to pass resolvers whenever 17 | - [ ] isGraphqlList: infer desecendant of owl:FunctionalProperty 18 | - [ ] promisify resolver at set time 19 | - [ ] add recipes for resolvers 20 | - [ ] refactor and dry up graphql folder 21 | - [ ] improve objectResolver performance 22 | - [ ] refactor getGraphqlScalarResolver 23 | - [ ] try using interfaces instead of ObjectTypes on fields, to see 24 | - [ ] support equivalences/sameAs 25 | - [ ] use a "consider all classes disjoint" option 26 | - [ ] Document polymorphism 27 | - [ ] error messages 28 | - [ ] docs 29 | - [ ] tests (test schema (string) generation, and inference execution) 30 | - [ ] SPARQL example 31 | 32 | ## Done 33 | 34 | - [x] allow up and down option for inverseOf inference 35 | - [x] place id field on top of the other fields for introspection queries to look nice 36 | - [x] use GraphQLObjectTypeConfig.isTypeOf (with multiple class IRI) instead of GraphQLInterfaceTypeConfig.resolveType. 37 | it's optionnal on relay: https://github.com/graphql/graphql-relay-js/blob/373f2dab5fc6d4ac4cf6394aa94cbebd8cb64650/src/node/node.js 38 | - [x] full promise support 39 | - [x] individuals support 40 | - [x] remove individuals support 41 | - [x] extend field for a given class 42 | - [x] ignore class or field globally: userland 43 | - [x] delete field on an ObjectType: userland ? 44 | - [x] mutate graph data: wont do 45 | - [x] make sure walklook behaves as wanted, find exceptions 46 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlFieldConfigMap.js: -------------------------------------------------------------------------------- 1 | const { GraphQLID } = require('graphql'); 2 | const { rdfsSubClassOf, rdfsResource, _rdfsDomain, _rdfsSubPropertyOf } = require('../constants'); 3 | const getIriLocalName = require('../utils/getIriLocalName'); 4 | const warn = require('../utils/warn'); 5 | const memorize = require('../graph/memorize'); 6 | const { walkmap } = require('../graph/traversal'); 7 | const requireGraphqlRelay = require('../requireGraphqlRelay'); 8 | const getGraphqlFieldConfig = require('./getGraphqlFieldConfig'); 9 | const getGraphqlName = require('./getGraphqlName'); 10 | 11 | function getGraphqlFieldConfigMap(g, iri) { 12 | const properties = new Set(); 13 | 14 | // Find super-classes of the class and their super-classes 15 | walkmap(g, iri, rdfsSubClassOf) 16 | // Everything is a Resource, plus many universal properties 17 | // like label and comment, have rdfs:Resource in their domain 18 | .add(rdfsResource) 19 | // For each class, find properties on their domain 20 | .forEach(classIri => g[classIri][_rdfsDomain] && 21 | // For each property, add the property to the list and find its subProperties and their subProperties 22 | g[classIri][_rdfsDomain].forEach(property => walkmap(g, property, _rdfsSubPropertyOf, properties))); 23 | 24 | const fieldConfigMap = {}; 25 | const fieldConfigExtensionMap = g[iri].graphqlFieldConfigExtensions || {}; // From userland 26 | 27 | // Add id field 28 | if (!g.config.preventIdField) { 29 | if (g.config.relay) { 30 | fieldConfigMap.id = requireGraphqlRelay().globalIdField(getGraphqlName(g, iri), g.resolvers.resolveSourceId); 31 | } 32 | else { 33 | fieldConfigMap.id = { 34 | type: GraphQLID, 35 | description: 'A unique identifier for the resource.', 36 | resolve: (source, args, context, info) => g.resolvers.resolveSourceId(source, context, info), 37 | }; 38 | } 39 | } 40 | 41 | // Add other fields 42 | properties.forEach(propertyIri => { 43 | const localName = getIriLocalName(propertyIri); 44 | 45 | if (fieldConfigMap[localName]) return warn(`Duplicate localName with ${propertyIri} on fieldConfigMap of ${iri}`); 46 | 47 | const fieldConfig = getGraphqlFieldConfig(g, propertyIri); 48 | 49 | if (fieldConfig) fieldConfigMap[localName] = Object.assign(fieldConfig, fieldConfigExtensionMap[propertyIri]); 50 | }); 51 | 52 | return fieldConfigMap; 53 | } 54 | 55 | module.exports = memorize(getGraphqlFieldConfigMap, 'graphqlFieldConfigMap'); 56 | -------------------------------------------------------------------------------- /examples/basic/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { GraphQLSchema, GraphQLObjectType, GraphQLList, GraphQLString, printSchema } = require('graphql'); // eslint-disable-line import/no-extraneous-dependencies 4 | const graphqlHTTP = require('express-graphql'); 5 | const express = require('express'); 6 | const SemanticGraph = require('../..'); 7 | 8 | const data = require('./data'); 9 | const resolvers = require('./resolvers'); 10 | 11 | // First we create a SemanticGraph 12 | const _ = new SemanticGraph(resolvers); 13 | 14 | console.log(`graph created: ${_}`); 15 | 16 | // Then we add our triples 17 | _.parseFile(path.join(__dirname, './ontology.ttl')); 18 | 19 | // Optionally we can tell semantic-graphql that in order to resolve foo:hasEmployees on foo:Company 20 | // it should not look for the data on individuals of foo:Company, 21 | // but use the owl:inverseOf properties on foo:hasEmployees (i.e. foo:worksForCompany on foo:Person). 22 | // This could allows to save a trip to the database in some real world situations. 23 | _['http://foo.com#hasEmployees'].shouldAlwaysUseInverseOf = true; 24 | 25 | // Finally we can build our shema 26 | const schema = new GraphQLSchema({ 27 | query: new GraphQLObjectType({ 28 | name: 'Query', 29 | fields: { 30 | companies: { 31 | type: new GraphQLList(_.getObjectType('http://foo.com#Company')), 32 | descriptions: 'All the Companies in database.', 33 | resolve: () => data.filter(node => node.type === 'Company'), 34 | }, 35 | thing: { 36 | // Using rdfs:Resource also works. It queries anything. 37 | // type: _.getInterfaceType('http://www.w3.org/2000/01/rdf-schema#Resource'), 38 | type: _.getInterfaceType('http://foo.com#Thing'), 39 | description: 'Anything you like, by id. Similar to Relay\'s node field.', 40 | args: { 41 | id: { 42 | type: GraphQLString, 43 | defaultValue: 'French', // of rdf:type foo:Language 44 | }, 45 | }, 46 | resolve: (_, { id }) => data.find(node => node.id === id), 47 | }, 48 | }, 49 | }), 50 | }); 51 | 52 | // Save schema in Schema language to disk 53 | fs.writeFileSync(path.join(__dirname, './schema.graphql'), printSchema(schema)); 54 | console.log('Schema saved on disk'); 55 | 56 | // Start server 57 | express() 58 | .use('/graphql', graphqlHTTP({ 59 | schema, 60 | pretty: true, 61 | graphiql: true, 62 | })) 63 | .listen(3000, err => console.log(err || 'GraphQL endpoint listening on port 3000\n')); 64 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlFieldConfig.js: -------------------------------------------------------------------------------- 1 | const { GraphQLList } = require('graphql'); 2 | const { xsdIri, rdfsLiteral, rdfsSubPropertyOf, rdfsRange } = require('../constants'); 3 | const warn = require('../utils/warn'); 4 | const { walklook } = require('../graph/traversal'); 5 | const memorize = require('../graph/memorize'); 6 | const requireGraphqlRelay = require('../requireGraphqlRelay'); 7 | const isGraphqlList = require('./isGraphqlList'); 8 | const getGraphqlDescription = require('./getGraphqlDescription'); 9 | const getGraphqlObjectType = require('./getGraphqlObjectType'); 10 | const getGraphqlScalarType = require('./getGraphqlScalarType'); 11 | const getGraphqlPolymorphicScalarType = require('./getGraphqlPolymorphicScalarType'); 12 | const getGraphqlPolymorphicObjectType = require('./getGraphqlPolymorphicObjectType'); 13 | const getGraphqlScalarResolver = require('./getGraphqlScalarResolver'); 14 | const getGraphqlObjectResolver = require('./getGraphqlObjectResolver'); 15 | const getRelayConnectionDefinitions = require('./getRelayConnectionDefinitions'); 16 | 17 | const isLiteral = iri => iri.startsWith(xsdIri) || iri === rdfsLiteral; 18 | 19 | function getGraphqlFieldConfig(g, iri) { 20 | // Look for a range, return it if found 21 | // Otherwise for each super-property, look for a range, 22 | // if not found, check their super-properties and so on 23 | // TODO: check walklook, maybe test it 24 | const ranges = [...walklook(g, iri, rdfsSubPropertyOf, rdfsRange)]; 25 | const nRanges = ranges.length; 26 | 27 | if (!nRanges) return; 28 | 29 | const fieldConfig = { 30 | description: getGraphqlDescription(g, iri), 31 | }; 32 | 33 | if (ranges.every(isLiteral)) { 34 | fieldConfig.resolve = getGraphqlScalarResolver(g, iri); 35 | fieldConfig.type = nRanges === 1 ? getGraphqlScalarType(g, ranges[0]) : getGraphqlPolymorphicScalarType(g, ranges); 36 | } 37 | else if (ranges.some(isLiteral)) { 38 | return warn(`Mixed literal/non-literal ranges on ${iri}:\n${ranges}`); 39 | } 40 | else { 41 | fieldConfig.resolve = getGraphqlObjectResolver(g, iri, ranges); 42 | fieldConfig.type = nRanges === 1 ? getGraphqlObjectType(g, ranges[0]) : getGraphqlPolymorphicObjectType(g, ranges); 43 | } 44 | 45 | if (isGraphqlList(g, iri)) fieldConfig.type = new GraphQLList(fieldConfig.type); 46 | 47 | if (g.config.relay && g[iri].isRelayConnection) { 48 | fieldConfig.args = requireGraphqlRelay().connectionArgs; 49 | fieldConfig.type = getRelayConnectionDefinitions(g, ranges[0]).connectionType; 50 | } 51 | 52 | // Support partial overrides from user 53 | // full override is achieved with the memorize wrapper 54 | if (typeof g[iri].graphqlFieldConfigExtension === 'object') Object.assign(fieldConfig, g[iri].graphqlFieldConfigExtension); 55 | 56 | return fieldConfig; 57 | } 58 | 59 | module.exports = memorize(getGraphqlFieldConfig, 'graphqlFieldConfig'); 60 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.6.3 4 | 5 | **Miscellaneous:** 6 | - Change repository location 7 | - Update deps 8 | 9 | ## 0.6.2 10 | 11 | **Miscellaneous:** 12 | - Updated dependencies and added lockfile. 13 | 14 | ## 0.6.1 15 | 16 | **Bug fixes:** 17 | - Improved `isIri` to support more IRIs. See #1 and #2. 18 | 19 | ## 0.6.0 20 | 21 | **Breaking changes:** 22 | - The names of generated GraphQL types are now capitalized regardless of the terminology. 23 | 24 | **New features:** 25 | - `resolvers.resolveSourceTypes` can now return a Promise. 26 | 27 | **Miscellaneous:** 28 | - `SemanticGraph#toString` now displays the number of triples in the graph. 29 | - Triples with predicates not used by the lib are not stored in memory. 30 | - Improved documentation. 31 | - Improved tests. 32 | 33 | ## 0.5.1 34 | 35 | **Bug fixes:** 36 | - Bug on `owl:inverseOf` inference that broke the feature in some cases. 37 | 38 | ## 0.5.0 39 | 40 | **Breaking changes:** 41 | - `getIriLocalName` is not exposed/exported by the package anymore. 42 | 43 | **New features:** 44 | - On in-graph properties, new `shouldAlwaysUseInverseOf` and `shouldNeverUseInverseOf` config keys to modify the resolver's behavior. 45 | 46 | **Bug fixes:** 47 | - `isGraphqlList` is now also infered from `isGraphqlConnection`. 48 | - `preventIdField` config option can now also prevent the Relay id field. 49 | 50 | **Miscellaneous:** 51 | - Tests! :tada: (very basic for now) 52 | - Improved documentation. 53 | 54 | ## 0.4.0 55 | 56 | **Breaking changes:** 57 | - `resolvers.resolveSourceTypes` must now be sync. 58 | - Interface type resolving was rolled back on InterfaceTypes (instead of ObjectTypes). Better support, although still incomplete. External ObjectTypes must not provide an `isTypeOf` method anymore, instead external InterfaceTypes must provide a `resolveType` method. 59 | 60 | **Bug fixes:** 61 | - Fragile type resolution on interfaces. Will require further work. 62 | 63 | **Miscellaneous:** 64 | - Promisify using `Promise.resolve` instead of home-made function. It's slower but safer. 65 | 66 | ## 0.3.1 67 | 68 | **Bug fixes:** 69 | - Warn when traversing graph and encoutering missing vertices. 70 | 71 | ## 0.3.0 72 | 73 | **Breaking changes:** 74 | - Cannot override `relayEdgeType` and `relayConnectionType` anymore. `relayConnectionDefinitions` override added instead. 75 | 76 | **Bug fixes:** 77 | - Bug concerning the creation of Relay types. 78 | 79 | ## 0.2.1 80 | 81 | **Bug fixes:** 82 | - Fixed a bug concerning the inference of owl:inverseOf. 83 | 84 | ## 0.2.0 85 | 86 | **Breaking changes:** 87 | - Removed `resolvers.resolveSourceClassIri`. 88 | - Added `resolvers.resolveSourceTypes`. 89 | - Interface type resolving now happens on GraphQLObjectTypes. This means that your external GraphQLObjectTypes must provide an `isTypeOf` method. 90 | 91 | **New features:** 92 | - Promise support for all resolvers. 93 | 94 | **Bug fixes:** 95 | - Fixed `requireGraphqlRelay` behavior. 96 | - Fixed a bug on `SemanticGraph#addFieldOnObjectType`. 97 | - Fixed a bug that happened when inferring owl:inverseOf on properties that are a rdfs:subProperty with no rdfs:range. 98 | - Fixed a circular dependency in ./src/graphql. 99 | 100 | **Miscellaneous:** 101 | - Add MIT license. 102 | - Add .npmignore file. 103 | - id field now appears on top when introspecting. 104 | - graphqlDescription are now created from the locale in config. 105 | 106 | ## 0.1.0 107 | 108 | First release! :tada: 109 | -------------------------------------------------------------------------------- /src/scalars.js: -------------------------------------------------------------------------------- 1 | const { GraphQLID, GraphQLBoolean, GraphQLInt, GraphQLFloat, GraphQLString, Kind } = require('graphql'); 2 | 3 | // https://www.w3.org/TR/xmlschema-2 4 | // http://graphql.org/docs/api-reference-type-system/#graphqlscalartype 5 | const graphqlScalarTypes = { 6 | Literal: GraphQLString, // refers to rdfs:Literal 7 | /* -------------------- 8 | Primitive datatypes 9 | -------------------- */ 10 | string: GraphQLString, 11 | boolean: GraphQLBoolean, 12 | decimal: GraphQLFloat, 13 | float: GraphQLFloat, 14 | double: GraphQLFloat, 15 | duration: GraphQLString, 16 | dateTime: GraphQLString, 17 | time: GraphQLString, 18 | date: GraphQLString, 19 | gYearMonth: GraphQLString, 20 | gYear: GraphQLString, 21 | gMonthDay: GraphQLString, 22 | gDay: GraphQLString, 23 | gMonth: GraphQLString, 24 | hexBinary: GraphQLString, 25 | base64Binary: GraphQLString, 26 | anyURI: GraphQLString, 27 | QName: GraphQLString, 28 | NOTATION: GraphQLString, 29 | /* ------------------ 30 | Derived datatypes 31 | ------------------ */ 32 | normalizedString: GraphQLString, 33 | token: GraphQLString, 34 | language: GraphQLString, 35 | NMTOKEN: GraphQLString, 36 | // NMTOKENS: new GraphQLList(GraphQLString), 37 | Name: GraphQLString, 38 | NCName: GraphQLString, 39 | ID: GraphQLID, 40 | IDREF: GraphQLID, 41 | // IDREFS: new GraphQLList(GraphQLID), 42 | ENTITY: GraphQLString, 43 | // ENTITIES: new GraphQLList(GraphQLString), 44 | integer: GraphQLInt, 45 | nonPositiveInteger: GraphQLInt, 46 | negativeInteger: GraphQLInt, 47 | long: GraphQLInt, 48 | int: GraphQLInt, 49 | short: GraphQLInt, 50 | byte: GraphQLInt, 51 | nonNegativeInteger: GraphQLInt, 52 | unsignedLong: GraphQLInt, 53 | unsignedInt: GraphQLInt, 54 | unsignedShort: GraphQLInt, 55 | unsignedByte: GraphQLInt, 56 | positiveInteger: GraphQLInt, 57 | }; 58 | 59 | // Not great 60 | // The most inclusive types must be last 61 | // example: float includes int, so float must be after int 62 | const graphqlScalarMethods = new Map([ 63 | [GraphQLBoolean, { 64 | isOfType: value => typeof value === 'boolean', 65 | coerceValue: Boolean, 66 | parseLiteral: ast => ast.kind === Kind.BOOLEAN ? ast.value : null, 67 | }], 68 | [GraphQLString, { 69 | isOfType: value => typeof value === 'string', 70 | coerce: String, 71 | parseLiteral: ast => ast.kind === Kind.STRING ? ast.value : null, 72 | }], 73 | [GraphQLInt, { 74 | isOfType: value => typeof value === 'number' && Math.round(value) === value, 75 | coerce(value) { 76 | if (value === '') return null; 77 | 78 | const number = Number(value); 79 | 80 | if (Math.abs(number) <= Number.MAX_SAFE_INTEGER) return (number < 0 ? Math.ceil : Math.floor)(number); 81 | 82 | return null; 83 | }, 84 | parseLiteral(ast) { 85 | if (ast.kind === Kind.INT) { 86 | const number = parseInt(ast.value, 10); 87 | 88 | if (Math.abs(number) <= Number.MAX_SAFE_INTEGER) return number; 89 | } 90 | 91 | return null; 92 | }, 93 | }], 94 | [GraphQLFloat, { 95 | isOfType: value => typeof value === 'number', 96 | coerce(value) { 97 | if (value === '') return null; 98 | 99 | const number = Number(value); 100 | 101 | return number === number ? number : null; 102 | }, 103 | parseLiteral: ast => ast.kind === Kind.FLOAT || ast.kind === Kind.INT ? parseFloat(ast.value) : null, 104 | }], 105 | // Must be last because it can be interpreted as either a string or a number 106 | [GraphQLID, { 107 | isOfType: value => typeof value === 'string' || typeof value === 'number', 108 | coerce: String, 109 | parseLiteral: ast => ast.kind === Kind.STRING || ast.kind === Kind.INT ? ast.value : null, 110 | }], 111 | ]); 112 | 113 | module.exports = { 114 | graphqlScalarTypes, 115 | graphqlScalarMethods, 116 | }; 117 | -------------------------------------------------------------------------------- /examples/basic/ontology.ttl: -------------------------------------------------------------------------------- 1 | @prefix owl: . 2 | @prefix rdfs: . 3 | @prefix xsd: . 4 | @prefix : . 5 | 6 | :Company 7 | a owl:Class ; 8 | rdfs:comment "A company to work and play." ; 9 | rdfs:label "Company" ; 10 | rdfs:subClassOf :Thing . 11 | 12 | :Language 13 | a owl:Class ; 14 | rdfs:comment "A system for communication." ; 15 | rdfs:label "Language" ; 16 | rdfs:subClassOf :Thing . 17 | 18 | :Person 19 | a owl:Class ; 20 | rdfs:comment "A human being." ; 21 | rdfs:label "Person" ; 22 | rdfs:subClassOf :Thing . 23 | 24 | :Thing 25 | a owl:Class ; 26 | rdfs:comment "An object, being, or entity." ; 27 | rdfs:label "Thing" ; 28 | rdfs:subClassOf owl:Thing . 29 | 30 | :basicWords 31 | a owl:DatatypeProperty ; 32 | rdfs:comment "A few words in that language." ; 33 | rdfs:domain :Language ; 34 | rdfs:label "Basic words" ; 35 | rdfs:range xsd:string . 36 | 37 | :foundingYear 38 | a owl:DatatypeProperty, owl:FunctionalProperty ; 39 | rdfs:comment "The year the Company was created." ; 40 | rdfs:domain :Company ; 41 | rdfs:label "Founding year" ; 42 | rdfs:range xsd:integer . 43 | 44 | :gender 45 | a owl:DatatypeProperty, owl:FunctionalProperty ; 46 | rdfs:comment "The gender of the Person. False: female, true: male." ; 47 | rdfs:domain :Person ; 48 | rdfs:label "Gender" ; 49 | rdfs:range xsd:boolean . 50 | 51 | :hasCEO 52 | :storageName "CEO" ; 53 | a owl:FunctionalProperty, owl:ObjectProperty ; 54 | rdfs:comment "The Person that is the CEO of the Company." ; 55 | rdfs:domain :Company ; 56 | rdfs:label "Has CEO" ; 57 | rdfs:range :Person . 58 | 59 | :hasEmployees 60 | a owl:ObjectProperty ; 61 | rdfs:comment "The Persons that work for this company" ; 62 | rdfs:domain :Company ; 63 | rdfs:label "Has employees" ; 64 | rdfs:range :Person ; 65 | owl:inverseOf :worksForCompany . 66 | 67 | :isCEOOfCompany 68 | a owl:FunctionalProperty, owl:ObjectProperty ; 69 | rdfs:comment "The Company this Person is the CEO of." ; 70 | rdfs:domain :Person ; 71 | rdfs:label "is CEO of company" ; 72 | rdfs:range :Company ; 73 | owl:inverseOf :hasCEO . 74 | 75 | :localName 76 | a owl:DatatypeProperty, owl:FunctionalProperty ; 77 | rdfs:comment "The Language in that Language." ; 78 | rdfs:domain :Language ; 79 | rdfs:label "Local name" ; 80 | rdfs:range xsd:string . 81 | 82 | :luckyNumber 83 | a owl:DatatypeProperty, owl:FunctionalProperty ; 84 | rdfs:comment "The lucky number of the Person." ; 85 | rdfs:domain :Person ; 86 | rdfs:label "Lucky number" ; 87 | rdfs:range xsd:float, xsd:string . 88 | 89 | :motherTongue 90 | a owl:FunctionalProperty, owl:ObjectProperty ; 91 | rdfs:comment "The first Language the Person has been exposed to from birth." ; 92 | rdfs:domain :Person ; 93 | rdfs:label "Mother tongue" ; 94 | rdfs:range :Language . 95 | 96 | :name 97 | a owl:DatatypeProperty, owl:FunctionalProperty ; 98 | rdfs:comment "A term used for identification." ; 99 | rdfs:domain :Thing ; 100 | rdfs:label "Name" ; 101 | rdfs:range xsd:string . 102 | 103 | :nickname 104 | a owl:DatatypeProperty, owl:FunctionalProperty ; 105 | rdfs:comment "The nickname of the Person." ; 106 | rdfs:domain :Person ; 107 | rdfs:label "Nickname" ; 108 | rdfs:range xsd:string . 109 | 110 | :speaks 111 | :comments "The Languages the Person speaks" ; 112 | a owl:ObjectProperty ; 113 | rdfs:domain :Person ; 114 | rdfs:label "Speaks" ; 115 | rdfs:range :Language . 116 | 117 | :vatIdentificationNumber 118 | a owl:DatatypeProperty, owl:FunctionalProperty ; 119 | rdfs:comment "The identifier used in many countries for value added tax purposes." ; 120 | rdfs:domain :Company ; 121 | rdfs:label "VAT indentification number" ; 122 | rdfs:range xsd:string . 123 | 124 | :worksForCompany 125 | a owl:FunctionalProperty, owl:ObjectProperty ; 126 | rdfs:comment "The Company this Person works for." ; 127 | rdfs:domain :Person ; 128 | rdfs:label "Works for company" ; 129 | rdfs:range :Company ; 130 | owl:inverseOf :hasEmployees . 131 | -------------------------------------------------------------------------------- /examples/basic/data.js: -------------------------------------------------------------------------------- 1 | const assignTypeAndId = type => x => Object.assign({ type, id: x.name }, x); 2 | 3 | const languages = [ 4 | { 5 | name: 'English', 6 | localName: 'English', 7 | basicWords: [ 8 | 'Hello', 9 | 'I love you', 10 | 'The sky is the limit.', 11 | ], 12 | }, 13 | { 14 | name: 'French', 15 | localName: 'Français', 16 | basicWords: [ 17 | 'Bonjour', 18 | 'Je t\'aime', 19 | 'Et voilà le travail!', 20 | ], 21 | }, 22 | { 23 | name: 'German', 24 | localName: 'Deutsch', 25 | basicWords: [ 26 | 'Hallo', 27 | 'Ich liebe dich', 28 | 'Ich bin ein berliner.', 29 | ], 30 | }, 31 | ].map(assignTypeAndId('Language')); 32 | 33 | const persons = [ 34 | { 35 | name: 'Gaëtan Barral', 36 | gender: true, 37 | worksForCompany: 'Edge Factory', 38 | motherTongue: 'French', 39 | nickname: 'Goët', 40 | luckyNumber: 'pi', 41 | speaks: [ 42 | 'French', 43 | 'English', 44 | 'German', 45 | ], 46 | }, 47 | { 48 | name: 'Gregor MacBurgers', 49 | gender: true, 50 | worksForCompany: 'Greasy burgers', 51 | luckyNumber: true, // should raise ex 52 | }, 53 | { 54 | name: 'Ahre Zo', 55 | gender: false, 56 | worksForCompany: 'Human Space Agency', 57 | luckyNumber: 6.626e-34, 58 | }, 59 | { 60 | name: 'Heinrich Müller', 61 | gender: true, 62 | worksForCompany: 'Four wheels', 63 | luckyNumber: 'phi', 64 | }, 65 | { 66 | name: 'Marie Birkeland', 67 | gender: false, 68 | worksForCompany: 'Greasy burgers', 69 | }, 70 | { 71 | name: 'Barbara T. Ashby', 72 | gender: false, 73 | worksForCompany: 'Greasy burgers', 74 | }, 75 | { 76 | name: 'Cai Jen', 77 | gender: true, 78 | worksForCompany: 'Four wheels', 79 | }, 80 | { 81 | name: 'Chibueze Eberechukwu', 82 | gender: true, 83 | worksForCompany: 'Human Space Agency', 84 | }, 85 | { 86 | name: 'Aðalbjörg Sigurvaldadóttir', 87 | gender: false, 88 | worksForCompany: 'Human Space Agency', 89 | }, 90 | { 91 | name: 'Søren Mikaelsen', 92 | gender: true, 93 | worksForCompany: 'Edge Factory', 94 | }, 95 | { 96 | name: 'Rodrigo Castro Barbosa', 97 | gender: true, 98 | worksForCompany: 'Human Space Agency', 99 | }, 100 | { 101 | name: 'Oliver Bårdsen', 102 | gender: true, 103 | worksForCompany: 'Greasy burgers', 104 | }, 105 | { 106 | name: 'Kosisochukwu Obiora', 107 | gender: true, 108 | worksForCompany: 'Edge Factory', 109 | }, 110 | { 111 | name: 'Zakir Akhtakhanov', 112 | gender: true, 113 | worksForCompany: 'Human Space Agency', 114 | }, 115 | { 116 | name: 'Александр Сорокин', 117 | gender: true, 118 | worksForCompany: 'Greasy burgers', 119 | }, 120 | { 121 | name: '尹晉唯', 122 | gender: false, 123 | worksForCompany: 'Edge Factory', 124 | }, 125 | { 126 | name: 'Frederikke Mikaelsen', 127 | gender: false, 128 | worksForCompany: 'Human Space Agency', 129 | }, 130 | { 131 | name: 'Гузель Аксакова', 132 | gender: false, 133 | worksForCompany: 'Human Space Agency', 134 | }, 135 | { 136 | name: 'Adaldrida Brandagamba', 137 | gender: false, 138 | worksForCompany: 'Human Space Agency', 139 | }, 140 | { 141 | name: 'May Donaldson', 142 | gender: false, 143 | }, 144 | ].map(assignTypeAndId('Person')); 145 | 146 | const companies = [ 147 | { 148 | name: 'Edge Factory', 149 | foundingYear: 2015, 150 | hasCEO: 'Gaëtan Barral', 151 | vat: 'EF0000', 152 | }, 153 | { 154 | name: 'Human Space Agency', 155 | foundingYear: 2215, 156 | hasCEO: 'Ahre Zo', 157 | vat: 'HSA000', 158 | }, 159 | { 160 | name: 'Greasy burgers', 161 | foundingYear: 1998, 162 | hasCEO: 'Gregor MacBurgers', 163 | vat: 'GB0000', 164 | }, 165 | { 166 | name: 'Four wheels', 167 | foundingYear: 1960, 168 | hasCEO: 'Heinrich Müller', 169 | vat: 'FW0000', 170 | }, 171 | ].map(assignTypeAndId('Company')); 172 | 173 | module.exports = [ 174 | ...languages, 175 | ...persons, 176 | ...companies, 177 | ]; 178 | -------------------------------------------------------------------------------- /ontologies/rdfs.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix rdfs: . 3 | @prefix owl: . 4 | @prefix dc: . 5 | 6 | a owl:Ontology ; 7 | dc:title "The RDF Schema vocabulary (RDFS)" . 8 | 9 | rdfs:Resource a rdfs:Class ; 10 | rdfs:isDefinedBy ; 11 | rdfs:label "Resource" ; 12 | rdfs:comment "The class resource, everything." . 13 | 14 | rdfs:Class a rdfs:Class ; 15 | rdfs:isDefinedBy ; 16 | rdfs:label "Class" ; 17 | rdfs:comment "The class of classes." ; 18 | rdfs:subClassOf rdfs:Resource . 19 | 20 | rdfs:subClassOf a rdf:Property ; 21 | rdfs:isDefinedBy ; 22 | rdfs:label "subClassOf" ; 23 | rdfs:comment "The subject is a subclass of a class." ; 24 | rdfs:range rdfs:Class ; 25 | rdfs:domain rdfs:Class . 26 | 27 | rdfs:subPropertyOf a rdf:Property ; 28 | rdfs:isDefinedBy ; 29 | rdfs:label "subPropertyOf" ; 30 | rdfs:comment "The subject is a subproperty of a property." ; 31 | rdfs:range rdf:Property ; 32 | rdfs:domain rdf:Property . 33 | 34 | rdfs:comment a rdf:Property ; 35 | rdfs:isDefinedBy ; 36 | rdfs:label "comment" ; 37 | rdfs:comment "A description of the subject resource." ; 38 | rdfs:domain rdfs:Resource ; 39 | rdfs:range rdfs:Literal . 40 | 41 | rdfs:label a rdf:Property ; 42 | rdfs:isDefinedBy ; 43 | rdfs:label "label" ; 44 | rdfs:comment "A human-readable name for the subject." ; 45 | rdfs:domain rdfs:Resource ; 46 | rdfs:range rdfs:Literal . 47 | 48 | rdfs:domain a rdf:Property ; 49 | rdfs:isDefinedBy ; 50 | rdfs:label "domain" ; 51 | rdfs:comment "A domain of the subject property." ; 52 | rdfs:range rdfs:Class ; 53 | rdfs:domain rdf:Property . 54 | 55 | rdfs:range a rdf:Property ; 56 | rdfs:isDefinedBy ; 57 | rdfs:label "range" ; 58 | rdfs:comment "A range of the subject property." ; 59 | rdfs:range rdfs:Class ; 60 | rdfs:domain rdf:Property . 61 | 62 | rdfs:seeAlso a rdf:Property ; 63 | rdfs:isDefinedBy ; 64 | rdfs:label "seeAlso" ; 65 | rdfs:comment "Further information about the subject resource." ; 66 | rdfs:range rdfs:Resource ; 67 | rdfs:domain rdfs:Resource . 68 | 69 | rdfs:isDefinedBy a rdf:Property ; 70 | rdfs:isDefinedBy ; 71 | rdfs:subPropertyOf rdfs:seeAlso ; 72 | rdfs:label "isDefinedBy" ; 73 | rdfs:comment "The defininition of the subject resource." ; 74 | rdfs:range rdfs:Resource ; 75 | rdfs:domain rdfs:Resource . 76 | 77 | rdfs:Literal a rdfs:Class ; 78 | rdfs:isDefinedBy ; 79 | rdfs:label "Literal" ; 80 | rdfs:comment "The class of literal values, eg. textual strings and integers." ; 81 | rdfs:subClassOf rdfs:Resource . 82 | 83 | rdfs:Container a rdfs:Class ; 84 | rdfs:isDefinedBy ; 85 | rdfs:label "Container" ; 86 | rdfs:subClassOf rdfs:Resource ; 87 | rdfs:comment "The class of RDF containers." . 88 | 89 | rdfs:ContainerMembershipProperty a rdfs:Class ; 90 | rdfs:isDefinedBy ; 91 | rdfs:label "ContainerMembershipProperty" ; 92 | rdfs:comment """The class of container membership properties, rdf:_1, rdf:_2, ..., 93 | all of which are sub-properties of 'member'.""" ; 94 | rdfs:subClassOf rdf:Property . 95 | 96 | rdfs:member a rdf:Property ; 97 | rdfs:isDefinedBy ; 98 | rdfs:label "member" ; 99 | rdfs:comment "A member of the subject resource." ; 100 | rdfs:domain rdfs:Resource ; 101 | rdfs:range rdfs:Resource . 102 | 103 | rdfs:Datatype a rdfs:Class ; 104 | rdfs:isDefinedBy ; 105 | rdfs:label "Datatype" ; 106 | rdfs:comment "The class of RDF datatypes." ; 107 | rdfs:subClassOf rdfs:Class . 108 | 109 | rdfs:seeAlso . 110 | -------------------------------------------------------------------------------- /src/graphql/getGraphqlObjectResolver.js: -------------------------------------------------------------------------------- 1 | const { owlInverseOf, _owlInverseOf, rdfsDomain, _rdfsSubClassOf } = require('../constants'); 2 | const isNil = require('../utils/isNil'); 3 | const castArrayShape = require('../utils/castArrayShape'); 4 | const { walkmap } = require('../graph/traversal'); 5 | const isGraphqlList = require('./isGraphqlList'); 6 | const requireGraphqlRelay = require('../requireGraphqlRelay'); 7 | 8 | function getGraphqlObjectResolver(g, iri, ranges) { 9 | const isList = isGraphqlList(g, iri); 10 | 11 | let inverseOfMap; 12 | 13 | // If inverseProperties exists, we can use them to retrieve missing remote data 14 | if (!g[iri].shouldNeverUseInverseOf && (g[iri][owlInverseOf] || g[iri][_owlInverseOf])) { 15 | const extendedRanges = new Set(); 16 | const inverseProperties = new Set(); 17 | 18 | if (g[iri][owlInverseOf]) g[iri][owlInverseOf].forEach(inverseProperties.add, inverseProperties); 19 | if (g[iri][_owlInverseOf]) g[iri][_owlInverseOf].forEach(inverseProperties.add, inverseProperties); 20 | 21 | // We want to look for the full extent of the currentProperty's ranges, i.e. include their subClasses 22 | ranges.forEach(rangeIri => walkmap(g, rangeIri, _rdfsSubClassOf, extendedRanges)); 23 | 24 | // For each inverseProperty we map the corresponding classes 25 | // That are both of the currentProperty's extended range and the inverseProperty's extended domain 26 | inverseOfMap = new Map(); 27 | 28 | inverseProperties.forEach(propertyIri => { 29 | if (!g[propertyIri][rdfsDomain]) return; 30 | 31 | const admitingRanges = []; 32 | const extendedDomains = new Set(); 33 | 34 | // Find the extended domain of the inverseProperty 35 | g[propertyIri][rdfsDomain].forEach(domainIri => walkmap(g, domainIri, _rdfsSubClassOf, extendedDomains)); 36 | 37 | // And among those domain, keep only those accepted as a range of the currentProperty 38 | extendedDomains.forEach(domainIri => { 39 | if (extendedRanges.has(domainIri)) admitingRanges.push(domainIri); 40 | }); 41 | 42 | inverseOfMap.set(propertyIri, admitingRanges); 43 | }); 44 | } 45 | 46 | const hasNoInverseOf = !(inverseOfMap && inverseOfMap.size); 47 | const resolveNothing = () => isList ? [] : null; 48 | const resolveResource = isList ? g.resolvers.resolveResources : g.resolvers.resolveResource; 49 | 50 | // A resolver for inverseOf properties 51 | const inverseOfResolver = (source, args, context, info) => { 52 | if (hasNoInverseOf) return resolveNothing(); 53 | 54 | return Promise.resolve(g.resolvers.resolveSourceId(source, context, info)) 55 | .then(sourceId => { 56 | 57 | const promises = []; 58 | 59 | inverseOfMap.forEach((admitingRanges, propertyIri) => { 60 | promises.push(g.resolvers.resolveResourcesByPredicate(admitingRanges, propertyIri, sourceId, context, info)); 61 | }); 62 | 63 | return Promise.all(promises) 64 | .then(results => { 65 | const finalResult = results.reduce((a, b) => a.concat(b), []); 66 | 67 | return isList ? finalResult : finalResult[0]; 68 | }); 69 | }); 70 | }; 71 | 72 | // XXX: put outside of scope to avoid re-allocation ? 73 | // The actual resolve function 74 | const resolver = (source, args, context, info) => { 75 | if (g[iri].shouldAlwaysUseInverseOf) return inverseOfResolver(source, args, context, info); 76 | 77 | return Promise.resolve(g.resolvers.resolveSourcePropertyValue(source, iri, context, info)) 78 | .then(ref => { 79 | // A reference to data was resolved, we resolve the underlying resources 80 | // NOTE: this does not aggregate both direct and inverse data 81 | if (!isNil(ref)) return resolveResource(castArrayShape(ref, isList), context, info); 82 | 83 | // No reference to data was resolved, maybe the data is on an inverse Property 84 | if (!g[iri].shouldNeverUseInverseOf) return inverseOfResolver(source, args, context, info); 85 | 86 | // Give up 87 | return resolveNothing(); 88 | }); 89 | }; 90 | 91 | if (g.config.relay && g[iri].isRelayConnection) { 92 | const { connectionFromArray, connectionFromPromisedArray } = requireGraphqlRelay(); 93 | 94 | return (source, args, context, info) => { 95 | const results = resolver(source, args, context, info); 96 | 97 | return (Array.isArray(results) ? connectionFromArray : connectionFromPromisedArray)(results, args); 98 | }; 99 | } 100 | 101 | return resolver; 102 | } 103 | 104 | module.exports = getGraphqlObjectResolver; 105 | -------------------------------------------------------------------------------- /ontologies/rdf.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix rdfs: . 3 | @prefix owl: . 4 | @prefix dc: . 5 | 6 | a owl:Ontology ; 7 | dc:title "The RDF Concepts Vocabulary (RDF)" ; 8 | dc:description "This is the RDF Schema for the RDF vocabulary terms in the RDF Namespace, defined in RDF 1.1 Concepts." . 9 | 10 | rdf:HTML a rdfs:Datatype ; 11 | rdfs:subClassOf rdfs:Literal ; 12 | rdfs:isDefinedBy ; 13 | rdfs:seeAlso ; 14 | rdfs:label "HTML" ; 15 | rdfs:comment "The datatype of RDF literals storing fragments of HTML content" . 16 | 17 | rdf:langString a rdfs:Datatype ; 18 | rdfs:subClassOf rdfs:Literal ; 19 | rdfs:isDefinedBy ; 20 | rdfs:seeAlso ; 21 | rdfs:label "langString" ; 22 | rdfs:comment "The datatype of language-tagged string values" . 23 | 24 | rdf:PlainLiteral a rdfs:Datatype ; 25 | rdfs:isDefinedBy ; 26 | rdfs:subClassOf rdfs:Literal ; 27 | rdfs:seeAlso ; 28 | rdfs:label "PlainLiteral" ; 29 | rdfs:comment "The class of plain (i.e. untyped) literal values, as used in RIF and OWL 2" . 30 | 31 | rdf:type a rdf:Property ; 32 | rdfs:isDefinedBy ; 33 | rdfs:label "type" ; 34 | rdfs:comment "The subject is an instance of a class." ; 35 | rdfs:range rdfs:Class ; 36 | rdfs:domain rdfs:Resource . 37 | 38 | rdf:Property a rdfs:Class ; 39 | rdfs:isDefinedBy ; 40 | rdfs:label "Property" ; 41 | rdfs:comment "The class of RDF properties." ; 42 | rdfs:subClassOf rdfs:Resource . 43 | 44 | rdf:Statement a rdfs:Class ; 45 | rdfs:isDefinedBy ; 46 | rdfs:label "Statement" ; 47 | rdfs:subClassOf rdfs:Resource ; 48 | rdfs:comment "The class of RDF statements." . 49 | 50 | rdf:subject a rdf:Property ; 51 | rdfs:isDefinedBy ; 52 | rdfs:label "subject" ; 53 | rdfs:comment "The subject of the subject RDF statement." ; 54 | rdfs:domain rdf:Statement ; 55 | rdfs:range rdfs:Resource . 56 | 57 | rdf:predicate a rdf:Property ; 58 | rdfs:isDefinedBy ; 59 | rdfs:label "predicate" ; 60 | rdfs:comment "The predicate of the subject RDF statement." ; 61 | rdfs:domain rdf:Statement ; 62 | rdfs:range rdfs:Resource . 63 | 64 | rdf:object a rdf:Property ; 65 | rdfs:isDefinedBy ; 66 | rdfs:label "object" ; 67 | rdfs:comment "The object of the subject RDF statement." ; 68 | rdfs:domain rdf:Statement ; 69 | rdfs:range rdfs:Resource . 70 | 71 | rdf:Bag a rdfs:Class ; 72 | rdfs:isDefinedBy ; 73 | rdfs:label "Bag" ; 74 | rdfs:comment "The class of unordered containers." ; 75 | rdfs:subClassOf rdfs:Container . 76 | 77 | rdf:Seq a rdfs:Class ; 78 | rdfs:isDefinedBy ; 79 | rdfs:label "Seq" ; 80 | rdfs:comment "The class of ordered containers." ; 81 | rdfs:subClassOf rdfs:Container . 82 | 83 | rdf:Alt a rdfs:Class ; 84 | rdfs:isDefinedBy ; 85 | rdfs:label "Alt" ; 86 | rdfs:comment "The class of containers of alternatives." ; 87 | rdfs:subClassOf rdfs:Container . 88 | 89 | rdf:value a rdf:Property ; 90 | rdfs:isDefinedBy ; 91 | rdfs:label "value" ; 92 | rdfs:comment "Idiomatic property used for structured values." ; 93 | rdfs:domain rdfs:Resource ; 94 | rdfs:range rdfs:Resource . 95 | 96 | rdf:List a rdfs:Class ; 97 | rdfs:isDefinedBy ; 98 | rdfs:label "List" ; 99 | rdfs:comment "The class of RDF Lists." ; 100 | rdfs:subClassOf rdfs:Resource . 101 | 102 | rdf:nil a rdf:List ; 103 | rdfs:isDefinedBy ; 104 | rdfs:label "nil" ; 105 | rdfs:comment "The empty list, with no items in it. If the rest of a list is nil then the list has no more items in it." . 106 | 107 | rdf:first a rdf:Property ; 108 | rdfs:isDefinedBy ; 109 | rdfs:label "first" ; 110 | rdfs:comment "The first item in the subject RDF list." ; 111 | rdfs:domain rdf:List ; 112 | rdfs:range rdfs:Resource . 113 | 114 | rdf:rest a rdf:Property ; 115 | rdfs:isDefinedBy ; 116 | rdfs:label "rest" ; 117 | rdfs:comment "The rest of the subject RDF list after the first item." ; 118 | rdfs:domain rdf:List ; 119 | rdfs:range rdf:List . 120 | 121 | rdf:XMLLiteral a rdfs:Datatype ; 122 | rdfs:subClassOf rdfs:Literal ; 123 | rdfs:isDefinedBy ; 124 | rdfs:label "XMLLiteral" ; 125 | rdfs:comment "The datatype of XML literal values." . 126 | -------------------------------------------------------------------------------- /src/SemanticGraph.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { readFileSync } = require('fs'); 3 | const createRdfParser = require('n3').Parser; 4 | const { 5 | rdfIri, rdfsIri, owlIri, rdfsResource, 6 | rdfType, rdfsLabel, rdfsComment, rdfsDomain, rdfsRange, rdfsSubClassOf, rdfsSubPropertyOf, owlInverseOf, 7 | } = require('./constants'); 8 | const invariant = require('./utils/invariant'); 9 | const isIri = require('./utils/isIri'); 10 | const requireGraphqlRelay = require('./requireGraphqlRelay'); 11 | const getGraphqlObjectType = require('./graphql/getGraphqlObjectType'); 12 | const getGraphqlInterfaceType = require('./graphql/getGraphqlInterfaceType'); 13 | const getGraphqlTypeResolver = require('./graphql/getGraphqlTypeResolver'); 14 | const getRelayConnectionDefinitions = require('./graphql/getRelayConnectionDefinitions'); 15 | 16 | const utf8 = 'utf-8'; 17 | const ttlParser = createRdfParser(); 18 | const parseFileAndIndex = (g, l) => ttlParser.parse(readFileSync(path.join(__dirname, l), utf8)).forEach(t => indexTriple(g, t)); 19 | 20 | const baseGraph = { nTriples: 0 }; 21 | const basePrefixes = { 22 | rdf: rdfIri, 23 | rdfs: rdfsIri, 24 | owl: owlIri, 25 | }; 26 | 27 | // Only those predicates are useful for the lib, thus stored in the graph 28 | const workingPredicates = [ 29 | rdfType, 30 | rdfsLabel, 31 | rdfsComment, 32 | rdfsDomain, 33 | rdfsRange, 34 | rdfsSubClassOf, 35 | rdfsSubPropertyOf, 36 | owlInverseOf, 37 | ]; 38 | 39 | parseFileAndIndex(baseGraph, '../ontologies/rdf.ttl'); 40 | parseFileAndIndex(baseGraph, '../ontologies/rdfs.ttl'); 41 | parseFileAndIndex(baseGraph, '../ontologies/owl.ttl'); 42 | 43 | class SemanticGraph { 44 | 45 | constructor(resolvers, config = {}) { 46 | invariant(resolvers && typeof resolvers === 'object', 'Expected first arg to be an object'); 47 | invariant(config && typeof config === 'object', 'Expected second arg to be an object'); 48 | validateResolvers(resolvers); 49 | 50 | Object.assign(this, baseGraph, { config, resolvers }); 51 | 52 | this.config.prefixes = Object.assign({}, basePrefixes, this.config.prefixes); 53 | 54 | if (config.relay) { 55 | const { fromGlobalId, nodeDefinitions } = requireGraphqlRelay(); 56 | const resolveNode = (globalId, context, info) => this.resolvers.resolveResource(fromGlobalId(globalId).id, context, info); 57 | const resolveType = getGraphqlTypeResolver(this, rdfsResource); 58 | 59 | // Add this.nodeInterface and this.nodeField 60 | Object.assign(this, nodeDefinitions(resolveNode, resolveType)); 61 | } 62 | 63 | this.addTriple = t => indexTriple(this, t); 64 | this.parse = (d, o) => createRdfParser(o).parse(d).forEach(this.addTriple); 65 | this.parseFile = (l, o, e = utf8) => this.parse(readFileSync(l, e), o); 66 | this.getObjectType = iri => getGraphqlObjectType(this, iri); 67 | this.getInterfaceType = iri => getGraphqlInterfaceType(this, iri); 68 | this.getEdgeType = iri => getRelayConnectionDefinitions(this, iri).edgeType; 69 | this.getConnectionType = iri => getRelayConnectionDefinitions(this, iri).connectionType; 70 | this.toString = () => `[SemanticGraph: ${this.nTriples} triples]`; 71 | } 72 | 73 | addFieldOnObjectType(classIri, fieldName, graphqlFieldConfig) { 74 | if (!this[classIri]) throw new Error(`Class not found: ${classIri}`); 75 | 76 | const iri = `http://CUSTOM_FIELD_${Math.random().toString().slice(2)}#${fieldName}`; 77 | 78 | this[iri] = { graphqlFieldConfig }; 79 | 80 | indexTriple(this, { 81 | subject: iri, 82 | predicate: rdfsDomain, 83 | object: classIri, 84 | }); 85 | 86 | return iri; // If the user wants to extend it later (why not) 87 | } 88 | 89 | extendFieldOnObjectType(classIri, propertyIri, graphqlFieldConfigExtension) { 90 | const x = this[classIri]; 91 | 92 | if (!x) throw new Error(`Class not found: ${classIri}`); 93 | 94 | if (!x.graphqlFieldConfigExtensionMap) x.graphqlFieldConfigExtensionMap = {}; 95 | 96 | x.graphqlFieldConfigExtensionMap[propertyIri] = graphqlFieldConfigExtension; 97 | } 98 | 99 | } 100 | 101 | /* Private methods */ 102 | 103 | function indexTriple(g, { subject, predicate, object }) { 104 | if (!workingPredicates.includes(predicate)) return; 105 | if (!(isIri(subject) && isIri(predicate)) || g[subject] && g[subject][predicate] && g[subject][predicate].includes(object)) return; 106 | 107 | upsert(g, subject, predicate, object); 108 | 109 | g.nTriples++; 110 | 111 | if (isIri(object)) upsert(g, object, `_${predicate}`, subject); 112 | } 113 | 114 | function upsert(theGuy, whoDid, what, kevinOffACliff) { 115 | const theGuyWhoDid = theGuy[whoDid]; 116 | 117 | /*do you know*/theGuyWhoDid ? 118 | theGuyWhoDid[what] ? 119 | theGuyWhoDid[what].push(kevinOffACliff) : 120 | theGuyWhoDid[what] = [kevinOffACliff] : // ?!!??! 121 | theGuy[whoDid] = { [what]: [kevinOffACliff] }; 122 | } 123 | 124 | const resolverNames = [ 125 | 'resolveSourceId', 126 | 'resolveSourceTypes', 127 | 'resolveSourcePropertyValue', 128 | 'resolveResource', 129 | 'resolveResources', 130 | 'resolveResourcesByPredicate', 131 | ]; 132 | 133 | function validateResolvers(resolvers) { 134 | resolverNames.forEach(key => { 135 | const type = typeof resolvers[key]; 136 | 137 | invariant(type === 'function', `Resolver validation: expected "${key}" to be a function, got ${type} instead.`); 138 | }); 139 | 140 | return resolvers; 141 | } 142 | 143 | module.exports = SemanticGraph; 144 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | const { assert } = require('chai'); 3 | const { GraphQLObjectType, GraphQLInterfaceType } = require('graphql'); 4 | const mockResolvers = require('./utils/mockResolvers'); 5 | const commonTurtlePrefixes = require('./utils/commonTurtlePrefixes'); 6 | const castArrayShape = require('../src/utils/castArrayShape'); 7 | const isNil = require('../src/utils/isNil'); 8 | const capitalize = require('../src/utils/capitalize'); 9 | const { walkmap, walklook } = require('../src/graph/traversal'); 10 | const { rdfsClass, rdfType, _rdfsDomain } = require('../src/constants'); 11 | const ArrayKeyedMap = require('../src/ArrayKeyedMap'); 12 | const SemanticGraph = require('..'); 13 | 14 | // TODO: split this file 15 | 16 | // NOTE: getIriLocalName and isIri will be imported from an external lib someday 17 | describe('Utils', () => { 18 | 19 | it('castArrayShape', () => { 20 | assert.deepEqual(castArrayShape([0, 1, 2], true), [0, 1, 2]); 21 | assert.deepEqual(castArrayShape([0, 1, 2], false), 0); 22 | assert.deepEqual(castArrayShape(0, true), [0]); 23 | assert.deepEqual(castArrayShape(0, false), 0); 24 | }); 25 | 26 | it('isNil', () => { 27 | assert.isTrue(isNil(null)); 28 | assert.isTrue(isNil(undefined)); 29 | assert.isTrue(isNil([])); 30 | 31 | assert.isFalse(isNil('')); 32 | assert.isFalse(isNil(0)); 33 | assert.isFalse(isNil([0])); 34 | }); 35 | 36 | it('capitalize', () => { 37 | assert.strictEqual(capitalize(''), ''); 38 | assert.strictEqual(capitalize('abc'), 'Abc'); 39 | assert.strictEqual(capitalize('012'), '012'); 40 | }); 41 | }); 42 | 43 | describe('Graph traversal', () => { 44 | 45 | const graph = { 46 | a: { 47 | x: ['b', 'c'], 48 | y: ['d', 'e'], 49 | }, 50 | b: { 51 | x: ['a', 'c', 'd'], 52 | z: ['a', 'f'], 53 | }, 54 | c: { 55 | x: ['c'], 56 | }, 57 | d: { 58 | y: ['a', 'b'], 59 | z: ['c'], 60 | }, 61 | e: { 62 | z: ['c', 'd', 'g'], 63 | }, 64 | f: { 65 | x: ['g'], 66 | }, 67 | g: { 68 | y: ['a', 'f'], 69 | }, 70 | }; 71 | 72 | it('walkmap', () => { 73 | // Walmap should traverse the graph in a depth-first manner 74 | // using the same exit edge, until all vertices are visited 75 | assert.deepEqual([...walkmap(graph, 'a', 'x')], ['a', 'b', 'c', 'd']); 76 | assert.deepEqual([...walkmap(graph, 'b', 'x')], ['b', 'a', 'c', 'd']); 77 | assert.deepEqual([...walkmap(graph, 'a', 'y')], ['a', 'd', 'b', 'e']); 78 | assert.deepEqual([...walkmap(graph, 'b', 'y')], ['b']); 79 | assert.deepEqual([...walkmap(graph, 'b', 'z')], ['b', 'a', 'f']); 80 | }); 81 | 82 | it('walklook', () => { 83 | // Walklook should traverse the graph in a breath-first manner 84 | // Stopping once a fringe has resolved a result 85 | assert.deepEqual([...walklook(graph, 'a', 'x', 'y')], ['d', 'e']); 86 | assert.deepEqual([...walklook(graph, 'a', 'x', 'z')], ['a', 'f']); 87 | assert.deepEqual([...walklook(graph, 'g', 'y', 'x')], ['b', 'c', 'g']); // BFS with stop condition 88 | assert.deepEqual([...walklook(graph, 'g', 'x', 'z')], []); 89 | assert.deepEqual([...walklook(graph, 'c', 'x', 'z')], []); 90 | }); 91 | }); 92 | 93 | describe('ArrayKeyedMap', () => { 94 | 95 | it('get/set', () => { 96 | const akm = new ArrayKeyedMap(); 97 | 98 | assert.doesNotThrow(() => akm.set(['a', 'b', 'c'], 'foo')); 99 | assert.doesNotThrow(() => akm.get(['d'])); 100 | assert.strictEqual(akm.get(['a', 'b', 'c']), 'foo'); 101 | assert.strictEqual(akm.get(['a', 'c', 'b']), 'foo'); 102 | assert.strictEqual(akm.get(['b', 'c', 'a']), 'foo'); 103 | assert.strictEqual(akm.get(['b', 'a', 'c']), 'foo'); 104 | assert.strictEqual(akm.get(['c', 'a', 'b']), 'foo'); 105 | assert.strictEqual(akm.get(['c', 'b', 'a']), 'foo'); 106 | }); 107 | 108 | it('has', () => { 109 | const akm = new ArrayKeyedMap(); 110 | 111 | akm.set(['a', 'b', 'c'], 'foo'); 112 | 113 | assert.isTrue(akm.has(['a', 'b', 'c'])); 114 | assert.isTrue(akm.has(['a', 'c', 'b'])); 115 | assert.isTrue(akm.has(['b', 'c', 'a'])); 116 | assert.isTrue(akm.has(['b', 'a', 'c'])); 117 | assert.isTrue(akm.has(['c', 'a', 'b'])); 118 | assert.isTrue(akm.has(['c', 'b', 'a'])); 119 | 120 | assert.isFalse(akm.has([])); 121 | assert.isFalse(akm.has(['a'])); 122 | assert.isFalse(akm.has(['a', 'b'])); 123 | }); 124 | }); 125 | 126 | describe('SemanticGraph', () => { 127 | 128 | it('throws when passed incorrect arguments', () => { 129 | assert.throws(() => new SemanticGraph()); 130 | assert.throws(() => new SemanticGraph('foo')); 131 | assert.throws(() => new SemanticGraph(mockResolvers, 'foo')); 132 | }); 133 | 134 | it('throws when passed invalid resolvers', () => { 135 | assert.throws(() => new SemanticGraph({})); 136 | assert.throws(() => new SemanticGraph(Object.assign({}, mockResolvers, { resolveSourceId: null }))); 137 | }); 138 | 139 | it('does not throw when arguments are correct', () => { 140 | assert.doesNotThrow(() => new SemanticGraph(mockResolvers)); 141 | assert.doesNotThrow(() => new SemanticGraph(mockResolvers, { foo: 'bar' })); 142 | }); 143 | 144 | it('includes the base graph in instances', () => { 145 | const _ = new SemanticGraph(mockResolvers); 146 | 147 | assert.isObject(_[rdfsClass]); 148 | assert.isArray(_[rdfsClass][rdfType]); 149 | assert.include(_[rdfsClass][rdfType], rdfsClass); 150 | }); 151 | 152 | it('exposes API methods', () => { 153 | const _ = new SemanticGraph(mockResolvers); 154 | 155 | assert.isFunction(_.addTriple); 156 | assert.isFunction(_.parse); 157 | assert.isFunction(_.parseFile); 158 | assert.isFunction(_.getObjectType); 159 | assert.isFunction(_.getInterfaceType); 160 | assert.isFunction(_.getEdgeType); 161 | assert.isFunction(_.getConnectionType); 162 | assert.isFunction(_.addFieldOnObjectType); 163 | assert.isFunction(_.extendFieldOnObjectType); 164 | assert.isFunction(_.toString); 165 | }); 166 | }); 167 | 168 | const fooIri = 'http://foo.com/'; 169 | const subject = `${fooIri}Subject`; 170 | const predicate = rdfType; 171 | const _predicate = `_${predicate}`; 172 | const object = `${fooIri}Object`; 173 | const fooPerson = `${fooIri}Person`; 174 | const fooName = `${fooIri}name`; 175 | const fooAge = `${fooIri}age`; 176 | const fooGender = `${fooIri}gender`; 177 | const personOntology = ` 178 | ${commonTurtlePrefixes} 179 | 180 | :Person a rdfs:Class ; 181 | rdfs:label "Person" ; 182 | rdfs:comment "A human being" . 183 | 184 | :name a rdf:Property ; 185 | rdfs:label "Name" ; 186 | rdfs:comment "The name of the Person" ; 187 | rdfs:domain :Person ; 188 | rdfs:range xsd:string . 189 | 190 | :age a rdf:Property ; 191 | rdfs:label "Age" ; 192 | rdfs:comment "The age of the Person" ; 193 | rdfs:domain :Person ; 194 | rdfs:range xsd:integer . 195 | 196 | :gender a rdf:Property ; 197 | rdfs:label "Gender" ; 198 | rdfs:comment "The gender of the Person. True for male, false or female" ; 199 | rdfs:domain :Person ; 200 | rdfs:range xsd:boolean . 201 | `; 202 | 203 | describe('Ontology comprehension', () => { 204 | 205 | it('adds a triple to the graph', () => { 206 | const _ = new SemanticGraph(mockResolvers); 207 | 208 | assert.doesNotThrow(() => _.addTriple({ subject, predicate, object })); 209 | 210 | assert.isObject(_[subject]); 211 | assert.isArray(_[subject][predicate]); 212 | assert.sameMembers(_[subject][predicate], [object]); 213 | 214 | assert.isObject(_[object]); 215 | assert.isArray(_[object][_predicate]); 216 | assert.sameMembers(_[object][_predicate], [subject]); 217 | 218 | _.addTriple({ subject, predicate, object: 'foo' }); 219 | 220 | assert.isObject(_[subject]); 221 | assert.isArray(_[subject][predicate]); 222 | assert.sameMembers(_[subject][predicate], [object, 'foo']); 223 | 224 | assert.isNotObject(_.foo); 225 | }); 226 | 227 | it('does not add the same triple twice', () => { 228 | const _ = new SemanticGraph(mockResolvers); 229 | 230 | _.addTriple({ subject, predicate, object }); 231 | _.addTriple({ subject, predicate, object }); 232 | 233 | assert.isObject(_[subject]); 234 | assert.isArray(_[subject][predicate]); 235 | assert.lengthOf(_[subject][predicate], 1); 236 | assert.sameMembers(_[subject][predicate], [object]); 237 | }); 238 | 239 | it('does not add malformed triples', () => { 240 | const _ = new SemanticGraph(mockResolvers); 241 | 242 | _.addTriple({ subject: 'foo', predicate, object }); 243 | 244 | assert.isNotObject(_.foo); 245 | 246 | _.addTriple({ subject, predicate: 'foo', object }); 247 | 248 | assert.isNotObject(_[subject]); 249 | 250 | _.addTriple({ subject, predicate, object }); 251 | _.addTriple({ subject, predicate: 'foo', object }); 252 | 253 | assert.isObject(_[subject]); 254 | assert.isNotArray(_[subject].foo); 255 | }); 256 | 257 | it('Parses turtle', () => { 258 | const _ = new SemanticGraph(mockResolvers); 259 | 260 | assert.doesNotThrow(() => _.parse(personOntology)); 261 | assert.isObject(_[fooPerson]); 262 | assert.isObject(_[fooName]); 263 | assert.isObject(_[fooAge]); 264 | assert.isObject(_[fooGender]); 265 | assert.sameMembers(_[fooPerson][_rdfsDomain], [fooName, fooAge, fooGender]); 266 | }); 267 | 268 | }); 269 | 270 | describe('GraphQL objects generation', () => { 271 | 272 | it('generates GraphQLObjectTypes and GraphQLInterfaceTypes', () => { 273 | const _ = new SemanticGraph(mockResolvers); 274 | 275 | _.parse(personOntology); 276 | 277 | let PersonType, fields; 278 | 279 | assert.doesNotThrow(() => PersonType = _.getObjectType(fooPerson)); 280 | assert.instanceOf(PersonType, GraphQLObjectType); 281 | assert.doesNotThrow(() => fields = PersonType._fields()); 282 | assert.property(fields, 'name'); 283 | assert.property(fields, 'age'); 284 | assert.property(fields, 'gender'); 285 | 286 | assert.doesNotThrow(() => PersonType = _.getInterfaceType(fooPerson)); 287 | assert.instanceOf(PersonType, GraphQLInterfaceType); 288 | assert.doesNotThrow(() => fields = PersonType._fields()); 289 | assert.property(fields, 'name'); 290 | assert.property(fields, 'age'); 291 | assert.property(fields, 'gender'); 292 | }); 293 | }); 294 | -------------------------------------------------------------------------------- /examples/foaf/foaf.ttl: -------------------------------------------------------------------------------- 1 | @prefix foaf: . 2 | @prefix owl: . 3 | @prefix dc11: . 4 | @prefix wot: . 5 | @prefix rdfs: . 6 | @prefix ns0: . 7 | @prefix schema: . 8 | @prefix geo: . 9 | @prefix dc: . 10 | @prefix rdf: . 11 | @prefix skos: . 12 | 13 | foaf: 14 | a owl:Ontology ; 15 | dc11:title "Friend of a Friend (FOAF) vocabulary" ; 16 | dc11:description "The Friend of a Friend (FOAF) RDF vocabulary, described using W3C RDF Schema and the Web Ontology Language." . 17 | 18 | wot:assurance a owl:AnnotationProperty . 19 | wot:src_assurance a owl:AnnotationProperty . 20 | a owl:AnnotationProperty . 21 | dc11:description a owl:AnnotationProperty . 22 | dc11:title a owl:AnnotationProperty . 23 | dc11:date a owl:AnnotationProperty . 24 | rdfs:Class a owl:Class . 25 | foaf:LabelProperty 26 | a rdfs:Class, owl:Class ; 27 | ns0:term_status "unstable" ; 28 | rdfs:label "Label Property" ; 29 | rdfs:comment "A foaf:LabelProperty is any RDF property with texual values that serve as labels." ; 30 | rdfs:isDefinedBy foaf: . 31 | 32 | foaf:Person 33 | a rdfs:Class, owl:Class ; 34 | rdfs:label "Person" ; 35 | rdfs:comment "A person." ; 36 | ns0:term_status "stable" ; 37 | owl:equivalentClass schema:Person, ; 38 | rdfs:subClassOf foaf:Agent, geo:SpatialThing ; 39 | rdfs:isDefinedBy foaf: ; 40 | owl:disjointWith foaf:Organization, foaf:Project . 41 | 42 | foaf:Agent 43 | a owl:Class, rdfs:Class ; 44 | ns0:term_status "stable" ; 45 | rdfs:label "Agent" ; 46 | rdfs:comment "An agent (eg. person, group, software or physical artifact)." ; 47 | owl:equivalentClass dc:Agent . 48 | 49 | geo:SpatialThing 50 | a owl:Class ; 51 | rdfs:label "Spatial Thing" . 52 | 53 | foaf:Document 54 | a rdfs:Class, owl:Class ; 55 | rdfs:label "Document" ; 56 | rdfs:comment "A document." ; 57 | ns0:term_status "stable" ; 58 | owl:equivalentClass schema:CreativeWork ; 59 | rdfs:isDefinedBy foaf: ; 60 | owl:disjointWith foaf:Organization, foaf:Project . 61 | 62 | foaf:Organization 63 | a rdfs:Class, owl:Class ; 64 | rdfs:label "Organization" ; 65 | rdfs:comment "An organization." ; 66 | ns0:term_status "stable" ; 67 | rdfs:subClassOf foaf:Agent ; 68 | rdfs:isDefinedBy foaf: ; 69 | owl:disjointWith foaf:Person, foaf:Document . 70 | 71 | foaf:Group 72 | a rdfs:Class, owl:Class ; 73 | ns0:term_status "stable" ; 74 | rdfs:label "Group" ; 75 | rdfs:comment "A class of Agents." ; 76 | rdfs:subClassOf foaf:Agent . 77 | 78 | foaf:Project 79 | a rdfs:Class, owl:Class ; 80 | ns0:term_status "testing" ; 81 | rdfs:label "Project" ; 82 | rdfs:comment "A project (a collective endeavour of some kind)." ; 83 | rdfs:isDefinedBy foaf: ; 84 | owl:disjointWith foaf:Person, foaf:Document . 85 | 86 | foaf:Image 87 | a rdfs:Class, owl:Class ; 88 | ns0:term_status "stable" ; 89 | rdfs:label "Image" ; 90 | rdfs:comment "An image." ; 91 | owl:equivalentClass schema:ImageObject ; 92 | rdfs:subClassOf foaf:Document ; 93 | rdfs:isDefinedBy foaf: . 94 | 95 | foaf:PersonalProfileDocument 96 | a rdfs:Class, owl:Class ; 97 | rdfs:label "PersonalProfileDocument" ; 98 | rdfs:comment "A personal profile RDF document." ; 99 | ns0:term_status "testing" ; 100 | rdfs:subClassOf foaf:Document . 101 | 102 | foaf:OnlineAccount 103 | a rdfs:Class, owl:Class ; 104 | ns0:term_status "testing" ; 105 | rdfs:label "Online Account" ; 106 | rdfs:comment "An online account." ; 107 | rdfs:isDefinedBy foaf: ; 108 | rdfs:subClassOf owl:Thing . 109 | 110 | owl:Thing rdfs:label "Thing" . 111 | foaf:OnlineGamingAccount 112 | a rdfs:Class, owl:Class ; 113 | ns0:term_status "unstable" ; 114 | rdfs:label "Online Gaming Account" ; 115 | rdfs:comment "An online gaming account." ; 116 | rdfs:subClassOf foaf:OnlineAccount ; 117 | rdfs:isDefinedBy foaf: . 118 | 119 | foaf:OnlineEcommerceAccount 120 | a rdfs:Class, owl:Class ; 121 | ns0:term_status "unstable" ; 122 | rdfs:label "Online E-commerce Account" ; 123 | rdfs:comment "An online e-commerce account." ; 124 | rdfs:subClassOf foaf:OnlineAccount ; 125 | rdfs:isDefinedBy foaf: . 126 | 127 | foaf:OnlineChatAccount 128 | a rdfs:Class, owl:Class ; 129 | ns0:term_status "unstable" ; 130 | rdfs:label "Online Chat Account" ; 131 | rdfs:comment "An online chat account." ; 132 | rdfs:subClassOf foaf:OnlineAccount ; 133 | rdfs:isDefinedBy foaf: . 134 | 135 | foaf:mbox 136 | a rdf:Property, owl:InverseFunctionalProperty, owl:ObjectProperty ; 137 | ns0:term_status "stable" ; 138 | rdfs:label "personal mailbox" ; 139 | rdfs:comment "A personal mailbox, ie. an Internet mailbox associated with exactly one owner, the first owner of this mailbox. This is a 'static inverse functional property', in that there is (across time and change) at most one individual that ever has any particular value for foaf:mbox." ; 140 | rdfs:domain foaf:Agent ; 141 | rdfs:range owl:Thing ; 142 | rdfs:isDefinedBy foaf: . 143 | 144 | foaf:mbox_sha1sum 145 | a rdf:Property, owl:InverseFunctionalProperty, owl:DatatypeProperty ; 146 | ns0:term_status "testing" ; 147 | rdfs:label "sha1sum of a personal mailbox URI name" ; 148 | rdfs:comment "The sha1sum of the URI of an Internet mailbox associated with exactly one owner, the first owner of the mailbox." ; 149 | rdfs:domain foaf:Agent ; 150 | rdfs:range rdfs:Literal ; 151 | rdfs:isDefinedBy foaf: . 152 | 153 | foaf:gender 154 | a rdf:Property, owl:FunctionalProperty, owl:DatatypeProperty ; 155 | ns0:term_status "testing" ; 156 | rdfs:label "gender" ; 157 | rdfs:comment "The gender of this Agent (typically but not necessarily 'male' or 'female')." ; 158 | rdfs:domain foaf:Agent ; 159 | rdfs:range rdfs:Literal ; 160 | rdfs:isDefinedBy foaf: . 161 | 162 | foaf:geekcode 163 | a rdf:Property, owl:DatatypeProperty ; 164 | ns0:term_status "archaic" ; 165 | rdfs:label "geekcode" ; 166 | rdfs:comment "A textual geekcode for this person, see http://www.geekcode.com/geek.html" ; 167 | rdfs:domain foaf:Person ; 168 | rdfs:range rdfs:Literal ; 169 | rdfs:isDefinedBy foaf: . 170 | 171 | foaf:dnaChecksum 172 | a rdf:Property, owl:DatatypeProperty ; 173 | ns0:term_status "archaic" ; 174 | rdfs:label "DNA checksum" ; 175 | rdfs:comment "A checksum for the DNA of some thing. Joke." ; 176 | rdfs:isDefinedBy foaf: ; 177 | rdfs:range rdfs:Literal . 178 | 179 | foaf:sha1 180 | a rdf:Property, owl:DatatypeProperty ; 181 | ns0:term_status "unstable" ; 182 | rdfs:label "sha1sum (hex)" ; 183 | rdfs:comment "A sha1sum hash, in hex." ; 184 | rdfs:domain foaf:Document ; 185 | rdfs:isDefinedBy foaf: . 186 | 187 | foaf:based_near 188 | a rdf:Property, owl:ObjectProperty ; 189 | ns0:term_status "testing" ; 190 | rdfs:label "based near" ; 191 | rdfs:comment "A location that something is based near, for some broadly human notion of near." ; 192 | rdfs:domain geo:SpatialThing ; 193 | rdfs:range geo:SpatialThing ; 194 | rdfs:isDefinedBy foaf: . 195 | 196 | foaf:title 197 | a rdf:Property, owl:DatatypeProperty ; 198 | ns0:term_status "testing" ; 199 | rdfs:label "title" ; 200 | rdfs:comment "Title (Mr, Mrs, Ms, Dr. etc)" ; 201 | rdfs:isDefinedBy foaf: . 202 | 203 | foaf:nick 204 | a rdf:Property, owl:DatatypeProperty ; 205 | ns0:term_status "testing" ; 206 | rdfs:label "nickname" ; 207 | rdfs:comment "A short informal nickname characterising an agent (includes login identifiers, IRC and other chat nicknames)." ; 208 | rdfs:isDefinedBy foaf: . 209 | 210 | foaf:jabberID 211 | a rdf:Property, owl:DatatypeProperty, owl:InverseFunctionalProperty ; 212 | ns0:term_status "testing" ; 213 | rdfs:label "jabber ID" ; 214 | rdfs:comment "A jabber ID for something." ; 215 | rdfs:isDefinedBy foaf: ; 216 | rdfs:domain foaf:Agent ; 217 | rdfs:range rdfs:Literal . 218 | 219 | foaf:aimChatID 220 | a rdf:Property, owl:DatatypeProperty, owl:InverseFunctionalProperty ; 221 | ns0:term_status "testing" ; 222 | rdfs:label "AIM chat ID" ; 223 | rdfs:comment "An AIM chat ID" ; 224 | rdfs:isDefinedBy foaf: ; 225 | rdfs:subPropertyOf foaf:nick ; 226 | rdfs:domain foaf:Agent ; 227 | rdfs:range rdfs:Literal . 228 | 229 | foaf:skypeID 230 | a rdf:Property, owl:DatatypeProperty ; 231 | ns0:term_status "testing" ; 232 | rdfs:label "Skype ID" ; 233 | rdfs:comment "A Skype ID" ; 234 | rdfs:isDefinedBy foaf: ; 235 | rdfs:subPropertyOf foaf:nick ; 236 | rdfs:domain foaf:Agent ; 237 | rdfs:range rdfs:Literal . 238 | 239 | foaf:icqChatID 240 | a rdf:Property, owl:DatatypeProperty, owl:InverseFunctionalProperty ; 241 | ns0:term_status "testing" ; 242 | rdfs:label "ICQ chat ID" ; 243 | rdfs:comment "An ICQ chat ID" ; 244 | rdfs:isDefinedBy foaf: ; 245 | rdfs:subPropertyOf foaf:nick ; 246 | rdfs:domain foaf:Agent ; 247 | rdfs:range rdfs:Literal . 248 | 249 | foaf:yahooChatID 250 | a rdf:Property, owl:DatatypeProperty, owl:InverseFunctionalProperty ; 251 | ns0:term_status "testing" ; 252 | rdfs:label "Yahoo chat ID" ; 253 | rdfs:comment "A Yahoo chat ID" ; 254 | rdfs:isDefinedBy foaf: ; 255 | rdfs:subPropertyOf foaf:nick ; 256 | rdfs:domain foaf:Agent ; 257 | rdfs:range rdfs:Literal . 258 | 259 | foaf:msnChatID 260 | a rdf:Property, owl:DatatypeProperty, owl:InverseFunctionalProperty ; 261 | ns0:term_status "testing" ; 262 | rdfs:label "MSN chat ID" ; 263 | rdfs:comment "An MSN chat ID" ; 264 | rdfs:isDefinedBy foaf: ; 265 | rdfs:subPropertyOf foaf:nick ; 266 | rdfs:domain foaf:Agent ; 267 | rdfs:range rdfs:Literal . 268 | 269 | foaf:name 270 | a rdf:Property, owl:DatatypeProperty ; 271 | ns0:term_status "testing" ; 272 | rdfs:label "name" ; 273 | rdfs:comment "A name for some thing." ; 274 | rdfs:domain owl:Thing ; 275 | rdfs:range rdfs:Literal ; 276 | rdfs:isDefinedBy foaf: ; 277 | rdfs:subPropertyOf rdfs:label . 278 | 279 | foaf:firstName 280 | a rdf:Property, owl:DatatypeProperty ; 281 | ns0:term_status "testing" ; 282 | rdfs:label "firstName" ; 283 | rdfs:comment "The first name of a person." ; 284 | rdfs:domain foaf:Person ; 285 | rdfs:range rdfs:Literal ; 286 | rdfs:isDefinedBy foaf: . 287 | 288 | foaf:lastName 289 | a rdf:Property, owl:DatatypeProperty ; 290 | ns0:term_status "testing" ; 291 | rdfs:label "lastName" ; 292 | rdfs:comment "The last name of a person." ; 293 | rdfs:domain foaf:Person ; 294 | rdfs:range rdfs:Literal ; 295 | rdfs:isDefinedBy foaf: . 296 | 297 | foaf:givenName 298 | a rdf:Property, owl:DatatypeProperty ; 299 | ns0:term_status "testing" ; 300 | rdfs:label "Given name" ; 301 | rdfs:comment "The given name of some person." ; 302 | rdfs:isDefinedBy foaf: . 303 | 304 | foaf:givenname 305 | a rdf:Property, owl:DatatypeProperty ; 306 | ns0:term_status "archaic" ; 307 | rdfs:label "Given name" ; 308 | rdfs:comment "The given name of some person." ; 309 | rdfs:isDefinedBy foaf: . 310 | 311 | foaf:surname 312 | a rdf:Property, owl:DatatypeProperty ; 313 | ns0:term_status "archaic" ; 314 | rdfs:label "Surname" ; 315 | rdfs:comment "The surname of some person." ; 316 | rdfs:domain foaf:Person ; 317 | rdfs:range rdfs:Literal ; 318 | rdfs:isDefinedBy foaf: . 319 | 320 | foaf:family_name 321 | a rdf:Property, owl:DatatypeProperty ; 322 | ns0:term_status "archaic" ; 323 | rdfs:label "family_name" ; 324 | rdfs:comment "The family name of some person." ; 325 | rdfs:domain foaf:Person ; 326 | rdfs:range rdfs:Literal ; 327 | rdfs:isDefinedBy foaf: . 328 | 329 | foaf:familyName 330 | a rdf:Property, owl:DatatypeProperty ; 331 | ns0:term_status "testing" ; 332 | rdfs:label "familyName" ; 333 | rdfs:comment "The family name of some person." ; 334 | rdfs:domain foaf:Person ; 335 | rdfs:range rdfs:Literal ; 336 | rdfs:isDefinedBy foaf: . 337 | 338 | foaf:phone 339 | a rdf:Property, owl:ObjectProperty ; 340 | ns0:term_status "testing" ; 341 | rdfs:label "phone" ; 342 | rdfs:comment "A phone, specified using fully qualified tel: URI scheme (refs: http://www.w3.org/Addressing/schemes.html#tel)." ; 343 | rdfs:isDefinedBy foaf: . 344 | 345 | foaf:homepage 346 | a rdf:Property, owl:ObjectProperty, owl:InverseFunctionalProperty ; 347 | ns0:term_status "stable" ; 348 | rdfs:label "homepage" ; 349 | rdfs:comment "A homepage for some thing." ; 350 | rdfs:subPropertyOf foaf:page, foaf:isPrimaryTopicOf ; 351 | rdfs:domain owl:Thing ; 352 | rdfs:range foaf:Document ; 353 | rdfs:isDefinedBy foaf: . 354 | 355 | foaf:weblog 356 | a rdf:Property, owl:ObjectProperty, owl:InverseFunctionalProperty ; 357 | ns0:term_status "stable" ; 358 | rdfs:label "weblog" ; 359 | rdfs:comment "A weblog of some thing (whether person, group, company etc.)." ; 360 | rdfs:subPropertyOf foaf:page ; 361 | rdfs:domain foaf:Agent ; 362 | rdfs:range foaf:Document ; 363 | rdfs:isDefinedBy foaf: . 364 | 365 | foaf:openid 366 | a rdf:Property, owl:ObjectProperty, owl:InverseFunctionalProperty ; 367 | ns0:term_status "testing" ; 368 | rdfs:label "openid" ; 369 | rdfs:comment "An OpenID for an Agent." ; 370 | rdfs:subPropertyOf foaf:isPrimaryTopicOf ; 371 | rdfs:domain foaf:Agent ; 372 | rdfs:range foaf:Document ; 373 | rdfs:isDefinedBy foaf: . 374 | 375 | foaf:tipjar 376 | a rdf:Property, owl:ObjectProperty ; 377 | ns0:term_status "testing" ; 378 | rdfs:label "tipjar" ; 379 | rdfs:comment "A tipjar document for this agent, describing means for payment and reward." ; 380 | rdfs:subPropertyOf foaf:page ; 381 | rdfs:domain foaf:Agent ; 382 | rdfs:range foaf:Document ; 383 | rdfs:isDefinedBy foaf: . 384 | 385 | foaf:plan 386 | a rdf:Property, owl:DatatypeProperty ; 387 | ns0:term_status "testing" ; 388 | rdfs:label "plan" ; 389 | rdfs:comment "A .plan comment, in the tradition of finger and '.plan' files." ; 390 | rdfs:isDefinedBy foaf: ; 391 | rdfs:domain foaf:Person ; 392 | rdfs:range rdfs:Literal . 393 | 394 | foaf:made 395 | a rdf:Property, owl:ObjectProperty ; 396 | ns0:term_status "stable" ; 397 | rdfs:label "made" ; 398 | rdfs:comment "Something that was made by this agent." ; 399 | rdfs:domain foaf:Agent ; 400 | rdfs:range owl:Thing ; 401 | rdfs:isDefinedBy foaf: ; 402 | owl:inverseOf foaf:maker . 403 | 404 | foaf:maker 405 | a rdf:Property, owl:ObjectProperty ; 406 | ns0:term_status "stable" ; 407 | rdfs:label "maker" ; 408 | rdfs:comment "An agent that made this thing." ; 409 | owl:equivalentProperty dc:creator ; 410 | rdfs:domain owl:Thing ; 411 | rdfs:range foaf:Agent ; 412 | rdfs:isDefinedBy foaf: ; 413 | owl:inverseOf foaf:made . 414 | 415 | foaf:img 416 | a rdf:Property, owl:ObjectProperty ; 417 | ns0:term_status "testing" ; 418 | rdfs:label "image" ; 419 | rdfs:comment "An image that can be used to represent some thing (ie. those depictions which are particularly representative of something, eg. one's photo on a homepage)." ; 420 | rdfs:domain foaf:Person ; 421 | rdfs:range foaf:Image ; 422 | rdfs:subPropertyOf foaf:depiction ; 423 | rdfs:isDefinedBy foaf: . 424 | 425 | foaf:depiction 426 | a rdf:Property, owl:ObjectProperty ; 427 | ns0:term_status "testing" ; 428 | rdfs:label "depiction" ; 429 | rdfs:comment "A depiction of some thing." ; 430 | rdfs:domain owl:Thing ; 431 | rdfs:range foaf:Image ; 432 | rdfs:isDefinedBy foaf: ; 433 | owl:inverseOf foaf:depicts . 434 | 435 | foaf:depicts 436 | a rdf:Property, owl:ObjectProperty ; 437 | ns0:term_status "testing" ; 438 | rdfs:label "depicts" ; 439 | rdfs:comment "A thing depicted in this representation." ; 440 | rdfs:range owl:Thing ; 441 | rdfs:domain foaf:Image ; 442 | rdfs:isDefinedBy foaf: ; 443 | owl:inverseOf foaf:depiction . 444 | 445 | foaf:thumbnail 446 | a rdf:Property, owl:ObjectProperty ; 447 | ns0:term_status "testing" ; 448 | rdfs:label "thumbnail" ; 449 | rdfs:comment "A derived thumbnail image." ; 450 | rdfs:domain foaf:Image ; 451 | rdfs:range foaf:Image ; 452 | rdfs:isDefinedBy foaf: . 453 | 454 | foaf:myersBriggs 455 | a rdf:Property, owl:DatatypeProperty ; 456 | ns0:term_status "testing" ; 457 | rdfs:label "myersBriggs" ; 458 | rdfs:comment "A Myers Briggs (MBTI) personality classification." ; 459 | rdfs:domain foaf:Person ; 460 | rdfs:range rdfs:Literal ; 461 | rdfs:isDefinedBy foaf: . 462 | 463 | foaf:workplaceHomepage 464 | a rdf:Property, owl:ObjectProperty ; 465 | ns0:term_status "testing" ; 466 | rdfs:label "workplace homepage" ; 467 | rdfs:comment "A workplace homepage of some person; the homepage of an organization they work for." ; 468 | rdfs:domain foaf:Person ; 469 | rdfs:range foaf:Document ; 470 | rdfs:isDefinedBy foaf: . 471 | 472 | foaf:workInfoHomepage 473 | a rdf:Property, owl:ObjectProperty ; 474 | ns0:term_status "testing" ; 475 | rdfs:label "work info homepage" ; 476 | rdfs:comment "A work info homepage of some person; a page about their work for some organization." ; 477 | rdfs:domain foaf:Person ; 478 | rdfs:range foaf:Document ; 479 | rdfs:isDefinedBy foaf: . 480 | 481 | foaf:schoolHomepage 482 | a rdf:Property, owl:ObjectProperty ; 483 | ns0:term_status "testing" ; 484 | rdfs:label "schoolHomepage" ; 485 | rdfs:comment "A homepage of a school attended by the person." ; 486 | rdfs:domain foaf:Person ; 487 | rdfs:range foaf:Document ; 488 | rdfs:isDefinedBy foaf: . 489 | 490 | foaf:knows 491 | a rdf:Property, owl:ObjectProperty ; 492 | ns0:term_status "stable" ; 493 | rdfs:label "knows" ; 494 | rdfs:comment "A person known by this person (indicating some level of reciprocated interaction between the parties)." ; 495 | rdfs:domain foaf:Person ; 496 | rdfs:range foaf:Person ; 497 | rdfs:isDefinedBy foaf: . 498 | 499 | foaf:interest 500 | a rdf:Property, owl:ObjectProperty ; 501 | ns0:term_status "testing" ; 502 | rdfs:label "interest" ; 503 | rdfs:comment "A page about a topic of interest to this person." ; 504 | rdfs:domain foaf:Agent ; 505 | rdfs:range foaf:Document ; 506 | rdfs:isDefinedBy foaf: . 507 | 508 | foaf:topic_interest 509 | a rdf:Property, owl:ObjectProperty ; 510 | ns0:term_status "testing" ; 511 | rdfs:label "topic_interest" ; 512 | rdfs:comment "A thing of interest to this person." ; 513 | rdfs:domain foaf:Agent ; 514 | rdfs:range owl:Thing ; 515 | rdfs:isDefinedBy foaf: . 516 | 517 | foaf:publications 518 | a rdf:Property, owl:ObjectProperty ; 519 | ns0:term_status "testing" ; 520 | rdfs:label "publications" ; 521 | rdfs:comment "A link to the publications of this person." ; 522 | rdfs:domain foaf:Person ; 523 | rdfs:range foaf:Document ; 524 | rdfs:isDefinedBy foaf: . 525 | 526 | foaf:currentProject 527 | a rdf:Property, owl:ObjectProperty ; 528 | ns0:term_status "testing" ; 529 | rdfs:label "current project" ; 530 | rdfs:comment "A current project this person works on." ; 531 | rdfs:domain foaf:Person ; 532 | rdfs:range owl:Thing ; 533 | rdfs:isDefinedBy foaf: . 534 | 535 | foaf:pastProject 536 | a rdf:Property, owl:ObjectProperty ; 537 | ns0:term_status "testing" ; 538 | rdfs:label "past project" ; 539 | rdfs:comment "A project this person has previously worked on." ; 540 | rdfs:domain foaf:Person ; 541 | rdfs:range owl:Thing ; 542 | rdfs:isDefinedBy foaf: . 543 | 544 | foaf:fundedBy 545 | a rdf:Property, owl:ObjectProperty ; 546 | ns0:term_status "archaic" ; 547 | rdfs:label "funded by" ; 548 | rdfs:comment "An organization funding a project or person." ; 549 | rdfs:domain owl:Thing ; 550 | rdfs:range owl:Thing ; 551 | rdfs:isDefinedBy foaf: . 552 | 553 | foaf:logo 554 | a rdf:Property, owl:ObjectProperty, owl:InverseFunctionalProperty ; 555 | ns0:term_status "testing" ; 556 | rdfs:label "logo" ; 557 | rdfs:comment "A logo representing some thing." ; 558 | rdfs:domain owl:Thing ; 559 | rdfs:range owl:Thing ; 560 | rdfs:isDefinedBy foaf: . 561 | 562 | foaf:topic 563 | a rdf:Property, owl:ObjectProperty ; 564 | ns0:term_status "testing" ; 565 | rdfs:label "topic" ; 566 | rdfs:comment "A topic of some page or document." ; 567 | rdfs:domain foaf:Document ; 568 | rdfs:range owl:Thing ; 569 | owl:inverseOf foaf:page ; 570 | rdfs:isDefinedBy foaf: . 571 | 572 | foaf:primaryTopic 573 | a rdf:Property, owl:FunctionalProperty, owl:ObjectProperty ; 574 | ns0:term_status "stable" ; 575 | rdfs:label "primary topic" ; 576 | rdfs:comment "The primary topic of some page or document." ; 577 | rdfs:domain foaf:Document ; 578 | rdfs:range owl:Thing ; 579 | owl:inverseOf foaf:isPrimaryTopicOf ; 580 | rdfs:isDefinedBy foaf: . 581 | 582 | foaf:focus 583 | a rdf:Property, owl:ObjectProperty ; 584 | ns0:term_status "testing" ; 585 | rdfs:label "focus" ; 586 | rdfs:comment "The underlying or 'focal' entity associated with some SKOS-described concept." ; 587 | rdfs:domain skos:Concept ; 588 | rdfs:range owl:Thing ; 589 | rdfs:isDefinedBy foaf: . 590 | 591 | skos:Concept rdfs:label "Concept" . 592 | foaf:isPrimaryTopicOf 593 | a rdf:Property, owl:InverseFunctionalProperty ; 594 | ns0:term_status "stable" ; 595 | rdfs:label "is primary topic of" ; 596 | rdfs:comment "A document that this thing is the primary topic of." ; 597 | rdfs:subPropertyOf foaf:page ; 598 | owl:inverseOf foaf:primaryTopic ; 599 | rdfs:domain owl:Thing ; 600 | rdfs:range foaf:Document ; 601 | rdfs:isDefinedBy foaf: . 602 | 603 | foaf:page 604 | a rdf:Property, owl:ObjectProperty ; 605 | ns0:term_status "stable" ; 606 | rdfs:label "page" ; 607 | rdfs:comment "A page or document about this thing." ; 608 | rdfs:domain owl:Thing ; 609 | rdfs:range foaf:Document ; 610 | rdfs:isDefinedBy foaf: ; 611 | owl:inverseOf foaf:topic . 612 | 613 | foaf:theme 614 | a rdf:Property, owl:ObjectProperty ; 615 | ns0:term_status "archaic" ; 616 | rdfs:label "theme" ; 617 | rdfs:comment "A theme." ; 618 | rdfs:domain owl:Thing ; 619 | rdfs:range owl:Thing ; 620 | rdfs:isDefinedBy foaf: . 621 | 622 | foaf:account 623 | a rdf:Property, owl:ObjectProperty ; 624 | ns0:term_status "testing" ; 625 | rdfs:label "account" ; 626 | rdfs:comment "Indicates an account held by this agent." ; 627 | rdfs:domain foaf:Agent ; 628 | rdfs:range foaf:OnlineAccount ; 629 | rdfs:isDefinedBy foaf: . 630 | 631 | foaf:holdsAccount 632 | a rdf:Property, owl:ObjectProperty ; 633 | ns0:term_status "archaic" ; 634 | rdfs:label "account" ; 635 | rdfs:comment "Indicates an account held by this agent." ; 636 | rdfs:domain foaf:Agent ; 637 | rdfs:range foaf:OnlineAccount ; 638 | rdfs:isDefinedBy foaf: . 639 | 640 | foaf:accountServiceHomepage 641 | a rdf:Property, owl:ObjectProperty ; 642 | ns0:term_status "testing" ; 643 | rdfs:label "account service homepage" ; 644 | rdfs:comment "Indicates a homepage of the service provide for this online account." ; 645 | rdfs:domain foaf:OnlineAccount ; 646 | rdfs:range foaf:Document ; 647 | rdfs:isDefinedBy foaf: . 648 | 649 | foaf:accountName 650 | a rdf:Property, owl:DatatypeProperty ; 651 | ns0:term_status "testing" ; 652 | rdfs:label "account name" ; 653 | rdfs:comment "Indicates the name (identifier) associated with this online account." ; 654 | rdfs:domain foaf:OnlineAccount ; 655 | rdfs:range rdfs:Literal ; 656 | rdfs:isDefinedBy foaf: . 657 | 658 | foaf:member 659 | a rdf:Property, owl:ObjectProperty ; 660 | ns0:term_status "stable" ; 661 | rdfs:label "member" ; 662 | rdfs:comment "Indicates a member of a Group" ; 663 | rdfs:domain foaf:Group ; 664 | rdfs:range foaf:Agent ; 665 | rdfs:isDefinedBy foaf: . 666 | 667 | foaf:membershipClass 668 | a rdf:Property, owl:AnnotationProperty ; 669 | ns0:term_status "unstable" ; 670 | rdfs:label "membershipClass" ; 671 | rdfs:comment "Indicates the class of individuals that are a member of a Group" ; 672 | rdfs:isDefinedBy foaf: . 673 | 674 | foaf:birthday 675 | a rdf:Property, owl:FunctionalProperty, owl:DatatypeProperty ; 676 | ns0:term_status "unstable" ; 677 | rdfs:label "birthday" ; 678 | rdfs:comment "The birthday of this Agent, represented in mm-dd string form, eg. '12-31'." ; 679 | rdfs:domain foaf:Agent ; 680 | rdfs:range rdfs:Literal ; 681 | rdfs:isDefinedBy foaf: . 682 | 683 | foaf:age 684 | a rdf:Property, owl:FunctionalProperty, owl:DatatypeProperty ; 685 | ns0:term_status "unstable" ; 686 | rdfs:label "age" ; 687 | rdfs:comment "The age in years of some agent." ; 688 | rdfs:domain foaf:Agent ; 689 | rdfs:range rdfs:Literal ; 690 | rdfs:isDefinedBy foaf: . 691 | 692 | foaf:status 693 | a rdf:Property, owl:DatatypeProperty ; 694 | ns0:term_status "unstable" ; 695 | rdfs:label "status" ; 696 | rdfs:comment "A string expressing what the user is happy for the general public (normally) to know about their current activity." ; 697 | rdfs:domain foaf:Agent ; 698 | rdfs:range rdfs:Literal ; 699 | rdfs:isDefinedBy foaf: . 700 | -------------------------------------------------------------------------------- /ontologies/owl.ttl: -------------------------------------------------------------------------------- 1 | @prefix dc: . 2 | @prefix grddl: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix xml: . 7 | @prefix xsd: . 8 | 9 | a owl:Ontology ; 10 | dc:title "The OWL 2 Schema vocabulary (OWL 2)" ; 11 | rdfs:comment """ 12 | This ontology partially describes the built-in classes and 13 | properties that together form the basis of the RDF/XML syntax of OWL 2. 14 | The content of this ontology is based on Tables 6.1 and 6.2 15 | in Section 6.4 of the OWL 2 RDF-Based Semantics specification, 16 | available at http://www.w3.org/TR/owl2-rdf-based-semantics/. 17 | Please note that those tables do not include the different annotations 18 | (labels, comments and rdfs:isDefinedBy links) used in this file. 19 | Also note that the descriptions provided in this ontology do not 20 | provide a complete and correct formal description of either the syntax 21 | or the semantics of the introduced terms (please see the OWL 2 22 | recommendations for the complete and normative specifications). 23 | Furthermore, the information provided by this ontology may be 24 | misleading if not used with care. This ontology SHOULD NOT be imported 25 | into OWL ontologies. Importing this file into an OWL 2 DL ontology 26 | will cause it to become an OWL 2 Full ontology and may have other, 27 | unexpected, consequences. 28 | """ ; 29 | rdfs:isDefinedBy 30 | , 31 | , 32 | ; 33 | rdfs:seeAlso , 34 | ; 35 | owl:imports ; 36 | owl:versionIRI ; 37 | owl:versionInfo "$Date: 2009/11/15 10:54:12 $" ; 38 | grddl:namespaceTransformation . 39 | 40 | 41 | owl:AllDifferent a rdfs:Class ; 42 | rdfs:label "AllDifferent" ; 43 | rdfs:comment "The class of collections of pairwise different individuals." ; 44 | rdfs:isDefinedBy ; 45 | rdfs:subClassOf rdfs:Resource . 46 | 47 | owl:AllDisjointClasses a rdfs:Class ; 48 | rdfs:label "AllDisjointClasses" ; 49 | rdfs:comment "The class of collections of pairwise disjoint classes." ; 50 | rdfs:isDefinedBy ; 51 | rdfs:subClassOf rdfs:Resource . 52 | 53 | owl:AllDisjointProperties a rdfs:Class ; 54 | rdfs:label "AllDisjointProperties" ; 55 | rdfs:comment "The class of collections of pairwise disjoint properties." ; 56 | rdfs:isDefinedBy ; 57 | rdfs:subClassOf rdfs:Resource . 58 | 59 | owl:Annotation a rdfs:Class ; 60 | rdfs:label "Annotation" ; 61 | rdfs:comment "The class of annotated annotations for which the RDF serialization consists of an annotated subject, predicate and object." ; 62 | rdfs:isDefinedBy ; 63 | rdfs:subClassOf rdfs:Resource . 64 | 65 | owl:AnnotationProperty a rdfs:Class ; 66 | rdfs:label "AnnotationProperty" ; 67 | rdfs:comment "The class of annotation properties." ; 68 | rdfs:isDefinedBy ; 69 | rdfs:subClassOf rdf:Property . 70 | 71 | owl:AsymmetricProperty a rdfs:Class ; 72 | rdfs:label "AsymmetricProperty" ; 73 | rdfs:comment "The class of asymmetric properties." ; 74 | rdfs:isDefinedBy ; 75 | rdfs:subClassOf owl:ObjectProperty . 76 | 77 | owl:Axiom a rdfs:Class ; 78 | rdfs:label "Axiom" ; 79 | rdfs:comment "The class of annotated axioms for which the RDF serialization consists of an annotated subject, predicate and object." ; 80 | rdfs:isDefinedBy ; 81 | rdfs:subClassOf rdfs:Resource . 82 | 83 | owl:Class a rdfs:Class ; 84 | rdfs:label "Class" ; 85 | rdfs:comment "The class of OWL classes." ; 86 | rdfs:isDefinedBy ; 87 | rdfs:subClassOf rdfs:Class . 88 | 89 | owl:DataRange a rdfs:Class ; 90 | rdfs:label "DataRange" ; 91 | rdfs:comment "The class of OWL data ranges, which are special kinds of datatypes. Note: The use of the IRI owl:DataRange has been deprecated as of OWL 2. The IRI rdfs:Datatype SHOULD be used instead." ; 92 | rdfs:isDefinedBy ; 93 | rdfs:subClassOf rdfs:Datatype . 94 | 95 | owl:DatatypeProperty a rdfs:Class ; 96 | rdfs:label "DatatypeProperty" ; 97 | rdfs:comment "The class of data properties." ; 98 | rdfs:isDefinedBy ; 99 | rdfs:subClassOf rdf:Property . 100 | 101 | owl:DeprecatedClass a rdfs:Class ; 102 | rdfs:label "DeprecatedClass" ; 103 | rdfs:comment "The class of deprecated classes." ; 104 | rdfs:isDefinedBy ; 105 | rdfs:subClassOf rdfs:Class . 106 | 107 | owl:DeprecatedProperty a rdfs:Class ; 108 | rdfs:label "DeprecatedProperty" ; 109 | rdfs:comment "The class of deprecated properties." ; 110 | rdfs:isDefinedBy ; 111 | rdfs:subClassOf rdf:Property . 112 | 113 | owl:FunctionalProperty a rdfs:Class ; 114 | rdfs:label "FunctionalProperty" ; 115 | rdfs:comment "The class of functional properties." ; 116 | rdfs:isDefinedBy ; 117 | rdfs:subClassOf rdf:Property . 118 | 119 | owl:InverseFunctionalProperty a rdfs:Class ; 120 | rdfs:label "InverseFunctionalProperty" ; 121 | rdfs:comment "The class of inverse-functional properties." ; 122 | rdfs:isDefinedBy ; 123 | rdfs:subClassOf owl:ObjectProperty . 124 | 125 | owl:IrreflexiveProperty a rdfs:Class ; 126 | rdfs:label "IrreflexiveProperty" ; 127 | rdfs:comment "The class of irreflexive properties." ; 128 | rdfs:isDefinedBy ; 129 | rdfs:subClassOf owl:ObjectProperty . 130 | 131 | owl:NamedIndividual a rdfs:Class ; 132 | rdfs:label "NamedIndividual" ; 133 | rdfs:comment "The class of named individuals." ; 134 | rdfs:isDefinedBy ; 135 | rdfs:subClassOf owl:Thing . 136 | 137 | owl:NegativePropertyAssertion a rdfs:Class ; 138 | rdfs:label "NegativePropertyAssertion" ; 139 | rdfs:comment "The class of negative property assertions." ; 140 | rdfs:isDefinedBy ; 141 | rdfs:subClassOf rdfs:Resource . 142 | 143 | owl:Nothing a owl:Class ; 144 | rdfs:label "Nothing" ; 145 | rdfs:comment "This is the empty class." ; 146 | rdfs:isDefinedBy ; 147 | rdfs:subClassOf owl:Thing . 148 | 149 | owl:ObjectProperty a rdfs:Class ; 150 | rdfs:label "ObjectProperty" ; 151 | rdfs:comment "The class of object properties." ; 152 | rdfs:isDefinedBy ; 153 | rdfs:subClassOf rdf:Property . 154 | 155 | owl:Ontology a rdfs:Class ; 156 | rdfs:label "Ontology" ; 157 | rdfs:comment "The class of ontologies." ; 158 | rdfs:isDefinedBy ; 159 | rdfs:subClassOf rdfs:Resource . 160 | 161 | owl:OntologyProperty a rdfs:Class ; 162 | rdfs:label "OntologyProperty" ; 163 | rdfs:comment "The class of ontology properties." ; 164 | rdfs:isDefinedBy ; 165 | rdfs:subClassOf rdf:Property . 166 | 167 | owl:ReflexiveProperty a rdfs:Class ; 168 | rdfs:label "ReflexiveProperty" ; 169 | rdfs:comment "The class of reflexive properties." ; 170 | rdfs:isDefinedBy ; 171 | rdfs:subClassOf owl:ObjectProperty . 172 | 173 | owl:Restriction a rdfs:Class ; 174 | rdfs:label "Restriction" ; 175 | rdfs:comment "The class of property restrictions." ; 176 | rdfs:isDefinedBy ; 177 | rdfs:subClassOf owl:Class . 178 | 179 | owl:SymmetricProperty a rdfs:Class ; 180 | rdfs:label "SymmetricProperty" ; 181 | rdfs:comment "The class of symmetric properties." ; 182 | rdfs:isDefinedBy ; 183 | rdfs:subClassOf owl:ObjectProperty . 184 | 185 | owl:TransitiveProperty a rdfs:Class ; 186 | rdfs:label "TransitiveProperty" ; 187 | rdfs:comment "The class of transitive properties." ; 188 | rdfs:isDefinedBy ; 189 | rdfs:subClassOf owl:ObjectProperty . 190 | 191 | owl:Thing a owl:Class ; 192 | rdfs:label "Thing" ; 193 | rdfs:comment "The class of OWL individuals." ; 194 | rdfs:isDefinedBy . 195 | 196 | owl:allValuesFrom a rdf:Property ; 197 | rdfs:label "allValuesFrom" ; 198 | rdfs:comment "The property that determines the class that a universal property restriction refers to." ; 199 | rdfs:domain owl:Restriction ; 200 | rdfs:isDefinedBy ; 201 | rdfs:range rdfs:Class . 202 | 203 | owl:annotatedProperty a rdf:Property ; 204 | rdfs:label "annotatedProperty" ; 205 | rdfs:comment "The property that determines the predicate of an annotated axiom or annotated annotation." ; 206 | rdfs:domain rdfs:Resource ; 207 | rdfs:isDefinedBy ; 208 | rdfs:range rdfs:Resource . 209 | 210 | owl:annotatedSource a rdf:Property ; 211 | rdfs:label "annotatedSource" ; 212 | rdfs:comment "The property that determines the subject of an annotated axiom or annotated annotation." ; 213 | rdfs:domain rdfs:Resource ; 214 | rdfs:isDefinedBy ; 215 | rdfs:range rdfs:Resource . 216 | 217 | owl:annotatedTarget a rdf:Property ; 218 | rdfs:label "annotatedTarget" ; 219 | rdfs:comment "The property that determines the object of an annotated axiom or annotated annotation." ; 220 | rdfs:domain rdfs:Resource ; 221 | rdfs:isDefinedBy ; 222 | rdfs:range rdfs:Resource . 223 | 224 | owl:assertionProperty a rdf:Property ; 225 | rdfs:label "assertionProperty" ; 226 | rdfs:comment "The property that determines the predicate of a negative property assertion." ; 227 | rdfs:domain owl:NegativePropertyAssertion ; 228 | rdfs:isDefinedBy ; 229 | rdfs:range rdf:Property . 230 | 231 | owl:backwardCompatibleWith a owl:AnnotationProperty, owl:OntologyProperty ; 232 | rdfs:label "backwardCompatibleWith" ; 233 | rdfs:comment "The annotation property that indicates that a given ontology is backward compatible with another ontology." ; 234 | rdfs:domain owl:Ontology ; 235 | rdfs:isDefinedBy ; 236 | rdfs:range owl:Ontology . 237 | 238 | owl:bottomDataProperty a owl:DatatypeProperty ; 239 | rdfs:label "bottomDataProperty" ; 240 | rdfs:comment "The data property that does not relate any individual to any data value." ; 241 | rdfs:domain owl:Thing ; 242 | rdfs:isDefinedBy ; 243 | rdfs:range rdfs:Literal . 244 | 245 | owl:bottomObjectProperty a owl:ObjectProperty ; 246 | rdfs:label "bottomObjectProperty" ; 247 | rdfs:comment "The object property that does not relate any two individuals." ; 248 | rdfs:domain owl:Thing ; 249 | rdfs:isDefinedBy ; 250 | rdfs:range owl:Thing . 251 | 252 | owl:cardinality a rdf:Property ; 253 | rdfs:label "cardinality" ; 254 | rdfs:comment "The property that determines the cardinality of an exact cardinality restriction." ; 255 | rdfs:domain owl:Restriction ; 256 | rdfs:isDefinedBy ; 257 | rdfs:range xsd:nonNegativeInteger . 258 | 259 | owl:complementOf a rdf:Property ; 260 | rdfs:label "complementOf" ; 261 | rdfs:comment "The property that determines that a given class is the complement of another class." ; 262 | rdfs:domain owl:Class ; 263 | rdfs:isDefinedBy ; 264 | rdfs:range owl:Class . 265 | 266 | owl:datatypeComplementOf a rdf:Property ; 267 | rdfs:label "datatypeComplementOf" ; 268 | rdfs:comment "The property that determines that a given data range is the complement of another data range with respect to the data domain." ; 269 | rdfs:domain rdfs:Datatype ; 270 | rdfs:isDefinedBy ; 271 | rdfs:range rdfs:Datatype . 272 | 273 | owl:deprecated a owl:AnnotationProperty ; 274 | rdfs:label "deprecated" ; 275 | rdfs:comment "The annotation property that indicates that a given entity has been deprecated." ; 276 | rdfs:domain rdfs:Resource ; 277 | rdfs:isDefinedBy ; 278 | rdfs:range rdfs:Resource . 279 | 280 | owl:differentFrom a rdf:Property ; 281 | rdfs:label "differentFrom" ; 282 | rdfs:comment "The property that determines that two given individuals are different." ; 283 | rdfs:domain owl:Thing ; 284 | rdfs:isDefinedBy ; 285 | rdfs:range owl:Thing . 286 | 287 | owl:disjointUnionOf a rdf:Property ; 288 | rdfs:label "disjointUnionOf" ; 289 | rdfs:comment "The property that determines that a given class is equivalent to the disjoint union of a collection of other classes." ; 290 | rdfs:domain owl:Class ; 291 | rdfs:isDefinedBy ; 292 | rdfs:range rdf:List . 293 | 294 | owl:disjointWith a rdf:Property ; 295 | rdfs:label "disjointWith" ; 296 | rdfs:comment "The property that determines that two given classes are disjoint." ; 297 | rdfs:domain owl:Class ; 298 | rdfs:isDefinedBy ; 299 | rdfs:range owl:Class . 300 | 301 | owl:distinctMembers a rdf:Property ; 302 | rdfs:label "distinctMembers" ; 303 | rdfs:comment "The property that determines the collection of pairwise different individuals in a owl:AllDifferent axiom." ; 304 | rdfs:domain owl:AllDifferent ; 305 | rdfs:isDefinedBy ; 306 | rdfs:range rdf:List . 307 | 308 | owl:equivalentClass a rdf:Property ; 309 | rdfs:label "equivalentClass" ; 310 | rdfs:comment "The property that determines that two given classes are equivalent, and that is used to specify datatype definitions." ; 311 | rdfs:domain rdfs:Class ; 312 | rdfs:isDefinedBy ; 313 | rdfs:range rdfs:Class . 314 | 315 | owl:equivalentProperty a rdf:Property ; 316 | rdfs:label "equivalentProperty" ; 317 | rdfs:comment "The property that determines that two given properties are equivalent." ; 318 | rdfs:domain rdf:Property ; 319 | rdfs:isDefinedBy ; 320 | rdfs:range rdf:Property . 321 | 322 | owl:hasKey a rdf:Property ; 323 | rdfs:label "hasKey" ; 324 | rdfs:comment "The property that determines the collection of properties that jointly build a key." ; 325 | rdfs:domain owl:Class ; 326 | rdfs:isDefinedBy ; 327 | rdfs:range rdf:List . 328 | 329 | owl:hasSelf a rdf:Property ; 330 | rdfs:label "hasSelf" ; 331 | rdfs:comment "The property that determines the property that a self restriction refers to." ; 332 | rdfs:domain owl:Restriction ; 333 | rdfs:isDefinedBy ; 334 | rdfs:range rdfs:Resource . 335 | 336 | owl:hasValue a rdf:Property ; 337 | rdfs:label "hasValue" ; 338 | rdfs:comment "The property that determines the individual that a has-value restriction refers to." ; 339 | rdfs:domain owl:Restriction ; 340 | rdfs:isDefinedBy ; 341 | rdfs:range rdfs:Resource . 342 | 343 | owl:imports a owl:OntologyProperty ; 344 | rdfs:label "imports" ; 345 | rdfs:comment "The property that is used for importing other ontologies into a given ontology." ; 346 | rdfs:domain owl:Ontology ; 347 | rdfs:isDefinedBy ; 348 | rdfs:range owl:Ontology . 349 | 350 | owl:incompatibleWith a owl:AnnotationProperty, owl:OntologyProperty ; 351 | rdfs:label "incompatibleWith" ; 352 | rdfs:comment "The annotation property that indicates that a given ontology is incompatible with another ontology." ; 353 | rdfs:domain owl:Ontology ; 354 | rdfs:isDefinedBy ; 355 | rdfs:range owl:Ontology . 356 | 357 | owl:intersectionOf a rdf:Property ; 358 | rdfs:label "intersectionOf" ; 359 | rdfs:comment "The property that determines the collection of classes or data ranges that build an intersection." ; 360 | rdfs:domain rdfs:Class ; 361 | rdfs:isDefinedBy ; 362 | rdfs:range rdf:List . 363 | 364 | owl:inverseOf a rdf:Property ; 365 | rdfs:label "inverseOf" ; 366 | rdfs:comment "The property that determines that two given properties are inverse." ; 367 | rdfs:domain owl:ObjectProperty ; 368 | rdfs:isDefinedBy ; 369 | rdfs:range owl:ObjectProperty . 370 | 371 | owl:maxCardinality a rdf:Property ; 372 | rdfs:label "maxCardinality" ; 373 | rdfs:comment "The property that determines the cardinality of a maximum cardinality restriction." ; 374 | rdfs:domain owl:Restriction ; 375 | rdfs:isDefinedBy ; 376 | rdfs:range xsd:nonNegativeInteger . 377 | 378 | owl:maxQualifiedCardinality a rdf:Property ; 379 | rdfs:label "maxQualifiedCardinality" ; 380 | rdfs:comment "The property that determines the cardinality of a maximum qualified cardinality restriction." ; 381 | rdfs:domain owl:Restriction ; 382 | rdfs:isDefinedBy ; 383 | rdfs:range xsd:nonNegativeInteger . 384 | 385 | owl:members a rdf:Property ; 386 | rdfs:label "members" ; 387 | rdfs:comment "The property that determines the collection of members in either a owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom." ; 388 | rdfs:domain rdfs:Resource ; 389 | rdfs:isDefinedBy ; 390 | rdfs:range rdf:List . 391 | 392 | owl:minCardinality a rdf:Property ; 393 | rdfs:label "minCardinality" ; 394 | rdfs:comment "The property that determines the cardinality of a minimum cardinality restriction." ; 395 | rdfs:domain owl:Restriction ; 396 | rdfs:isDefinedBy ; 397 | rdfs:range xsd:nonNegativeInteger . 398 | 399 | owl:minQualifiedCardinality a rdf:Property ; 400 | rdfs:label "minQualifiedCardinality" ; 401 | rdfs:comment "The property that determines the cardinality of a minimum qualified cardinality restriction." ; 402 | rdfs:domain owl:Restriction ; 403 | rdfs:isDefinedBy ; 404 | rdfs:range xsd:nonNegativeInteger . 405 | 406 | owl:onClass a rdf:Property ; 407 | rdfs:label "onClass" ; 408 | rdfs:comment "The property that determines the class that a qualified object cardinality restriction refers to." ; 409 | rdfs:domain owl:Restriction ; 410 | rdfs:isDefinedBy ; 411 | rdfs:range owl:Class . 412 | 413 | owl:onDataRange a rdf:Property ; 414 | rdfs:label "onDataRange" ; 415 | rdfs:comment "The property that determines the data range that a qualified data cardinality restriction refers to." ; 416 | rdfs:domain owl:Restriction ; 417 | rdfs:isDefinedBy ; 418 | rdfs:range rdfs:Datatype . 419 | 420 | owl:onDatatype a rdf:Property ; 421 | rdfs:label "onDatatype" ; 422 | rdfs:comment "The property that determines the datatype that a datatype restriction refers to." ; 423 | rdfs:domain rdfs:Datatype ; 424 | rdfs:isDefinedBy ; 425 | rdfs:range rdfs:Datatype . 426 | 427 | owl:oneOf a rdf:Property ; 428 | rdfs:label "oneOf" ; 429 | rdfs:comment "The property that determines the collection of individuals or data values that build an enumeration." ; 430 | rdfs:domain rdfs:Class ; 431 | rdfs:isDefinedBy ; 432 | rdfs:range rdf:List . 433 | 434 | owl:onProperties a rdf:Property ; 435 | rdfs:label "onProperties" ; 436 | rdfs:comment "The property that determines the n-tuple of properties that a property restriction on an n-ary data range refers to." ; 437 | rdfs:domain owl:Restriction ; 438 | rdfs:isDefinedBy ; 439 | rdfs:range rdf:List . 440 | 441 | owl:onProperty a rdf:Property ; 442 | rdfs:label "onProperty" ; 443 | rdfs:comment "The property that determines the property that a property restriction refers to." ; 444 | rdfs:domain owl:Restriction ; 445 | rdfs:isDefinedBy ; 446 | rdfs:range rdf:Property . 447 | 448 | owl:priorVersion a owl:AnnotationProperty, owl:OntologyProperty ; 449 | rdfs:label "priorVersion" ; 450 | rdfs:comment "The annotation property that indicates the predecessor ontology of a given ontology." ; 451 | rdfs:domain owl:Ontology ; 452 | rdfs:isDefinedBy ; 453 | rdfs:range owl:Ontology . 454 | 455 | owl:propertyChainAxiom a rdf:Property ; 456 | rdfs:label "propertyChainAxiom" ; 457 | rdfs:comment "The property that determines the n-tuple of properties that build a sub property chain of a given property." ; 458 | rdfs:domain owl:ObjectProperty ; 459 | rdfs:isDefinedBy ; 460 | rdfs:range rdf:List . 461 | 462 | owl:propertyDisjointWith a rdf:Property ; 463 | rdfs:label "propertyDisjointWith" ; 464 | rdfs:comment "The property that determines that two given properties are disjoint." ; 465 | rdfs:domain rdf:Property ; 466 | rdfs:isDefinedBy ; 467 | rdfs:range rdf:Property . 468 | 469 | owl:qualifiedCardinality a rdf:Property ; 470 | rdfs:label "qualifiedCardinality" ; 471 | rdfs:comment "The property that determines the cardinality of an exact qualified cardinality restriction." ; 472 | rdfs:domain owl:Restriction ; 473 | rdfs:isDefinedBy ; 474 | rdfs:range xsd:nonNegativeInteger . 475 | 476 | owl:sameAs a rdf:Property ; 477 | rdfs:label "sameAs" ; 478 | rdfs:comment "The property that determines that two given individuals are equal." ; 479 | rdfs:domain owl:Thing ; 480 | rdfs:isDefinedBy ; 481 | rdfs:range owl:Thing . 482 | 483 | owl:someValuesFrom a rdf:Property ; 484 | rdfs:label "someValuesFrom" ; 485 | rdfs:comment "The property that determines the class that an existential property restriction refers to." ; 486 | rdfs:domain owl:Restriction ; 487 | rdfs:isDefinedBy ; 488 | rdfs:range rdfs:Class . 489 | 490 | owl:sourceIndividual a rdf:Property ; 491 | rdfs:label "sourceIndividual" ; 492 | rdfs:comment "The property that determines the subject of a negative property assertion." ; 493 | rdfs:domain owl:NegativePropertyAssertion ; 494 | rdfs:isDefinedBy ; 495 | rdfs:range owl:Thing . 496 | 497 | owl:targetIndividual a rdf:Property ; 498 | rdfs:label "targetIndividual" ; 499 | rdfs:comment "The property that determines the object of a negative object property assertion." ; 500 | rdfs:domain owl:NegativePropertyAssertion ; 501 | rdfs:isDefinedBy ; 502 | rdfs:range owl:Thing . 503 | 504 | owl:targetValue a rdf:Property ; 505 | rdfs:label "targetValue" ; 506 | rdfs:comment "The property that determines the value of a negative data property assertion." ; 507 | rdfs:domain owl:NegativePropertyAssertion ; 508 | rdfs:isDefinedBy ; 509 | rdfs:range rdfs:Literal . 510 | 511 | owl:topDataProperty a owl:DatatypeProperty ; 512 | rdfs:label "topDataProperty" ; 513 | rdfs:comment "The data property that relates every individual to every data value." ; 514 | rdfs:domain owl:Thing ; 515 | rdfs:isDefinedBy ; 516 | rdfs:range rdfs:Literal . 517 | 518 | owl:topObjectProperty a owl:ObjectProperty ; 519 | rdfs:label "topObjectProperty" ; 520 | rdfs:comment "The object property that relates every two individuals." ; 521 | rdfs:domain owl:Thing ; 522 | rdfs:isDefinedBy ; 523 | rdfs:range owl:Thing . 524 | 525 | owl:unionOf a rdf:Property ; 526 | rdfs:label "unionOf" ; 527 | rdfs:comment "The property that determines the collection of classes or data ranges that build a union." ; 528 | rdfs:domain rdfs:Class ; 529 | rdfs:isDefinedBy ; 530 | rdfs:range rdf:List . 531 | 532 | owl:versionInfo a owl:AnnotationProperty ; 533 | rdfs:label "versionInfo" ; 534 | rdfs:comment "The annotation property that provides version information for an ontology or another OWL construct." ; 535 | rdfs:domain rdfs:Resource ; 536 | rdfs:isDefinedBy ; 537 | rdfs:range rdfs:Resource . 538 | 539 | owl:versionIRI a owl:OntologyProperty ; 540 | rdfs:label "versionIRI" ; 541 | rdfs:comment "The property that identifies the version IRI of an ontology." ; 542 | rdfs:domain owl:Ontology ; 543 | rdfs:isDefinedBy ; 544 | rdfs:range owl:Ontology . 545 | 546 | owl:withRestrictions a rdf:Property ; 547 | rdfs:label "withRestrictions" ; 548 | rdfs:comment "The property that determines the collection of facet-value pairs that define a datatype restriction." ; 549 | rdfs:domain rdfs:Datatype ; 550 | rdfs:isDefinedBy ; 551 | rdfs:range rdf:List . 552 | -------------------------------------------------------------------------------- /examples/basic/schema.graphql: -------------------------------------------------------------------------------- 1 | # A company to work and play. 2 | type Company implements CompanyInterface, ThingInterface, OwlThingInterface, RdfsResourceInterface { 3 | # A unique identifier for the resource. 4 | id: ID 5 | 6 | # Founding year - The year the Company was created. 7 | foundingYear: Int 8 | 9 | # Has CEO - The Person that is the CEO of the Company. 10 | hasCEO: Person 11 | 12 | # Has employees - The Persons that work for this company. 13 | hasEmployees: [Person] 14 | 15 | # VAT indentification number - The identifier used in many countries for value added tax purposes. 16 | vatIdentificationNumber: String 17 | 18 | # Name - A term used for identification. 19 | name: String 20 | 21 | # The data property that does not relate any individual to any data value. 22 | bottomDataProperty: [String] 23 | 24 | # The object property that does not relate any two individuals. 25 | bottomObjectProperty: [OwlThing] 26 | 27 | # The property that determines that two given individuals are different. 28 | differentFrom: [OwlThing] 29 | 30 | # The property that determines that two given individuals are equal. 31 | sameAs: [OwlThing] 32 | 33 | # The data property that relates every individual to every data value. 34 | topDataProperty: [String] 35 | 36 | # The object property that relates every two individuals. 37 | topObjectProperty: [OwlThing] 38 | 39 | # The subject is an instance of a class. 40 | type: [RdfsClass] 41 | 42 | # Idiomatic property used for structured values. 43 | value: [RdfsResource] 44 | 45 | # A description of the subject resource. 46 | comment: [String] 47 | 48 | # A human-readable name for the subject. 49 | label: [String] 50 | 51 | # Further information about the subject resource. 52 | seeAlso: [RdfsResource] 53 | 54 | # The defininition of the subject resource. 55 | isDefinedBy: [RdfsResource] 56 | 57 | # A member of the subject resource. 58 | member: [RdfsResource] 59 | 60 | # The property that determines the predicate of an annotated axiom or annotated annotation. 61 | annotatedProperty: [RdfsResource] 62 | 63 | # The property that determines the subject of an annotated axiom or annotated annotation. 64 | annotatedSource: [RdfsResource] 65 | 66 | # The property that determines the object of an annotated axiom or annotated annotation. 67 | annotatedTarget: [RdfsResource] 68 | 69 | # The annotation property that indicates that a given entity has been deprecated. 70 | deprecated: [RdfsResource] 71 | 72 | # The property that determines the collection of members in either a 73 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 74 | members: [RdfList] 75 | 76 | # The annotation property that provides version information for an ontology or another OWL construct. 77 | versionInfo: [RdfsResource] 78 | } 79 | 80 | # Interface for http://foo.com#Company 81 | interface CompanyInterface { 82 | # A unique identifier for the resource. 83 | id: ID 84 | 85 | # Founding year - The year the Company was created. 86 | foundingYear: Int 87 | 88 | # Has CEO - The Person that is the CEO of the Company. 89 | hasCEO: Person 90 | 91 | # Has employees - The Persons that work for this company. 92 | hasEmployees: [Person] 93 | 94 | # VAT indentification number - The identifier used in many countries for value added tax purposes. 95 | vatIdentificationNumber: String 96 | 97 | # Name - A term used for identification. 98 | name: String 99 | 100 | # The data property that does not relate any individual to any data value. 101 | bottomDataProperty: [String] 102 | 103 | # The object property that does not relate any two individuals. 104 | bottomObjectProperty: [OwlThing] 105 | 106 | # The property that determines that two given individuals are different. 107 | differentFrom: [OwlThing] 108 | 109 | # The property that determines that two given individuals are equal. 110 | sameAs: [OwlThing] 111 | 112 | # The data property that relates every individual to every data value. 113 | topDataProperty: [String] 114 | 115 | # The object property that relates every two individuals. 116 | topObjectProperty: [OwlThing] 117 | 118 | # The subject is an instance of a class. 119 | type: [RdfsClass] 120 | 121 | # Idiomatic property used for structured values. 122 | value: [RdfsResource] 123 | 124 | # A description of the subject resource. 125 | comment: [String] 126 | 127 | # A human-readable name for the subject. 128 | label: [String] 129 | 130 | # Further information about the subject resource. 131 | seeAlso: [RdfsResource] 132 | 133 | # The defininition of the subject resource. 134 | isDefinedBy: [RdfsResource] 135 | 136 | # A member of the subject resource. 137 | member: [RdfsResource] 138 | 139 | # The property that determines the predicate of an annotated axiom or annotated annotation. 140 | annotatedProperty: [RdfsResource] 141 | 142 | # The property that determines the subject of an annotated axiom or annotated annotation. 143 | annotatedSource: [RdfsResource] 144 | 145 | # The property that determines the object of an annotated axiom or annotated annotation. 146 | annotatedTarget: [RdfsResource] 147 | 148 | # The annotation property that indicates that a given entity has been deprecated. 149 | deprecated: [RdfsResource] 150 | 151 | # The property that determines the collection of members in either a 152 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 153 | members: [RdfList] 154 | 155 | # The annotation property that provides version information for an ontology or another OWL construct. 156 | versionInfo: [RdfsResource] 157 | } 158 | 159 | # A system for communication. 160 | type Language implements LanguageInterface, ThingInterface, OwlThingInterface, RdfsResourceInterface { 161 | # A unique identifier for the resource. 162 | id: ID 163 | 164 | # Basic words - A few words in that language. 165 | basicWords: [String] 166 | 167 | # Local name - The Language in that Language. 168 | localName: String 169 | 170 | # Name - A term used for identification. 171 | name: String 172 | 173 | # The data property that does not relate any individual to any data value. 174 | bottomDataProperty: [String] 175 | 176 | # The object property that does not relate any two individuals. 177 | bottomObjectProperty: [OwlThing] 178 | 179 | # The property that determines that two given individuals are different. 180 | differentFrom: [OwlThing] 181 | 182 | # The property that determines that two given individuals are equal. 183 | sameAs: [OwlThing] 184 | 185 | # The data property that relates every individual to every data value. 186 | topDataProperty: [String] 187 | 188 | # The object property that relates every two individuals. 189 | topObjectProperty: [OwlThing] 190 | 191 | # The subject is an instance of a class. 192 | type: [RdfsClass] 193 | 194 | # Idiomatic property used for structured values. 195 | value: [RdfsResource] 196 | 197 | # A description of the subject resource. 198 | comment: [String] 199 | 200 | # A human-readable name for the subject. 201 | label: [String] 202 | 203 | # Further information about the subject resource. 204 | seeAlso: [RdfsResource] 205 | 206 | # The defininition of the subject resource. 207 | isDefinedBy: [RdfsResource] 208 | 209 | # A member of the subject resource. 210 | member: [RdfsResource] 211 | 212 | # The property that determines the predicate of an annotated axiom or annotated annotation. 213 | annotatedProperty: [RdfsResource] 214 | 215 | # The property that determines the subject of an annotated axiom or annotated annotation. 216 | annotatedSource: [RdfsResource] 217 | 218 | # The property that determines the object of an annotated axiom or annotated annotation. 219 | annotatedTarget: [RdfsResource] 220 | 221 | # The annotation property that indicates that a given entity has been deprecated. 222 | deprecated: [RdfsResource] 223 | 224 | # The property that determines the collection of members in either a 225 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 226 | members: [RdfList] 227 | 228 | # The annotation property that provides version information for an ontology or another OWL construct. 229 | versionInfo: [RdfsResource] 230 | } 231 | 232 | # Interface for http://foo.com#Language 233 | interface LanguageInterface { 234 | # A unique identifier for the resource. 235 | id: ID 236 | 237 | # Basic words - A few words in that language. 238 | basicWords: [String] 239 | 240 | # Local name - The Language in that Language. 241 | localName: String 242 | 243 | # Name - A term used for identification. 244 | name: String 245 | 246 | # The data property that does not relate any individual to any data value. 247 | bottomDataProperty: [String] 248 | 249 | # The object property that does not relate any two individuals. 250 | bottomObjectProperty: [OwlThing] 251 | 252 | # The property that determines that two given individuals are different. 253 | differentFrom: [OwlThing] 254 | 255 | # The property that determines that two given individuals are equal. 256 | sameAs: [OwlThing] 257 | 258 | # The data property that relates every individual to every data value. 259 | topDataProperty: [String] 260 | 261 | # The object property that relates every two individuals. 262 | topObjectProperty: [OwlThing] 263 | 264 | # The subject is an instance of a class. 265 | type: [RdfsClass] 266 | 267 | # Idiomatic property used for structured values. 268 | value: [RdfsResource] 269 | 270 | # A description of the subject resource. 271 | comment: [String] 272 | 273 | # A human-readable name for the subject. 274 | label: [String] 275 | 276 | # Further information about the subject resource. 277 | seeAlso: [RdfsResource] 278 | 279 | # The defininition of the subject resource. 280 | isDefinedBy: [RdfsResource] 281 | 282 | # A member of the subject resource. 283 | member: [RdfsResource] 284 | 285 | # The property that determines the predicate of an annotated axiom or annotated annotation. 286 | annotatedProperty: [RdfsResource] 287 | 288 | # The property that determines the subject of an annotated axiom or annotated annotation. 289 | annotatedSource: [RdfsResource] 290 | 291 | # The property that determines the object of an annotated axiom or annotated annotation. 292 | annotatedTarget: [RdfsResource] 293 | 294 | # The annotation property that indicates that a given entity has been deprecated. 295 | deprecated: [RdfsResource] 296 | 297 | # The property that determines the collection of members in either a 298 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 299 | members: [RdfList] 300 | 301 | # The annotation property that provides version information for an ontology or another OWL construct. 302 | versionInfo: [RdfsResource] 303 | } 304 | 305 | # The class of OWL individuals. 306 | type OwlThing implements OwlThingInterface, RdfsResourceInterface { 307 | # A unique identifier for the resource. 308 | id: ID 309 | 310 | # The data property that does not relate any individual to any data value. 311 | bottomDataProperty: [String] 312 | 313 | # The object property that does not relate any two individuals. 314 | bottomObjectProperty: [OwlThing] 315 | 316 | # The property that determines that two given individuals are different. 317 | differentFrom: [OwlThing] 318 | 319 | # The property that determines that two given individuals are equal. 320 | sameAs: [OwlThing] 321 | 322 | # The data property that relates every individual to every data value. 323 | topDataProperty: [String] 324 | 325 | # The object property that relates every two individuals. 326 | topObjectProperty: [OwlThing] 327 | 328 | # The subject is an instance of a class. 329 | type: [RdfsClass] 330 | 331 | # Idiomatic property used for structured values. 332 | value: [RdfsResource] 333 | 334 | # A description of the subject resource. 335 | comment: [String] 336 | 337 | # A human-readable name for the subject. 338 | label: [String] 339 | 340 | # Further information about the subject resource. 341 | seeAlso: [RdfsResource] 342 | 343 | # The defininition of the subject resource. 344 | isDefinedBy: [RdfsResource] 345 | 346 | # A member of the subject resource. 347 | member: [RdfsResource] 348 | 349 | # The property that determines the predicate of an annotated axiom or annotated annotation. 350 | annotatedProperty: [RdfsResource] 351 | 352 | # The property that determines the subject of an annotated axiom or annotated annotation. 353 | annotatedSource: [RdfsResource] 354 | 355 | # The property that determines the object of an annotated axiom or annotated annotation. 356 | annotatedTarget: [RdfsResource] 357 | 358 | # The annotation property that indicates that a given entity has been deprecated. 359 | deprecated: [RdfsResource] 360 | 361 | # The property that determines the collection of members in either a 362 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 363 | members: [RdfList] 364 | 365 | # The annotation property that provides version information for an ontology or another OWL construct. 366 | versionInfo: [RdfsResource] 367 | } 368 | 369 | # Interface for http://www.w3.org/2002/07/owl#Thing 370 | interface OwlThingInterface { 371 | # A unique identifier for the resource. 372 | id: ID 373 | 374 | # The data property that does not relate any individual to any data value. 375 | bottomDataProperty: [String] 376 | 377 | # The object property that does not relate any two individuals. 378 | bottomObjectProperty: [OwlThing] 379 | 380 | # The property that determines that two given individuals are different. 381 | differentFrom: [OwlThing] 382 | 383 | # The property that determines that two given individuals are equal. 384 | sameAs: [OwlThing] 385 | 386 | # The data property that relates every individual to every data value. 387 | topDataProperty: [String] 388 | 389 | # The object property that relates every two individuals. 390 | topObjectProperty: [OwlThing] 391 | 392 | # The subject is an instance of a class. 393 | type: [RdfsClass] 394 | 395 | # Idiomatic property used for structured values. 396 | value: [RdfsResource] 397 | 398 | # A description of the subject resource. 399 | comment: [String] 400 | 401 | # A human-readable name for the subject. 402 | label: [String] 403 | 404 | # Further information about the subject resource. 405 | seeAlso: [RdfsResource] 406 | 407 | # The defininition of the subject resource. 408 | isDefinedBy: [RdfsResource] 409 | 410 | # A member of the subject resource. 411 | member: [RdfsResource] 412 | 413 | # The property that determines the predicate of an annotated axiom or annotated annotation. 414 | annotatedProperty: [RdfsResource] 415 | 416 | # The property that determines the subject of an annotated axiom or annotated annotation. 417 | annotatedSource: [RdfsResource] 418 | 419 | # The property that determines the object of an annotated axiom or annotated annotation. 420 | annotatedTarget: [RdfsResource] 421 | 422 | # The annotation property that indicates that a given entity has been deprecated. 423 | deprecated: [RdfsResource] 424 | 425 | # The property that determines the collection of members in either a 426 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 427 | members: [RdfList] 428 | 429 | # The annotation property that provides version information for an ontology or another OWL construct. 430 | versionInfo: [RdfsResource] 431 | } 432 | 433 | # A human being. 434 | type Person implements PersonInterface, ThingInterface, OwlThingInterface, RdfsResourceInterface { 435 | # A unique identifier for the resource. 436 | id: ID 437 | 438 | # Gender - The gender of the Person. False: female, true: male. 439 | gender: Boolean 440 | 441 | # is CEO of company - The Company this Person is the CEO of. 442 | isCEOOfCompany: Company 443 | 444 | # Lucky number - The lucky number of the Person. 445 | luckyNumber: Polymorphic_scalar_float_string 446 | 447 | # Mother tongue - The first Language the Person has been exposed to from birth. 448 | motherTongue: Language 449 | 450 | # Nickname - The nickname of the Person. 451 | nickname: String 452 | 453 | # Speaks. 454 | speaks: [Language] 455 | 456 | # Works for company - The Company this Person works for. 457 | worksForCompany: Company 458 | 459 | # Name - A term used for identification. 460 | name: String 461 | 462 | # The data property that does not relate any individual to any data value. 463 | bottomDataProperty: [String] 464 | 465 | # The object property that does not relate any two individuals. 466 | bottomObjectProperty: [OwlThing] 467 | 468 | # The property that determines that two given individuals are different. 469 | differentFrom: [OwlThing] 470 | 471 | # The property that determines that two given individuals are equal. 472 | sameAs: [OwlThing] 473 | 474 | # The data property that relates every individual to every data value. 475 | topDataProperty: [String] 476 | 477 | # The object property that relates every two individuals. 478 | topObjectProperty: [OwlThing] 479 | 480 | # The subject is an instance of a class. 481 | type: [RdfsClass] 482 | 483 | # Idiomatic property used for structured values. 484 | value: [RdfsResource] 485 | 486 | # A description of the subject resource. 487 | comment: [String] 488 | 489 | # A human-readable name for the subject. 490 | label: [String] 491 | 492 | # Further information about the subject resource. 493 | seeAlso: [RdfsResource] 494 | 495 | # The defininition of the subject resource. 496 | isDefinedBy: [RdfsResource] 497 | 498 | # A member of the subject resource. 499 | member: [RdfsResource] 500 | 501 | # The property that determines the predicate of an annotated axiom or annotated annotation. 502 | annotatedProperty: [RdfsResource] 503 | 504 | # The property that determines the subject of an annotated axiom or annotated annotation. 505 | annotatedSource: [RdfsResource] 506 | 507 | # The property that determines the object of an annotated axiom or annotated annotation. 508 | annotatedTarget: [RdfsResource] 509 | 510 | # The annotation property that indicates that a given entity has been deprecated. 511 | deprecated: [RdfsResource] 512 | 513 | # The property that determines the collection of members in either a 514 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 515 | members: [RdfList] 516 | 517 | # The annotation property that provides version information for an ontology or another OWL construct. 518 | versionInfo: [RdfsResource] 519 | } 520 | 521 | # Interface for http://foo.com#Person 522 | interface PersonInterface { 523 | # A unique identifier for the resource. 524 | id: ID 525 | 526 | # Gender - The gender of the Person. False: female, true: male. 527 | gender: Boolean 528 | 529 | # is CEO of company - The Company this Person is the CEO of. 530 | isCEOOfCompany: Company 531 | 532 | # Lucky number - The lucky number of the Person. 533 | luckyNumber: Polymorphic_scalar_float_string 534 | 535 | # Mother tongue - The first Language the Person has been exposed to from birth. 536 | motherTongue: Language 537 | 538 | # Nickname - The nickname of the Person. 539 | nickname: String 540 | 541 | # Speaks. 542 | speaks: [Language] 543 | 544 | # Works for company - The Company this Person works for. 545 | worksForCompany: Company 546 | 547 | # Name - A term used for identification. 548 | name: String 549 | 550 | # The data property that does not relate any individual to any data value. 551 | bottomDataProperty: [String] 552 | 553 | # The object property that does not relate any two individuals. 554 | bottomObjectProperty: [OwlThing] 555 | 556 | # The property that determines that two given individuals are different. 557 | differentFrom: [OwlThing] 558 | 559 | # The property that determines that two given individuals are equal. 560 | sameAs: [OwlThing] 561 | 562 | # The data property that relates every individual to every data value. 563 | topDataProperty: [String] 564 | 565 | # The object property that relates every two individuals. 566 | topObjectProperty: [OwlThing] 567 | 568 | # The subject is an instance of a class. 569 | type: [RdfsClass] 570 | 571 | # Idiomatic property used for structured values. 572 | value: [RdfsResource] 573 | 574 | # A description of the subject resource. 575 | comment: [String] 576 | 577 | # A human-readable name for the subject. 578 | label: [String] 579 | 580 | # Further information about the subject resource. 581 | seeAlso: [RdfsResource] 582 | 583 | # The defininition of the subject resource. 584 | isDefinedBy: [RdfsResource] 585 | 586 | # A member of the subject resource. 587 | member: [RdfsResource] 588 | 589 | # The property that determines the predicate of an annotated axiom or annotated annotation. 590 | annotatedProperty: [RdfsResource] 591 | 592 | # The property that determines the subject of an annotated axiom or annotated annotation. 593 | annotatedSource: [RdfsResource] 594 | 595 | # The property that determines the object of an annotated axiom or annotated annotation. 596 | annotatedTarget: [RdfsResource] 597 | 598 | # The annotation property that indicates that a given entity has been deprecated. 599 | deprecated: [RdfsResource] 600 | 601 | # The property that determines the collection of members in either a 602 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 603 | members: [RdfList] 604 | 605 | # The annotation property that provides version information for an ontology or another OWL construct. 606 | versionInfo: [RdfsResource] 607 | } 608 | 609 | scalar Polymorphic_scalar_float_string 610 | 611 | type Query { 612 | companies: [Company] 613 | 614 | # Anything you like, by id. Similar to Relay's node field. 615 | thing(id: String = "French"): ThingInterface 616 | } 617 | 618 | # The class of RDF Lists. 619 | type RdfList implements RdfListInterface, RdfsResourceInterface { 620 | # A unique identifier for the resource. 621 | id: ID 622 | 623 | # The first item in the subject RDF list. 624 | first: [RdfsResource] 625 | 626 | # The rest of the subject RDF list after the first item. 627 | rest: [RdfList] 628 | 629 | # The subject is an instance of a class. 630 | type: [RdfsClass] 631 | 632 | # Idiomatic property used for structured values. 633 | value: [RdfsResource] 634 | 635 | # A description of the subject resource. 636 | comment: [String] 637 | 638 | # A human-readable name for the subject. 639 | label: [String] 640 | 641 | # Further information about the subject resource. 642 | seeAlso: [RdfsResource] 643 | 644 | # The defininition of the subject resource. 645 | isDefinedBy: [RdfsResource] 646 | 647 | # A member of the subject resource. 648 | member: [RdfsResource] 649 | 650 | # The property that determines the predicate of an annotated axiom or annotated annotation. 651 | annotatedProperty: [RdfsResource] 652 | 653 | # The property that determines the subject of an annotated axiom or annotated annotation. 654 | annotatedSource: [RdfsResource] 655 | 656 | # The property that determines the object of an annotated axiom or annotated annotation. 657 | annotatedTarget: [RdfsResource] 658 | 659 | # The annotation property that indicates that a given entity has been deprecated. 660 | deprecated: [RdfsResource] 661 | 662 | # The property that determines the collection of members in either a 663 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 664 | members: [RdfList] 665 | 666 | # The annotation property that provides version information for an ontology or another OWL construct. 667 | versionInfo: [RdfsResource] 668 | } 669 | 670 | # Interface for http://www.w3.org/1999/02/22-rdf-syntax-ns#List 671 | interface RdfListInterface { 672 | # A unique identifier for the resource. 673 | id: ID 674 | 675 | # The first item in the subject RDF list. 676 | first: [RdfsResource] 677 | 678 | # The rest of the subject RDF list after the first item. 679 | rest: [RdfList] 680 | 681 | # The subject is an instance of a class. 682 | type: [RdfsClass] 683 | 684 | # Idiomatic property used for structured values. 685 | value: [RdfsResource] 686 | 687 | # A description of the subject resource. 688 | comment: [String] 689 | 690 | # A human-readable name for the subject. 691 | label: [String] 692 | 693 | # Further information about the subject resource. 694 | seeAlso: [RdfsResource] 695 | 696 | # The defininition of the subject resource. 697 | isDefinedBy: [RdfsResource] 698 | 699 | # A member of the subject resource. 700 | member: [RdfsResource] 701 | 702 | # The property that determines the predicate of an annotated axiom or annotated annotation. 703 | annotatedProperty: [RdfsResource] 704 | 705 | # The property that determines the subject of an annotated axiom or annotated annotation. 706 | annotatedSource: [RdfsResource] 707 | 708 | # The property that determines the object of an annotated axiom or annotated annotation. 709 | annotatedTarget: [RdfsResource] 710 | 711 | # The annotation property that indicates that a given entity has been deprecated. 712 | deprecated: [RdfsResource] 713 | 714 | # The property that determines the collection of members in either a 715 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 716 | members: [RdfList] 717 | 718 | # The annotation property that provides version information for an ontology or another OWL construct. 719 | versionInfo: [RdfsResource] 720 | } 721 | 722 | # The class of classes. 723 | type RdfsClass implements RdfsClassInterface, RdfsResourceInterface { 724 | # A unique identifier for the resource. 725 | id: ID 726 | 727 | # The subject is a subclass of a class. 728 | subClassOf: [RdfsClass] 729 | 730 | # The property that determines that two given classes are equivalent, and that is used to specify datatype definitions. 731 | equivalentClass: [RdfsClass] 732 | 733 | # The property that determines the collection of classes or data ranges that build an intersection. 734 | intersectionOf: [RdfList] 735 | 736 | # The property that determines the collection of individuals or data values that build an enumeration. 737 | oneOf: [RdfList] 738 | 739 | # The property that determines the collection of classes or data ranges that build a union. 740 | unionOf: [RdfList] 741 | 742 | # The subject is an instance of a class. 743 | type: [RdfsClass] 744 | 745 | # Idiomatic property used for structured values. 746 | value: [RdfsResource] 747 | 748 | # A description of the subject resource. 749 | comment: [String] 750 | 751 | # A human-readable name for the subject. 752 | label: [String] 753 | 754 | # Further information about the subject resource. 755 | seeAlso: [RdfsResource] 756 | 757 | # The defininition of the subject resource. 758 | isDefinedBy: [RdfsResource] 759 | 760 | # A member of the subject resource. 761 | member: [RdfsResource] 762 | 763 | # The property that determines the predicate of an annotated axiom or annotated annotation. 764 | annotatedProperty: [RdfsResource] 765 | 766 | # The property that determines the subject of an annotated axiom or annotated annotation. 767 | annotatedSource: [RdfsResource] 768 | 769 | # The property that determines the object of an annotated axiom or annotated annotation. 770 | annotatedTarget: [RdfsResource] 771 | 772 | # The annotation property that indicates that a given entity has been deprecated. 773 | deprecated: [RdfsResource] 774 | 775 | # The property that determines the collection of members in either a 776 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 777 | members: [RdfList] 778 | 779 | # The annotation property that provides version information for an ontology or another OWL construct. 780 | versionInfo: [RdfsResource] 781 | } 782 | 783 | # Interface for http://www.w3.org/2000/01/rdf-schema#Class 784 | interface RdfsClassInterface { 785 | # A unique identifier for the resource. 786 | id: ID 787 | 788 | # The subject is a subclass of a class. 789 | subClassOf: [RdfsClass] 790 | 791 | # The property that determines that two given classes are equivalent, and that is used to specify datatype definitions. 792 | equivalentClass: [RdfsClass] 793 | 794 | # The property that determines the collection of classes or data ranges that build an intersection. 795 | intersectionOf: [RdfList] 796 | 797 | # The property that determines the collection of individuals or data values that build an enumeration. 798 | oneOf: [RdfList] 799 | 800 | # The property that determines the collection of classes or data ranges that build a union. 801 | unionOf: [RdfList] 802 | 803 | # The subject is an instance of a class. 804 | type: [RdfsClass] 805 | 806 | # Idiomatic property used for structured values. 807 | value: [RdfsResource] 808 | 809 | # A description of the subject resource. 810 | comment: [String] 811 | 812 | # A human-readable name for the subject. 813 | label: [String] 814 | 815 | # Further information about the subject resource. 816 | seeAlso: [RdfsResource] 817 | 818 | # The defininition of the subject resource. 819 | isDefinedBy: [RdfsResource] 820 | 821 | # A member of the subject resource. 822 | member: [RdfsResource] 823 | 824 | # The property that determines the predicate of an annotated axiom or annotated annotation. 825 | annotatedProperty: [RdfsResource] 826 | 827 | # The property that determines the subject of an annotated axiom or annotated annotation. 828 | annotatedSource: [RdfsResource] 829 | 830 | # The property that determines the object of an annotated axiom or annotated annotation. 831 | annotatedTarget: [RdfsResource] 832 | 833 | # The annotation property that indicates that a given entity has been deprecated. 834 | deprecated: [RdfsResource] 835 | 836 | # The property that determines the collection of members in either a 837 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 838 | members: [RdfList] 839 | 840 | # The annotation property that provides version information for an ontology or another OWL construct. 841 | versionInfo: [RdfsResource] 842 | } 843 | 844 | # The class resource, everything. 845 | type RdfsResource implements RdfsResourceInterface { 846 | # A unique identifier for the resource. 847 | id: ID 848 | 849 | # The subject is an instance of a class. 850 | type: [RdfsClass] 851 | 852 | # Idiomatic property used for structured values. 853 | value: [RdfsResource] 854 | 855 | # A description of the subject resource. 856 | comment: [String] 857 | 858 | # A human-readable name for the subject. 859 | label: [String] 860 | 861 | # Further information about the subject resource. 862 | seeAlso: [RdfsResource] 863 | 864 | # The defininition of the subject resource. 865 | isDefinedBy: [RdfsResource] 866 | 867 | # A member of the subject resource. 868 | member: [RdfsResource] 869 | 870 | # The property that determines the predicate of an annotated axiom or annotated annotation. 871 | annotatedProperty: [RdfsResource] 872 | 873 | # The property that determines the subject of an annotated axiom or annotated annotation. 874 | annotatedSource: [RdfsResource] 875 | 876 | # The property that determines the object of an annotated axiom or annotated annotation. 877 | annotatedTarget: [RdfsResource] 878 | 879 | # The annotation property that indicates that a given entity has been deprecated. 880 | deprecated: [RdfsResource] 881 | 882 | # The property that determines the collection of members in either a 883 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 884 | members: [RdfList] 885 | 886 | # The annotation property that provides version information for an ontology or another OWL construct. 887 | versionInfo: [RdfsResource] 888 | } 889 | 890 | # Interface for http://www.w3.org/2000/01/rdf-schema#Resource 891 | interface RdfsResourceInterface { 892 | # A unique identifier for the resource. 893 | id: ID 894 | 895 | # The subject is an instance of a class. 896 | type: [RdfsClass] 897 | 898 | # Idiomatic property used for structured values. 899 | value: [RdfsResource] 900 | 901 | # A description of the subject resource. 902 | comment: [String] 903 | 904 | # A human-readable name for the subject. 905 | label: [String] 906 | 907 | # Further information about the subject resource. 908 | seeAlso: [RdfsResource] 909 | 910 | # The defininition of the subject resource. 911 | isDefinedBy: [RdfsResource] 912 | 913 | # A member of the subject resource. 914 | member: [RdfsResource] 915 | 916 | # The property that determines the predicate of an annotated axiom or annotated annotation. 917 | annotatedProperty: [RdfsResource] 918 | 919 | # The property that determines the subject of an annotated axiom or annotated annotation. 920 | annotatedSource: [RdfsResource] 921 | 922 | # The property that determines the object of an annotated axiom or annotated annotation. 923 | annotatedTarget: [RdfsResource] 924 | 925 | # The annotation property that indicates that a given entity has been deprecated. 926 | deprecated: [RdfsResource] 927 | 928 | # The property that determines the collection of members in either a 929 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 930 | members: [RdfList] 931 | 932 | # The annotation property that provides version information for an ontology or another OWL construct. 933 | versionInfo: [RdfsResource] 934 | } 935 | 936 | # Interface for http://foo.com#Thing 937 | interface ThingInterface { 938 | # A unique identifier for the resource. 939 | id: ID 940 | 941 | # Name - A term used for identification. 942 | name: String 943 | 944 | # The data property that does not relate any individual to any data value. 945 | bottomDataProperty: [String] 946 | 947 | # The object property that does not relate any two individuals. 948 | bottomObjectProperty: [OwlThing] 949 | 950 | # The property that determines that two given individuals are different. 951 | differentFrom: [OwlThing] 952 | 953 | # The property that determines that two given individuals are equal. 954 | sameAs: [OwlThing] 955 | 956 | # The data property that relates every individual to every data value. 957 | topDataProperty: [String] 958 | 959 | # The object property that relates every two individuals. 960 | topObjectProperty: [OwlThing] 961 | 962 | # The subject is an instance of a class. 963 | type: [RdfsClass] 964 | 965 | # Idiomatic property used for structured values. 966 | value: [RdfsResource] 967 | 968 | # A description of the subject resource. 969 | comment: [String] 970 | 971 | # A human-readable name for the subject. 972 | label: [String] 973 | 974 | # Further information about the subject resource. 975 | seeAlso: [RdfsResource] 976 | 977 | # The defininition of the subject resource. 978 | isDefinedBy: [RdfsResource] 979 | 980 | # A member of the subject resource. 981 | member: [RdfsResource] 982 | 983 | # The property that determines the predicate of an annotated axiom or annotated annotation. 984 | annotatedProperty: [RdfsResource] 985 | 986 | # The property that determines the subject of an annotated axiom or annotated annotation. 987 | annotatedSource: [RdfsResource] 988 | 989 | # The property that determines the object of an annotated axiom or annotated annotation. 990 | annotatedTarget: [RdfsResource] 991 | 992 | # The annotation property that indicates that a given entity has been deprecated. 993 | deprecated: [RdfsResource] 994 | 995 | # The property that determines the collection of members in either a 996 | # owl:AllDifferent, owl:AllDisjointClasses or owl:AllDisjointProperties axiom. 997 | members: [RdfList] 998 | 999 | # The annotation property that provides version information for an ontology or another OWL construct. 1000 | versionInfo: [RdfsResource] 1001 | } 1002 | --------------------------------------------------------------------------------