├── .gitignore ├── LICENSE ├── Procfile ├── README.md ├── db.sqlite3 ├── manage.py ├── mapping ├── mapping_github.ttl ├── mapping_linkedin.ttl └── mapping_tweet.ttl ├── odmtp ├── __init__.py ├── modules │ ├── __init__.py │ ├── mapper.py │ ├── mapper_github_xr2rml.py │ ├── mapper_linkedin_xr2rml.py │ ├── mapper_twitter_xr2rml.py │ ├── tp2query.py │ ├── tp2query_github.py │ ├── tp2query_linkedin.py │ ├── tp2query_twitter.py │ ├── trimmer.py │ ├── trimmer_xr2rml_github.py │ ├── trimmer_xr2rml_linkedin.py │ └── trimmer_xr2rml_twitter.py └── odmtp.py ├── odmtp_tpf_server ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── ontologie ├── github_ontologie.ttl ├── linkedin_ontologie.ttl └── twitter_ontologie.ttl ├── requirements.txt ├── runtime.txt ├── server ├── __init__.py ├── admin.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── tpf ├── __init__.py ├── fragment.py └── tpq.py └── utils ├── __init__.py ├── github_api.py ├── management_token.py ├── rml_closer.py ├── twitter_api.py ├── xr2rml_mapper.py └── xr2rml_mapping.py /.gitignore: -------------------------------------------------------------------------------- 1 | utils/users.json 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # Jupyter Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # SageMath parsed files 81 | *.sage.py 82 | 83 | # dotenv 84 | .env 85 | 86 | # virtualenv 87 | .venv 88 | venv/ 89 | ENV/ 90 | 91 | # Spyder project settings 92 | .spyderproject 93 | .spyproject 94 | 95 | # Rope project settings 96 | .ropeproject 97 | 98 | # mkdocs documentation 99 | /site 100 | 101 | # mypy 102 | .mypy_cache/ 103 | 104 | .DS_Store 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Benjamin MOREAU 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 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn --pythonpath django odmtp_tpf_server.wsgi --log-file - -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ODMTP TPF Server 2 | odmtp-tpf is a Triple Pattern Fragment server using Python, Django and ODMTP. 3 | 4 | ODMTP (On Demand Mapper with Triple pattern matching) enables triple pattern matching over non-RDF datasources. 5 | 6 | ODMTP support inference (see Semantic Reasoner (Inference) section) 7 | 8 | # Online demo 9 | 10 | ODMTP's implemented for Twitter API, Github API and Linkedin API are available online. You can run SPARQL queries using the online TPF client demo: [Here](http://query.linkeddatafragments.org/#datasources=http%3A%2F%2Fodmtp.priloo.univ-nantes.fr%2Ftwitter%2Fextended%2F&query=PREFIX%20it%3A%20%3Chttp%3A%2F%2Fwww.influencetracker.com%2Fontology%23%3E%0A%0ASELECT%20%3Fs%20WHERE%20%7B%0A%20%20%3Fs%20it%3AincludedHashtag%20%22SemanticWeb%22.%0A%7D) for Twitter, [Here](http://query.linkeddatafragments.org/#datasources=http%3A%2F%2Fodmtp.priloo.univ-nantes.fr%2Fgithub%2Fextended%2F&query=PREFIX%20schema%3A%20%3Chttp%3A%2F%2Fschema.org%2F%3E%0A%0ASELECT%20%3Frepo%0AWHERE%20%7B%0A%09%3Frepo%20schema%3Alanguage%20%22Java%22%0A%7D) for Github (limited to 60 request per hour) and [Here](http://odmtp.priloo.univ-nantes.fr/linkedin/authentification/) for your Linkedin profile (you will need to login to access your personal LI profile). 11 | 12 | ODMTP approach is already used on [OpenDataSoft Plateform](https://data.opendatasoft.com) and can be tested [Here](http://query.linkeddatafragments.org/#datasources=https%3A%2F%2Fpublic.opendatasoft.com%2Fapi%2Ftpf%2Froman-emperors%2F&query=PREFIX%20roman%3A%20%3Chttps%3A%2F%2Fpublic.opendatasoft.com%2Fld%2Fontologies%2Froman-emperors%2F%3E%0A%0ASELECT%20%3Fname%20WHERE%20%7B%0A%20%20%3Fs%20roman%3Abirth_cty%20%22Rome%22%5E%5Exsd%3Astring%20.%0A%20%20%3Fs%20roman%3Areign_start%20%3Fdate%20.%0A%20%20%20%20FILTER%20(%3Fdate%20%3E%20%220014-12-31T00%3A00%3A00%2B00%3A00%22%5E%5Exsd%3AdateTime)%0A%20%20%3Fs%20%20roman%3Aname%20%3Fname%20.%0A%7D). 13 | 14 | # Instructions 15 | ## Installation 16 | 17 | #### macOS 18 | You need to install [Homebrew](http://brew.sh/). 19 | 20 | and then install Python 2.7: 21 | ```bash 22 | brew install python 23 | ``` 24 | #### Ubuntu 25 | ``` 26 | sudo apt-get install python-dev python-setuptools 27 | ``` 28 | 29 | ## Dependencies 30 | You need to install dependencies with pip: 31 | ```bash 32 | pip install -r requirements.txt 33 | ``` 34 | 35 | ## Running The Platform 36 | #### macOS & Ubuntu 37 | From `~/odmtp-tpf` run the comand: 38 | ```bash 39 | python manage.py runserver 40 | ``` 41 | 42 | The TPF server should run at: http://127.0.0.1:8000/ 43 | 44 | # Semantic Reasoner (Inference) 45 | RDF data contains explicit and implicit triples that can be inferred using rules described in ontologies. 46 | To support inference, ODMTP use ontologies to materialize implicit triples of mappings (extended mappings). 47 | Each API can be queried using extended mappings at: `http://127.0.0.1:8000/{api}/extended` 48 | Example: http://127.0.0.1:8000/twitter/extended 49 | 50 | However, mappings only contains schema of the corresponding RDF dataset. 51 | Thus, rules that apply on RDF instances cannot be applied on mappings. 52 | 53 | ## Supported rules 54 | 55 | All rules that apply to schema (class and properties) are supported by ODMTP Semantic Reasoner. 56 | 57 | ### Implemented rules 58 | 59 | | Rule Name | if dataset contains ... | ... then add | 60 | |----------------------------------|:---------------------------------------------------------:|------------------------------| 61 | | rdfs2 (domain) | aaa rdfs:domain xxx .
uuu aaa yyy . | uuu rdf:type xxx . | 62 | | rdfs3 (range) | aaa rdfs:range xxx .
uuu aaa vvv . | vvv rdf:type xxx . | 63 | | rdfs5 (subProperty transitivity) | uuu rdfs:subPropertyOf vvv .
vvv rdfs:subPropertyOf xxx . | uuu rdfs:subPropertyOf xxx . | 64 | | rdfs7 (subProperty) | aaa rdfs:subPropertyOf bbb .
uuu aaa yyy . | uuu bbb yyy . | 65 | | rdfs9 (subClassOf) | uuu rdfs:subClassOf xxx .
vvv rdf:type uuu . | vvv rdf:type xxx . | 66 | | rdfs11 (subClassOf transitivity) | uuu rdfs:subClassOf vvv .
vvv rdfs:subClassOf xxx . | uuu rdfs:subClassOf xxx . | 67 | | owl sameAs Class | uuu owl:sameAs xxx .
vvv rdf:type uuu . | vvv rdf:type xxx . | 68 | | owl sameAs Property | aaa owl:sameAs bbb .
uuu aaa yyy . | uuu bbb yyy . | 69 | | owl equivalentClass | uuu owl:equivalentClass xxx .
vvv rdf:type uuu . | vvv rdf:type xxx . | 70 | | owl equivalentProperty | aaa owl:equivalentProperty bbb .
uuu aaa yyy . | uuu bbb yyy . | 71 | 72 | ### Not implemented rules 73 | 74 | Not all supported rules are yet implemented. 75 | Complete list of [RDFS](https://www.w3.org/TR/rdf11-mt/#rdfs-entailment) and [OWL-LD](http://semanticweb.org/OWLLD/#Rules) rules. 76 | 77 | ## Not supported rules 78 | 79 | Rules that applies on instances are not supported by ODMTP Semantic Reasoner. 80 | examples: 81 | 82 | | Rule Name | if data contains ... | ... then add | Comment | 83 | |-----------------------|:-----------------------------------------:|------------------|--------------------------------------------------------------------------------| 84 | | owl-ld eq-rep-subject | subj1 owl:sameAs subj2 .
subj1 aaa obj1 . | subj2 aaa obj1 . | Not supported if one of the two subject
is not defined in ontology or mapping | 85 | | owl-ld eq-rep-object | obj1 owl:sameAs obj2 .
subj1 aaa obj1 . | subj1 aaa obj2 . | Not supported if subject or objects are
not defined in ontology or mapping | 86 | 87 | # Mappings 88 | Mappings are accessible at: `http://127.0.0.1:8000/{api}/mapping` 89 | Example: http://127.0.0.1:8000/twitter/mapping 90 | 91 | Extended mapping are accessible at `http://127.0.0.1:8000/{api}/mapping/extended` 92 | Example: http://127.0.0.1:8000/twitter/mapping/extended 93 | 94 | # Examples of Simple Queries 95 | You can use any Triple Pattern Fragment client: http://linkeddatafragments.org/software/ 96 | to run SPARQL queries over twitter API and github Repo API V3 97 | ## SPARQL queries over Twitter API 98 | You can run this SPARQL query over http://127.0.0.1:8000/twitter/ to retrieve tweets using #iswc2017 hashtag. 99 | ```sparql 100 | PREFIX it: 101 | 102 | SELECT ?s WHERE { 103 | ?s it:includedHashtag "SemanticWeb". 104 | } 105 | ``` 106 | 107 | Retrieve tweets from a specific user. 108 | ```sparql 109 | PREFIX schema: 110 | 111 | SELECT ?s WHERE { 112 | ?s schema:author "NantesTech". 113 | } 114 | ``` 115 | 116 | SPO query to browse tweets 117 | ```sparql 118 | SELECT ?s ?p ?o WHERE { 119 | ?s ?p ?o 120 | } 121 | ``` 122 | 123 | To retrieve a specific tweet by ID 124 | ```sparql 125 | SELECT ?p ?o WHERE { 126 | ?p ?o 127 | } 128 | ``` 129 | 130 | ## SPARQL queries over Github API 131 | You can run this SPARQL query over http://127.0.0.1:8000/github/ to retrieve repositories using Java programming language. 132 | ```sparql 133 | PREFIX schema: 134 | 135 | SELECT ?repo 136 | WHERE { 137 | ?repo schema:language "Java" 138 | } 139 | ``` 140 | 141 | SPO query to browse repositories 142 | ```sparql 143 | SELECT ?s ?p ?o WHERE { 144 | ?s ?p ?o 145 | } 146 | ``` 147 | 148 | # Extras 149 | To understand how ODTMP approach is working, the ISWC 2017 poster is available [here](https://docs.google.com/presentation/d/e/2PACX-1vT7fstdxp9LrqPdYpVpbDopBjBLJB5oUysFDp8iS3Z33MCqk-6Yq-2OrWZuWT1tqyFWLeAYcv2kshXe/embed?). 150 | 151 | This is just a prototype, feel free to optimize it, improve mapping files, work on new api's etc. 152 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/db.sqlite3 -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "odmtp_tpf_server.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /mapping/mapping_github.ttl: -------------------------------------------------------------------------------- 1 | @prefix rr: . 2 | @prefix rml: . 3 | @prefix xrr: . 4 | @prefix schema: . 5 | @prefix rdfs: . 6 | 7 | <#Repo> 8 | xrr:logicalSource [ 9 | xrr:query "https://api.github.com/"; 10 | rml:iterator "$.items.*"; 11 | ]; 12 | rr:subjectMap [ 13 | rr:template "https://github.com/{$.full_name}"; 14 | rr:class schema:Code; 15 | ]; 16 | rr:predicateObjectMap [ 17 | rr:predicate rdfs:label; 18 | rr:objectMap [ xrr:reference "$.name"; ]; 19 | ]; 20 | rr:predicateObjectMap [ 21 | rr:predicate rdfs:comment; 22 | rr:objectMap [ xrr:reference "$.description"; ]; 23 | ]; 24 | rr:predicateObjectMap [ 25 | rr:predicate schema:author; 26 | rr:objectMap [ xrr:reference "$.owner.login"; ]; 27 | ]; 28 | rr:predicateObjectMap [ 29 | rr:predicate schema:dateCreated; 30 | rr:objectMap [ xrr:reference "$.created_at"; ]; 31 | ]; 32 | rr:predicateObjectMap [ 33 | rr:predicate schema:dateModified; 34 | rr:objectMap [ xrr:reference "$.updated_at"; ]; 35 | ]; 36 | rr:predicateObjectMap [ 37 | rr:predicate schema:language; 38 | rr:objectMap [ xrr:reference "$.language"; ]; 39 | ]. 40 | -------------------------------------------------------------------------------- /mapping/mapping_linkedin.ttl: -------------------------------------------------------------------------------- 1 | @prefix rr: . 2 | @prefix rml: . 3 | @prefix xrr: . 4 | @prefix schema: . 5 | @prefix it: . 6 | @prefix foaf: . 7 | @prefix rdfs: . 8 | @prefix dbpedia: . 9 | @prefix ql: . 10 | 11 | <#Profile> rml:logicalSource [ rml:iterator "$.[*]" ; 12 | xrr:query "https://api.linkedin.com/v1/people/" 13 | ] ; 14 | 15 | rr:subjectMap [ 16 | rml:reference "$.publicProfileUrl"; 17 | rr:template "https://www.linkedin.com/search/results/index/?keywords={$.firstName}"; 18 | rr:class schema:Person ; 19 | ]; 20 | 21 | rr:predicateObjectMap [ 22 | rr:predicate rdfs:label; 23 | rr:objectMap [ xrr:reference "$.firstName"; ]; 24 | ]; 25 | 26 | rr:predicateObjectMap [ 27 | rr:predicate rdfs:label; 28 | rr:objectMap [ xrr:reference "$.lastName"; ]; 29 | ]; 30 | 31 | rr:predicateObjectMap [ 32 | rr:predicate schema:givenName ; 33 | rr:objectMap [ xrr:reference "$.firstName" ]; 34 | ], 35 | 36 | [ rr:predicate schema:familyName ; 37 | rr:objectMap [ xrr:reference "$.lastName" ]; 38 | ], 39 | 40 | [rr:objectMap [ rr:parentTriplesMap <#LocationActuelle> ] ; 41 | rr:predicate 42 | ], 43 | 44 | [rr:objectMap [ rr:parentTriplesMap <#Positions> ] ; 45 | rr:predicate 46 | ], 47 | 48 | 49 | [rr:predicate ; 50 | rr:objectMap [ xrr:reference "$.publicProfileUrl" ]; 51 | ], 52 | 53 | [rr:predicate ; 54 | rr:objectMap [ xrr:reference "$.siteStandardProfileRequest" ]; 55 | ], 56 | 57 | [rr:predicate dbpedia:number ; 58 | rr:objectMap [ xrr:reference "$.numConnections" ]; 59 | ], 60 | 61 | [rr:predicate ; 62 | rr:objectMap [ xrr:reference "$.pictureUrl" ]; 63 | ]. 64 | 65 | <#LocationActuelle> rml:logicalSource [ rml:iterator "$.[*]" ; 66 | xrr:query "https://api.linkedin.com/v1/people/"] ; 67 | 68 | rr:subjectMap [ 69 | rr:template "http://dbpedia.org/resource/{$.location.name}"; 70 | rr:class dbpedia:City ; 71 | ]; 72 | 73 | rr:predicateObjectMap [ 74 | rr:predicate rdfs:label; 75 | rr:objectMap [ xrr:reference "$.location.name"; ]; 76 | ]; 77 | 78 | rr:predicateObjectMap [ 79 | rr:objectMap [ rr:parentTriplesMap <#Country> ] ; 80 | rr:predicate 81 | ]; 82 | 83 | rr:predicateObjectMap [ 84 | rr:predicate dbpedia:place ; 85 | rr:objectMap [ xrr:reference "$.location.name" ]; 86 | ]. 87 | 88 | <#Country> rml:logicalSource [ rml:iterator "$.[*]" ; 89 | xrr:query "https://api.linkedin.com/v1/people/" 90 | ] ; 91 | 92 | rr:subjectMap [ 93 | rr:template "http://dbpedia.org/resource/{$.location.country.code}"; 94 | rr:class dbpedia:Country ; 95 | ]; 96 | 97 | rr:predicateObjectMap [ 98 | rr:predicate rdfs:label; 99 | rr:objectMap [ xrr:reference "$.location.country.code"; ]; 100 | ]; 101 | 102 | rr:predicateObjectMap [ 103 | rr:predicate ; 104 | rr:objectMap [ xrr:reference "$.location.country.code" ]; 105 | ]. 106 | 107 | <#Positions> rml:logicalSource [ rml:iterator "$.[*].positions.values.[*]" ; 108 | xrr:query "https://api.linkedin.com/v1/people/" 109 | ] ; 110 | 111 | rr:subjectMap [ 112 | rr:template "https://linkedin.com/Positions/{$.[*].positions.values.[*].title}"; 113 | rr:class ; 114 | ]; 115 | 116 | rr:predicateObjectMap [ 117 | rr:predicate rdfs:label; 118 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].title"; ]; 119 | ]; 120 | 121 | rr:predicateObjectMap [ 122 | rr:objectMap [ rr:parentTriplesMap <#Company> ] ; 123 | rr:predicate 124 | ]; 125 | 126 | rr:predicateObjectMap [ 127 | rr:objectMap [ rr:parentTriplesMap <#LocationCompany> ] ; 128 | rr:predicate 129 | ]; 130 | 131 | rr:predicateObjectMap [ 132 | rr:predicate schema:identifier ; 133 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].id" ]; 134 | ]; 135 | 136 | rr:predicateObjectMap [ 137 | rr:predicate schema:jobTitle ; 138 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].title" ]; 139 | ]; 140 | 141 | rr:predicateObjectMap [ 142 | rr:predicate dbpedia:month ; 143 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].month" ]; 144 | ]; 145 | 146 | rr:predicateObjectMap [ 147 | rr:predicate dbpedia:year ; 148 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].year" ]; 149 | ]. 150 | 151 | <#Company> rml:logicalSource [ rml:iterator "$.[*].positions.values.[*].company" ; 152 | xrr:query "https://api.linkedin.com/v1/people/" 153 | ] ; 154 | 155 | rr:subjectMap [ 156 | rr:template "http://dbpedia.org/resource/{$.[*].positions.values.[*].company.name}"; 157 | rr:class dbpedia:Company ; 158 | ]; 159 | 160 | rr:predicateObjectMap [ 161 | rr:predicate rdfs:label; 162 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].company.name"; ]; 163 | ]; 164 | 165 | rr:predicateObjectMap [ 166 | rr:predicate schema:identifier ; 167 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].company.id" ]; 168 | ]; 169 | rr:predicateObjectMap [ 170 | rr:predicate dbpedia:industry ; 171 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].company.industry" ]; 172 | ]; 173 | 174 | rr:predicateObjectMap [ 175 | rr:predicate schema:description ; 176 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].company.type" ]; 177 | ]; 178 | 179 | rr:predicateObjectMap [ 180 | rr:predicate dbpedia:numberOfEmployees ; 181 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].company.size" ]; 182 | ]; 183 | 184 | rr:predicateObjectMap [ 185 | rr:predicate dbpedia:companyName ; 186 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].company.name" ]; 187 | ]. 188 | 189 | <#LocationCompany> rml:logicalSource [ rml:iterator "$.[*].positions.values.[*].company" ; 190 | xrr:query "https://api.linkedin.com/v1/people/" ] ; 191 | 192 | rr:subjectMap [ 193 | rr:template "http://dbpedia.org/resource/{$.[*].positions.values.[*].location.name}"; 194 | rr:class dbpedia:Place ; 195 | ]; 196 | rr:predicateObjectMap [ 197 | rr:predicate rdfs:label; 198 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].location.name"; ]; 199 | ]; 200 | rr:predicateObjectMap [ 201 | rr:predicate dbpedia:address ; 202 | rr:objectMap [ xrr:reference "$.[*].positions.values.[*].location.name" ]; 203 | ]. 204 | -------------------------------------------------------------------------------- /mapping/mapping_tweet.ttl: -------------------------------------------------------------------------------- 1 | @prefix rr: . 2 | @prefix rml: . 3 | @prefix xrr: . 4 | @prefix schema: . 5 | @prefix it: . 6 | 7 | <#Tweets> 8 | xrr:logicalSource [ 9 | xrr:query "https://api.twitter.com/1.1/"; 10 | rml:iterator "$.statuses.*"; 11 | ]; 12 | rr:subjectMap [ 13 | rr:template "https://twitter.com/statuses/{$.id_str}"; 14 | rr:class schema:SocialMediaPosting; 15 | ]; 16 | rr:predicateObjectMap [ 17 | rr:predicate schema:articleBody; 18 | rr:objectMap [ xrr:reference "$.text"; ]; 19 | ]; 20 | rr:predicateObjectMap [ 21 | rr:predicate schema:author; 22 | rr:objectMap [ xrr:reference "$.user.screen_name"; ]; 23 | ]; 24 | rr:predicateObjectMap [ 25 | rr:predicate schema:dateCreated; 26 | rr:objectMap [ xrr:reference "$.created_at"; ]; 27 | ]; 28 | rr:predicateObjectMap [ 29 | rr:predicate it:includedHashtag; 30 | rr:objectMap [ xrr:reference "$.entities.hashtags.[*].text"; ]; 31 | ]; 32 | rr:predicateObjectMap [ 33 | rr:predicate it:includedUrl; 34 | rr:objectMap [ xrr:reference "$.entities.urls.[*].expanded_url"; ]; 35 | ]. 36 | -------------------------------------------------------------------------------- /odmtp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/odmtp/__init__.py -------------------------------------------------------------------------------- /odmtp/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/odmtp/modules/__init__.py -------------------------------------------------------------------------------- /odmtp/modules/mapper.py: -------------------------------------------------------------------------------- 1 | class Mapper(object): 2 | 3 | def result_set_2_rdf(self, result_set, reduced_mapping, fragment): 4 | raise NotImplementedError() 5 | -------------------------------------------------------------------------------- /odmtp/modules/mapper_github_xr2rml.py: -------------------------------------------------------------------------------- 1 | from jsonpath_rw import parse 2 | from rdflib import URIRef, Literal 3 | 4 | from odmtp.modules.mapper import Mapper 5 | 6 | 7 | class MapperGithubXr2rml(Mapper): 8 | 9 | def result_set_2_rdf(self, result_set, reduced_mapping, fragment): 10 | for repo in result_set: 11 | for s, p, o in reduced_mapping.mapping: 12 | subject = s 13 | obj = o 14 | splited_subject = subject.split('{') 15 | subject_prefix = splited_subject[0] 16 | subject_jsonpath = parse(splited_subject[1].split('}')[0]) 17 | subject_values = [match.value for match in subject_jsonpath.find(repo)] 18 | if '$.' in obj: 19 | object_jsonpath = parse(obj.split('{')[0].split('}')[0]) 20 | object_values = [match.value for match in object_jsonpath.find(repo)] 21 | for object_value in object_values: 22 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, subject_values[0])), p, Literal(object_value)) 23 | else: 24 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, subject_values[0])), p, obj) 25 | -------------------------------------------------------------------------------- /odmtp/modules/mapper_linkedin_xr2rml.py: -------------------------------------------------------------------------------- 1 | from jsonpath_rw import parse 2 | from rdflib import URIRef, Literal 3 | from urllib import quote 4 | 5 | from odmtp.modules.mapper import Mapper 6 | 7 | 8 | class MapperlinkedinXr2rml(Mapper): 9 | 10 | def result_set_2_rdf(self, result_set, reduced_mapping, fragment): 11 | for s, p, o in reduced_mapping.mapping: 12 | subject = s 13 | obj = o 14 | splited_subject = subject.split('{') 15 | subject_prefix = splited_subject[0] 16 | subject_jsonpath = parse(splited_subject[1].split('}')[0]) 17 | subject_values = [match.value for match in subject_jsonpath.find(result_set)] 18 | if '$.' in obj: 19 | if 'http' in obj: 20 | splited_object = obj.split('{') 21 | object_prefix = splited_object[0] 22 | object_jsonpath = parse(splited_object[1].split('}')[0]) 23 | object_values = [match.value for match in object_jsonpath.find(result_set)] 24 | for object_value in object_values: 25 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, quote(subject_values[0].encode('utf8')))), p, URIRef("%s%s" % (object_prefix, quote(object_values[0].encode('utf8'))))) 26 | else: 27 | object_jsonpath = parse(obj.split('{')[0].split('}')[0]) 28 | object_values = [match.value for match in object_jsonpath.find(result_set)] 29 | for object_value in object_values: 30 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, quote(subject_values[0].encode('utf8')))), p, Literal(object_value)) 31 | else: 32 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, quote(subject_values[0].encode('utf8')))), p, obj) 33 | -------------------------------------------------------------------------------- /odmtp/modules/mapper_twitter_xr2rml.py: -------------------------------------------------------------------------------- 1 | from jsonpath_rw import parse 2 | from rdflib import URIRef, Literal 3 | 4 | from odmtp.modules.mapper import Mapper 5 | 6 | 7 | class MapperTwitterXr2rml(Mapper): 8 | 9 | def result_set_2_rdf(self, result_set, reduced_mapping, fragment): 10 | for tweet in result_set: 11 | for s, p, o in reduced_mapping.mapping: 12 | subject = s 13 | obj = o 14 | splited_subject = subject.split('{') 15 | subject_prefix = splited_subject[0] 16 | subject_jsonpath = parse(splited_subject[1].split('}')[0]) 17 | subject_values = [match.value for match in subject_jsonpath.find(tweet)] 18 | if '$.' in obj: 19 | object_jsonpath = parse(obj.split('{')[0].split('}')[0]) 20 | object_values = [match.value for match in object_jsonpath.find(tweet)] 21 | for object_value in object_values: 22 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, subject_values[0])), p, Literal(object_value)) 23 | else: 24 | fragment.add_data_triple(URIRef("%s%s" % (subject_prefix, subject_values[0])), p, obj) 25 | -------------------------------------------------------------------------------- /odmtp/modules/tp2query.py: -------------------------------------------------------------------------------- 1 | class Tp2Query(object): 2 | 3 | def request(self, tpq, reduced_mapping, fragment, extended): 4 | raise NotImplementedError() 5 | 6 | def _frament_fill_meta(self, tpq, fragment): 7 | raise NotImplementedError() 8 | -------------------------------------------------------------------------------- /odmtp/modules/tp2query_github.py: -------------------------------------------------------------------------------- 1 | from rdflib import URIRef, Literal, Namespace, BNode, RDF, XSD 2 | from urllib import urlencode 3 | from urlparse import urlparse 4 | 5 | from utils.github_api import GithubApi 6 | from odmtp.modules.tp2query import Tp2Query 7 | 8 | 9 | REPO_SEARCH = "search/repositories" 10 | REPOS = "repositories" 11 | 12 | # Associate key of the JSON result set with github query qualifiers. 13 | # see https://help.github.com/articles/searching-repositories 14 | GITHUB_QUALIFIERS = { 15 | '$.full_name': '%s in:full_name', 16 | '$.description': '%s in:description', 17 | '$.name': 'name:%s', 18 | '$.owner.login': 'user:%s', 19 | '$.created_at': 'created:%s', 20 | '$.updated_at': 'pushed:%s', 21 | '$.language': 'language:%s' 22 | } 23 | 24 | REPO_PER_PAGE = 5 25 | TPF_URL = '%s://%s/github/%s' 26 | 27 | 28 | class Tp2QueryGithub(Tp2Query): 29 | 30 | def request(self, tpq, reduced_mapping, fragment, request, extended): 31 | tpf_url = urlparse(request.build_absolute_uri()) 32 | tpf_url = TPF_URL % (tpf_url.scheme, tpf_url.netloc, 'extended/') if extended else TPF_URL % (tpf_url.scheme, tpf_url.netloc, '') 33 | last_result = False 34 | result_set = None 35 | number_of_triples_per_repo = len(reduced_mapping.mapping) 36 | query = '' 37 | query_parameters = {} 38 | github = GithubApi() 39 | for subject_prefix in reduced_mapping.logical_sources: 40 | if tpq.subject is None or tpq.subject.startswith(subject_prefix): 41 | query_url = reduced_mapping.logical_sources[subject_prefix]['query'] 42 | if tpq.subject is None and tpq.obj is None: 43 | query = "e" 44 | else: 45 | if tpq.subject: 46 | full_name = tpq.subject.rpartition('/')[2] 47 | query = "%s %s" % (query, GITHUB_QUALIFIERS['$.full_name'] % full_name) 48 | last_result = True 49 | if tpq.predicate: 50 | if tpq.obj: 51 | for s, p, o in reduced_mapping.mapping: 52 | if '%s' % o in GITHUB_QUALIFIERS: 53 | query = "%s %s" % (query, GITHUB_QUALIFIERS['%s' % o] % '%s' % tpq.obj) 54 | else: 55 | query = "%s %s" % (query, '%s' % tpq.obj) 56 | query_url = "%s%s" % (query_url, REPO_SEARCH) 57 | query_parameters['q'] = query 58 | query_parameters['page'] = tpq.page 59 | query_parameters['per_page'] = REPO_PER_PAGE 60 | parameters = "?%s" % urlencode(query_parameters) 61 | result_set = github.request("%s%s" % (query_url, parameters)) 62 | total_count = result_set['total_count'] 63 | result_set = result_set['items'] 64 | if (tpq.page * REPO_PER_PAGE) >= total_count: 65 | last_result = True 66 | total_nb_triples = total_count * number_of_triples_per_repo 67 | nb_triple_per_page = REPO_PER_PAGE * number_of_triples_per_repo 68 | self._frament_fill_meta(tpq, fragment, last_result, total_nb_triples, nb_triple_per_page, request, tpf_url, query_url) 69 | return result_set 70 | 71 | def _frament_fill_meta(self, tpq, fragment, last_result, total_nb_triples, nb_triple_per_page, request, tpf_url, query_url): 72 | meta_graph = self._tpf_uri(tpf_url, 'metadata') 73 | fragment.add_graph(meta_graph) 74 | dataset_base = self._tpf_uri(tpf_url) 75 | source = URIRef(request.build_absolute_uri()) 76 | dataset_template = Literal('%s%s' % (dataset_base, '{?subject,predicate,object}')) 77 | data_graph = self._tpf_uri(tpf_url, 'dataset') 78 | tp_node = BNode('triplePattern') 79 | subject_node = BNode('subject') 80 | predicate_node = BNode('predicate') 81 | object_node = BNode('object') 82 | HYDRA = Namespace("http://www.w3.org/ns/hydra/core#") 83 | VOID = Namespace("http://rdfs.org/ns/void#") 84 | FOAF = Namespace("http://xmlns.com/foaf/0.1/") 85 | DCTERMS = Namespace("http://purl.org/dc/terms/") 86 | PROV = Namespace("http://www.w3.org/ns/prov#") 87 | 88 | fragment.add_meta_quad(meta_graph, FOAF['primaryTopic'], dataset_base, meta_graph) 89 | fragment.add_meta_quad(data_graph, HYDRA['member'], data_graph, meta_graph) 90 | fragment.add_meta_quad(data_graph, RDF.type, VOID['Dataset'], meta_graph) 91 | fragment.add_meta_quad(data_graph, RDF.type, HYDRA['Collection'], meta_graph) 92 | fragment.add_meta_quad(data_graph, VOID['subset'], dataset_base, meta_graph) 93 | fragment.add_meta_quad(data_graph, VOID['uriLookupEndpoint'], dataset_template, meta_graph) 94 | fragment.add_meta_quad(data_graph, HYDRA['search'], tp_node, meta_graph) 95 | fragment.add_meta_quad(tp_node, HYDRA['template'], dataset_template, meta_graph) 96 | fragment.add_meta_quad(tp_node, HYDRA['variableRepresentation'], HYDRA['ExplicitRepresentation'], meta_graph) 97 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], subject_node, meta_graph) 98 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], predicate_node, meta_graph) 99 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], object_node, meta_graph) 100 | fragment.add_meta_quad(subject_node, HYDRA['variable'], Literal("subject"), meta_graph) 101 | fragment.add_meta_quad(subject_node, HYDRA['property'], RDF.subject, meta_graph) 102 | fragment.add_meta_quad(predicate_node, HYDRA['variable'], Literal("predicate"), meta_graph) 103 | fragment.add_meta_quad(predicate_node, HYDRA['property'], RDF.predicate, meta_graph) 104 | fragment.add_meta_quad(object_node, HYDRA['variable'], Literal("object"), meta_graph) 105 | fragment.add_meta_quad(object_node, HYDRA['property'], RDF.object, meta_graph) 106 | 107 | fragment.add_meta_quad(dataset_base, VOID['subset'], source, meta_graph) 108 | fragment.add_meta_quad(source, RDF.type, HYDRA['PartialCollectionView'], meta_graph) 109 | fragment.add_meta_quad(source, DCTERMS['title'], Literal("TPF Github search API v3"), meta_graph) 110 | fragment.add_meta_quad(source, DCTERMS['description'], Literal("Triples from the github repo api v3 matching the pattern {?s=%s, ?p=%s, ?o=%s}" % (tpq.subject, tpq.predicate, tpq.obj)), meta_graph) 111 | fragment.add_meta_quad(source, DCTERMS['source'], data_graph, meta_graph) 112 | fragment.add_meta_quad(source, HYDRA['totalItems'], Literal(total_nb_triples, datatype=XSD.int), meta_graph) 113 | fragment.add_meta_quad(source, VOID['triples'], Literal(total_nb_triples, datatype=XSD.int), meta_graph) 114 | fragment.add_meta_quad(source, HYDRA['itemsPerPage'], Literal(nb_triple_per_page, datatype=XSD.int), meta_graph) 115 | fragment.add_meta_quad(source, HYDRA['first'], self._tpf_url(dataset_base, 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 116 | 117 | fragment.add_meta_quad(source, RDF.type, PROV['Entity'], meta_graph) 118 | fragment.add_meta_quad(source, PROV['wasDerivedFrom'], URIRef(query_url), meta_graph) 119 | fragment.add_meta_quad(source, PROV['wasGeneratedBy'], URIRef("https://github.com/benjimor/odmtp-tpf"), meta_graph) 120 | if tpq.page > 1: 121 | fragment.add_meta_quad(source, HYDRA['previous'], self._tpf_url(dataset_base, tpq.page - 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 122 | if not last_result: 123 | fragment.add_meta_quad(source, HYDRA['next'], self._tpf_url(dataset_base, tpq.page + 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 124 | fragment.add_prefix('twittertpf', Namespace("%s#" % tpf_url[:-1])) 125 | fragment.add_prefix('void', VOID) 126 | fragment.add_prefix('foaf', FOAF) 127 | fragment.add_prefix('hydra', HYDRA) 128 | fragment.add_prefix('purl', Namespace('http://purl.org/dc/terms/')) 129 | fragment.add_prefix('prov', PROV) 130 | 131 | def _tpf_uri(self, tpf_url, tag=None): 132 | if tag is None: 133 | return URIRef(tpf_url) 134 | return URIRef("%s%s" % (tpf_url[:-1], '#%s' % tag)) 135 | 136 | def _tpf_url(self, dataset_base, page, subject, predicate, obj): 137 | subject_parameter = subject if subject else '' 138 | predicate_parameter = predicate if predicate else '' 139 | if obj: 140 | if isinstance(obj, URIRef): 141 | object_parameter = obj 142 | else: 143 | object_parameter = ('"%s"^^%s' % (obj, obj._datatype)) 144 | else: 145 | object_parameter = '' 146 | parameters = {'page': page, 'subject': subject_parameter, 'predicate': predicate_parameter, 'object': object_parameter} 147 | return URIRef("%s?%s" % (dataset_base, urlencode(parameters))) 148 | -------------------------------------------------------------------------------- /odmtp/modules/tp2query_linkedin.py: -------------------------------------------------------------------------------- 1 | from rdflib import URIRef, Literal, Namespace, BNode, RDF, XSD 2 | from urllib import urlencode 3 | from urlparse import urlparse 4 | 5 | 6 | from odmtp.modules.tp2query import Tp2Query 7 | from linkedin import linkedin 8 | 9 | import ipware 10 | import json 11 | from utils.management_token import USERS_FILE_PATH, linkedin_verification_ip_token_date 12 | 13 | 14 | BASE_QUERY = 'filter:safe' 15 | 16 | TPF_URL = '%s://%s/linkedin/%s' 17 | 18 | LAST_PAGE = 1 19 | 20 | 21 | class Tp2QueryLinkedin(Tp2Query): 22 | 23 | def request(self, tpq, reduced_mapping, fragment, request, extended): 24 | tpf_url = urlparse(request.build_absolute_uri()) 25 | tpf_url = TPF_URL % (tpf_url.scheme, tpf_url.netloc, 'extended/') if extended else TPF_URL % (tpf_url.scheme, tpf_url.netloc, '') 26 | validiteToken = linkedin_verification_ip_token_date(request) 27 | result_set = None 28 | last_result = True 29 | total_nb_triples = len(reduced_mapping.mapping) 30 | if validiteToken: 31 | client_ip, is_routable = ipware.get_client_ip(request) 32 | json_data = open(USERS_FILE_PATH, 'r') 33 | users = json.load(json_data) 34 | ACCESS_TOKEN = users[client_ip]['token'] 35 | application = linkedin.LinkedInApplication(token=ACCESS_TOKEN) 36 | result_set = application.get_profile(selectors=['id', 'first-name', 'last-name', 'location', 'positions', 'num-connections', 'picture-url', 'educations', 'public-profile-url']) 37 | else: 38 | raise ValueError("Not authentified, go to: linkedin/authentification/") 39 | self._frament_fill_meta(tpq, fragment, last_result, total_nb_triples, total_nb_triples, request, tpf_url) 40 | return result_set 41 | 42 | def _frament_fill_meta(self, tpq, fragment, last_result, total_nb_triples, nb_triple_per_page, request, tpf_url): 43 | meta_graph = self._tpf_uri(tpf_url, 'metadata') 44 | fragment.add_graph(meta_graph) 45 | dataset_base = self._tpf_uri(tpf_url) 46 | source = URIRef(request.build_absolute_uri()) 47 | dataset_template = Literal('%s%s' % (dataset_base, '{?subject,predicate,object}')) 48 | data_graph = self._tpf_uri(tpf_url, 'dataset') 49 | tp_node = BNode('triplePattern') 50 | subject_node = BNode('subject') 51 | predicate_node = BNode('predicate') 52 | object_node = BNode('object') 53 | 54 | HYDRA = Namespace("http://www.w3.org/ns/hydra/core#") 55 | VOID = Namespace("http://rdfs.org/ns/void#") 56 | FOAF = Namespace("http://xmlns.com/foaf/0.1/") 57 | DCTERMS = Namespace("http://purl.org/dc/terms/") 58 | PROV = Namespace("http://www.w3.org/ns/prov#") 59 | 60 | fragment.add_meta_quad(meta_graph, FOAF['primaryTopic'], dataset_base, meta_graph) 61 | fragment.add_meta_quad(data_graph, RDF.type, VOID['Dataset'], meta_graph) 62 | fragment.add_meta_quad(data_graph, RDF.type, HYDRA['Collection'], meta_graph) 63 | fragment.add_meta_quad(data_graph, VOID['subset'], dataset_base, meta_graph) 64 | fragment.add_meta_quad(data_graph, HYDRA['search'], tp_node, meta_graph) 65 | fragment.add_meta_quad(tp_node, HYDRA['template'], dataset_template, meta_graph) 66 | fragment.add_meta_quad(tp_node, HYDRA['variableRepresentation'], HYDRA['ExplicitRepresentation'], meta_graph) 67 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], subject_node, meta_graph) 68 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], predicate_node, meta_graph) 69 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], object_node, meta_graph) 70 | fragment.add_meta_quad(subject_node, HYDRA['variable'], Literal("subject"), meta_graph) 71 | fragment.add_meta_quad(subject_node, HYDRA['property'], RDF.subject, meta_graph) 72 | fragment.add_meta_quad(predicate_node, HYDRA['variable'], Literal("predicate"), meta_graph) 73 | fragment.add_meta_quad(predicate_node, HYDRA['property'], RDF.predicate, meta_graph) 74 | fragment.add_meta_quad(object_node, HYDRA['variable'], Literal("object"), meta_graph) 75 | fragment.add_meta_quad(object_node, HYDRA['property'], RDF.object, meta_graph) 76 | 77 | fragment.add_meta_quad(dataset_base, VOID['subset'], source, meta_graph) 78 | fragment.add_meta_quad(source, RDF.type, HYDRA['PartialCollectionView'], meta_graph) 79 | fragment.add_meta_quad(source, DCTERMS['title'], Literal("TPF Linkedin API"), meta_graph) 80 | fragment.add_meta_quad(source, DCTERMS['description'], Literal("Triples from the linkedin api matching the pattern {?s=%s, ?p=%s, ?o=%s}" % (tpq.subject, tpq.predicate, tpq.obj)), meta_graph) 81 | fragment.add_meta_quad(source, DCTERMS['source'], data_graph, meta_graph) 82 | 83 | fragment.add_meta_quad(source, HYDRA['totalItems'], Literal(total_nb_triples, datatype=XSD.int), meta_graph) 84 | fragment.add_meta_quad(source, VOID['triples'], Literal(total_nb_triples, datatype=XSD.int), meta_graph) 85 | fragment.add_meta_quad(source, HYDRA['itemsPerPage'], Literal(nb_triple_per_page, datatype=XSD.int), meta_graph) 86 | fragment.add_meta_quad(source, HYDRA['first'], self._tpf_url(dataset_base, 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 87 | 88 | fragment.add_meta_quad(source, RDF.type, PROV['Entity'], meta_graph) 89 | fragment.add_meta_quad(source, PROV['wasDerivedFrom'], URIRef("https://api.linkedin.com/v1/"), meta_graph) 90 | fragment.add_meta_quad(source, PROV['wasGeneratedBy'], URIRef("https://github.com/benjimor/odmtp-tpf"), meta_graph) 91 | if tpq.page > 1: 92 | fragment.add_meta_quad(source, HYDRA['previous'], self._tpf_url(dataset_base, 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 93 | if not last_result: 94 | fragment.add_meta_quad(source, HYDRA['next'], self._tpf_url(dataset_base, 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 95 | fragment.add_prefix('linkedintpf', Namespace("%s#" % tpf_url[:-1])) 96 | fragment.add_prefix('void', VOID) 97 | fragment.add_prefix('foaf', FOAF) 98 | fragment.add_prefix('hydra', HYDRA) 99 | fragment.add_prefix('purl', Namespace('http://purl.org/dc/terms/')) 100 | fragment.add_prefix('prov', PROV) 101 | 102 | def _tpf_uri(self, tpf_url, tag=None): 103 | if tag is None: 104 | return URIRef(tpf_url) 105 | return URIRef("%s%s" % (tpf_url[:-1], '#%s' % tag)) 106 | 107 | def _tpf_url(self, dataset_base, page, subject, predicate, obj): 108 | subject_parameter = subject if subject else '' 109 | predicate_parameter = predicate if predicate else '' 110 | if obj: 111 | if isinstance(obj, URIRef): 112 | object_parameter = obj 113 | else: 114 | object_parameter = ('"%s"^^%s' % (obj, obj._datatype)) 115 | else: 116 | object_parameter = '' 117 | parameters = {'page': page, 'subject': subject_parameter, 'predicate': predicate_parameter, 'object': object_parameter} 118 | return URIRef("%s?%s" % (dataset_base, urlencode(parameters))) 119 | -------------------------------------------------------------------------------- /odmtp/modules/tp2query_twitter.py: -------------------------------------------------------------------------------- 1 | from rdflib import URIRef, Literal, Namespace, BNode, RDF, XSD 2 | from urllib import urlencode 3 | from urlparse import urlparse 4 | 5 | from utils.twitter_api import TwitterApi, API_ENDPOINT 6 | from odmtp.modules.tp2query import Tp2Query 7 | 8 | 9 | TWEET_SEARCH = "search/tweets.json" 10 | TWEET_LOOKUP = "statuses/show/%s.json" 11 | 12 | # Associate key of the JSON result set with twitter query operators. 13 | # see https://dev.twitter.com/rest/public/search 14 | TWITTER_OPERATORS = { 15 | '$.text': '"%s"', 16 | '$.entities.hashtags.[*].text': '#%s', 17 | '$.entities.urls.[*].expanded_url': 'url:%s', 18 | '$.user.screen_name': 'from:%s' 19 | } 20 | 21 | BASE_QUERY = 'filter:safe' 22 | 23 | TWEETS_PER_PAGE = 5 24 | 25 | TPF_URL = '%s://%s/twitter/%s' 26 | 27 | # twitter search API returns top 15000 tweets matching query 28 | # So i set up a limit to count maximum number of result (TWEETS_PER_PAGE * LAST_PAGE) 29 | LAST_PAGE = 5 30 | 31 | 32 | class Tp2QueryTwitter(Tp2Query): 33 | 34 | def request(self, tpq, reduced_mapping, fragment, request, extended): 35 | tpf_url = urlparse(request.build_absolute_uri()) 36 | tpf_url = TPF_URL % (tpf_url.scheme, tpf_url.netloc, 'extended/') if extended else TPF_URL % (tpf_url.scheme, tpf_url.netloc, '') 37 | print tpf_url 38 | last_result = False 39 | result_set = None 40 | query_parameters = {} 41 | number_of_triples_per_tweets = len(reduced_mapping.mapping) 42 | twitter = TwitterApi() 43 | if 'access_token' not in request.COOKIES: 44 | request.COOKIES['access_token'] = twitter.get_access_token() 45 | twitter.set_access_token(request.COOKIES['access_token']) 46 | for subject_prefix in reduced_mapping.logical_sources: 47 | if tpq.subject is None or tpq.subject.startswith(subject_prefix): 48 | query_url = reduced_mapping.logical_sources[subject_prefix]['query'] 49 | if tpq.subject: 50 | tweet_id = tpq.subject.rpartition('/')[2] 51 | query_url = "%s%s" % (query_url, TWEET_LOOKUP % tweet_id) 52 | result_set = twitter.request(query_url) 53 | result_set = [result_set] 54 | last_result = True 55 | total_nb_triples = len(result_set) * number_of_triples_per_tweets 56 | else: 57 | q = BASE_QUERY 58 | if tpq.obj: 59 | if tpq.predicate: 60 | for s, p, o in reduced_mapping.mapping: 61 | if '%s' % o in TWITTER_OPERATORS: 62 | q = "%s %s" % (q, TWITTER_OPERATORS['%s' % o] % '%s' % tpq.obj) 63 | else: 64 | q = "%s %s" % (q, '"%s"' % tpq.obj) 65 | query_parameters['q'] = q 66 | query_parameters['count'] = TWEETS_PER_PAGE 67 | query_url = "%s%s" % (query_url, TWEET_SEARCH) 68 | parameters = "?%s" % urlencode(query_parameters) 69 | for i in range(tpq.page): 70 | result_set = twitter.request("%s%s" % (query_url, parameters)) 71 | if 'next_results' in result_set['search_metadata']: 72 | parameters = result_set['search_metadata']['next_results'] 73 | else: 74 | last_result = True 75 | break 76 | result_set = result_set['statuses'] 77 | if tpq.page >= LAST_PAGE: 78 | last_result = True 79 | total_nb_triples = TWEETS_PER_PAGE * LAST_PAGE * number_of_triples_per_tweets 80 | nb_triple_per_page = TWEETS_PER_PAGE * number_of_triples_per_tweets 81 | self._frament_fill_meta(tpq, fragment, last_result, total_nb_triples, nb_triple_per_page, request, tpf_url) 82 | return result_set 83 | 84 | def _frament_fill_meta(self, tpq, fragment, last_result, total_nb_triples, nb_triple_per_page, request, tpf_url): 85 | meta_graph = self._tpf_uri(tpf_url, 'metadata') 86 | fragment.add_graph(meta_graph) 87 | dataset_base = self._tpf_uri(tpf_url) 88 | source = URIRef(request.build_absolute_uri()) 89 | dataset_template = Literal('%s%s' % (dataset_base, '{?subject,predicate,object}')) 90 | data_graph = self._tpf_uri(tpf_url, 'dataset') 91 | tp_node = BNode('triplePattern') 92 | subject_node = BNode('subject') 93 | predicate_node = BNode('predicate') 94 | object_node = BNode('object') 95 | HYDRA = Namespace("http://www.w3.org/ns/hydra/core#") 96 | VOID = Namespace("http://rdfs.org/ns/void#") 97 | FOAF = Namespace("http://xmlns.com/foaf/0.1/") 98 | DCTERMS = Namespace("http://purl.org/dc/terms/") 99 | PROV = Namespace("http://www.w3.org/ns/prov#") 100 | 101 | fragment.add_meta_quad(meta_graph, FOAF['primaryTopic'], dataset_base, meta_graph) 102 | fragment.add_meta_quad(data_graph, HYDRA['member'], data_graph, meta_graph) 103 | fragment.add_meta_quad(data_graph, RDF.type, VOID['Dataset'], meta_graph) 104 | fragment.add_meta_quad(data_graph, RDF.type, HYDRA['Collection'], meta_graph) 105 | fragment.add_meta_quad(data_graph, VOID['subset'], dataset_base, meta_graph) 106 | fragment.add_meta_quad(data_graph, VOID['uriLookupEndpoint'], dataset_template, meta_graph) 107 | fragment.add_meta_quad(data_graph, HYDRA['search'], tp_node, meta_graph) 108 | fragment.add_meta_quad(tp_node, HYDRA['template'], dataset_template, meta_graph) 109 | fragment.add_meta_quad(tp_node, HYDRA['variableRepresentation'], HYDRA['ExplicitRepresentation'], meta_graph) 110 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], subject_node, meta_graph) 111 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], predicate_node, meta_graph) 112 | fragment.add_meta_quad(tp_node, HYDRA['mapping'], object_node, meta_graph) 113 | fragment.add_meta_quad(subject_node, HYDRA['variable'], Literal("subject"), meta_graph) 114 | fragment.add_meta_quad(subject_node, HYDRA['property'], RDF.subject, meta_graph) 115 | fragment.add_meta_quad(predicate_node, HYDRA['variable'], Literal("predicate"), meta_graph) 116 | fragment.add_meta_quad(predicate_node, HYDRA['property'], RDF.predicate, meta_graph) 117 | fragment.add_meta_quad(object_node, HYDRA['variable'], Literal("object"), meta_graph) 118 | fragment.add_meta_quad(object_node, HYDRA['property'], RDF.object, meta_graph) 119 | 120 | fragment.add_meta_quad(dataset_base, VOID['subset'], source, meta_graph) 121 | fragment.add_meta_quad(source, RDF.type, HYDRA['PartialCollectionView'], meta_graph) 122 | fragment.add_meta_quad(source, DCTERMS['title'], Literal("TPF Twitter search API 1.1"), meta_graph) 123 | fragment.add_meta_quad(source, DCTERMS['description'], Literal("Triples from the twitter api matching the pattern {?s=%s, ?p=%s, ?o=%s}" % (tpq.subject, tpq.predicate, tpq.obj)), meta_graph) 124 | fragment.add_meta_quad(source, DCTERMS['source'], data_graph, meta_graph) 125 | fragment.add_meta_quad(source, HYDRA['totalItems'], Literal(total_nb_triples, datatype=XSD.int), meta_graph) 126 | fragment.add_meta_quad(source, VOID['triples'], Literal(total_nb_triples, datatype=XSD.int), meta_graph) 127 | fragment.add_meta_quad(source, HYDRA['itemsPerPage'], Literal(nb_triple_per_page, datatype=XSD.int), meta_graph) 128 | fragment.add_meta_quad(source, HYDRA['first'], self._tpf_url(dataset_base, 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 129 | 130 | fragment.add_meta_quad(source, RDF.type, PROV['Entity'], meta_graph) 131 | fragment.add_meta_quad(source, PROV['wasDerivedFrom'], URIRef(API_ENDPOINT), meta_graph) 132 | fragment.add_meta_quad(source, PROV['wasGeneratedBy'], URIRef("https://github.com/benjimor/odmtp-tpf"), meta_graph) 133 | if tpq.page > 1: 134 | fragment.add_meta_quad(source, HYDRA['previous'], self._tpf_url(dataset_base, tpq.page - 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 135 | if not last_result: 136 | fragment.add_meta_quad(source, HYDRA['next'], self._tpf_url(dataset_base, tpq.page + 1, tpq.subject, tpq.predicate, tpq.obj), meta_graph) 137 | fragment.add_prefix('twittertpf', Namespace(tpf_url)) 138 | fragment.add_prefix('void', VOID) 139 | fragment.add_prefix('foaf', FOAF) 140 | fragment.add_prefix('hydra', HYDRA) 141 | fragment.add_prefix('purl', Namespace('http://purl.org/dc/terms/')) 142 | fragment.add_prefix('prov', PROV) 143 | 144 | def _tpf_uri(self, tpf_url, tag=None): 145 | if tag is None: 146 | return URIRef(tpf_url) 147 | return URIRef("%s%s" % (tpf_url, tag)) 148 | 149 | def _tpf_url(self, dataset_base, page, subject, predicate, obj): 150 | subject_parameter = subject if subject else '' 151 | predicate_parameter = predicate if predicate else '' 152 | if obj: 153 | if isinstance(obj, URIRef): 154 | object_parameter = obj 155 | else: 156 | object_parameter = ('"%s"^^%s' % (obj, obj._datatype)) 157 | else: 158 | object_parameter = '' 159 | parameters = {'page': page, 'subject': subject_parameter, 'predicate': predicate_parameter, 'object': object_parameter} 160 | return URIRef("%s?%s" % (dataset_base, urlencode(parameters))) 161 | -------------------------------------------------------------------------------- /odmtp/modules/trimmer.py: -------------------------------------------------------------------------------- 1 | from rdflib import URIRef 2 | import copy 3 | 4 | 5 | class Trimmer(object): 6 | 7 | def __init__(self): 8 | self.mapping = None 9 | 10 | def get_reduced_mapping(self, tpq): 11 | reduced_mapping = copy.deepcopy(self.mapping) 12 | self.mapping_triple_pattern_matching(reduced_mapping, tpq) 13 | return reduced_mapping 14 | 15 | def mapping_triple_pattern_matching(self, xr2rml_mapping, tpq): 16 | if tpq.predicate is not None: 17 | xr2rml_mapping.mapping = xr2rml_mapping.mapping & xr2rml_mapping.mapping.triples((None, tpq.predicate, None)) 18 | if tpq.subject is not None: 19 | for s, p, o in xr2rml_mapping.mapping: 20 | subject_prefix = s.split('{')[0] 21 | if not tpq.subject.startswith(subject_prefix): 22 | xr2rml_mapping.mapping.remove((s, p, o)) 23 | if tpq.obj is not None and type(tpq.obj) is URIRef: 24 | object_prefix = tpq.obj.split('{')[0] 25 | for s, p, o in xr2rml_mapping.mapping: 26 | if not tpq.obj.startswith(object_prefix): 27 | xr2rml_mapping.mapping.remove((s, p, o)) 28 | -------------------------------------------------------------------------------- /odmtp/modules/trimmer_xr2rml_github.py: -------------------------------------------------------------------------------- 1 | from utils.xr2rml_mapper import Xr2rmlMapper 2 | from odmtp.modules.trimmer import Trimmer 3 | 4 | 5 | class TrimmerXr2rmlGithub(Trimmer): 6 | 7 | def __init__(self, extended=False): 8 | if extended: 9 | self.mapping = Xr2rmlMapper('./mapping/mapping_github.ttl', './ontologie/github_ontologie.ttl').get_mapping() 10 | else: 11 | self.mapping = Xr2rmlMapper('./mapping/mapping_github.ttl').get_mapping() 12 | -------------------------------------------------------------------------------- /odmtp/modules/trimmer_xr2rml_linkedin.py: -------------------------------------------------------------------------------- 1 | from utils.xr2rml_mapper import Xr2rmlMapper 2 | from odmtp.modules.trimmer import Trimmer 3 | 4 | 5 | class TrimmerXr2rmllinkedin(Trimmer): 6 | 7 | def __init__(self, extended=False): 8 | if extended: 9 | self.mapping = Xr2rmlMapper('./mapping/mapping_linkedin.ttl', './ontologie/linkedin_ontologie.ttl').get_mapping() 10 | else: 11 | self.mapping = Xr2rmlMapper('./mapping/mapping_linkedin.ttl').get_mapping() 12 | -------------------------------------------------------------------------------- /odmtp/modules/trimmer_xr2rml_twitter.py: -------------------------------------------------------------------------------- 1 | from utils.xr2rml_mapper import Xr2rmlMapper 2 | from odmtp.modules.trimmer import Trimmer 3 | 4 | 5 | class TrimmerXr2rmlTwitter(Trimmer): 6 | 7 | def __init__(self, extended=False): 8 | if extended: 9 | self.mapping = Xr2rmlMapper('./mapping/mapping_tweet.ttl', './ontologie/twitter_ontologie.ttl').get_mapping() 10 | else: 11 | self.mapping = Xr2rmlMapper('./mapping/mapping_tweet.ttl').get_mapping() 12 | -------------------------------------------------------------------------------- /odmtp/odmtp.py: -------------------------------------------------------------------------------- 1 | class Odmtp(object): 2 | 3 | def __init__(self, trimmer, tp2query, mapper): 4 | self.trimmer = trimmer 5 | self.tp2query = tp2query 6 | self.mapper = mapper 7 | 8 | def match(self, tpq, fragment, request, extended=False): 9 | reduced_mapping = self.trimmer.get_reduced_mapping(tpq) 10 | result_set = self.tp2query.request(tpq, reduced_mapping, fragment, request, extended) 11 | self.mapper.result_set_2_rdf(result_set, reduced_mapping, fragment) 12 | -------------------------------------------------------------------------------- /odmtp_tpf_server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/odmtp_tpf_server/__init__.py -------------------------------------------------------------------------------- /odmtp_tpf_server/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for odmtrip_tpf_server project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.8.18. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.8/ref/settings/ 11 | """ 12 | 13 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 14 | import os 15 | 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # SECURITY WARNING: don't run with debug turned on in production! 20 | DEBUG = False 21 | 22 | ALLOWED_HOSTS = ['odmtp.herokuapp.com', '127.0.0.1', 'odmtp.priloo.univ-nantes.fr'] 23 | 24 | 25 | # Application definition 26 | 27 | INSTALLED_APPS = ( 28 | 'django.contrib.admin', 29 | 'django.contrib.auth', 30 | 'django.contrib.contenttypes', 31 | 'django.contrib.sessions', 32 | 'django.contrib.messages', 33 | 'django.contrib.staticfiles', 34 | 'django.contrib.sessions.backends.signed_cookies', 35 | 'server' 36 | ) 37 | 38 | MIDDLEWARE_CLASSES = ( 39 | 'django.contrib.sessions.middleware.SessionMiddleware', 40 | 'django.middleware.common.CommonMiddleware', 41 | 'django.middleware.csrf.CsrfViewMiddleware', 42 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 43 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 44 | 'django.contrib.messages.middleware.MessageMiddleware', 45 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 46 | 'django.middleware.security.SecurityMiddleware', 47 | ) 48 | 49 | CACHES = { 50 | 'default': { 51 | 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 52 | 'LOCATION': '127.0.0.1:11211', 53 | } 54 | } 55 | 56 | SESSION_ENGINE = 'django.contrib.sessions.backends.cache' 57 | 58 | ROOT_URLCONF = 'odmtp_tpf_server.urls' 59 | 60 | TEMPLATES = [ 61 | { 62 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 63 | 'DIRS': [], 64 | 'APP_DIRS': True, 65 | 'OPTIONS': { 66 | 'context_processors': [ 67 | 'django.template.context_processors.debug', 68 | 'django.template.context_processors.request', 69 | 'django.contrib.auth.context_processors.auth', 70 | 'django.contrib.messages.context_processors.messages', 71 | ], 72 | }, 73 | }, 74 | ] 75 | 76 | WSGI_APPLICATION = 'odmtp_tpf_server.wsgi.application' 77 | 78 | 79 | # Database 80 | # https://docs.djangoproject.com/en/1.8/ref/settings/#databases 81 | 82 | DATABASES = { 83 | 'default': { 84 | 'ENGINE': 'django.db.backends.sqlite3', 85 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 86 | } 87 | } 88 | 89 | 90 | # Internationalization 91 | # https://docs.djangoproject.com/en/1.8/topics/i18n/ 92 | 93 | LANGUAGE_CODE = 'en-us' 94 | 95 | TIME_ZONE = 'UTC' 96 | 97 | USE_I18N = True 98 | 99 | USE_L10N = True 100 | 101 | USE_TZ = True 102 | 103 | 104 | # Static files (CSS, JavaScript, Images) 105 | # https://docs.djangoproject.com/en/1.8/howto/static-files/ 106 | 107 | STATIC_URL = '/static/' 108 | 109 | try: 110 | from local_settings import * 111 | except ImportError: 112 | pass 113 | -------------------------------------------------------------------------------- /odmtp_tpf_server/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import include, url 2 | from django.contrib import admin 3 | 4 | urlpatterns = [ 5 | url(r'^admin/', include(admin.site.urls)), 6 | url(r'', include('server.urls')), 7 | ] 8 | -------------------------------------------------------------------------------- /odmtp_tpf_server/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for odmtrip_tpf_server project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "odmtp_tpf_server.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /ontologie/github_ontologie.ttl: -------------------------------------------------------------------------------- 1 | @prefix dct: . 2 | @prefix owl: . 3 | @prefix rdf: . 4 | @prefix rdfa: . 5 | @prefix rdfs: . 6 | @prefix schema: . 7 | @prefix xml: . 8 | @prefix xsd: . 9 | 10 | schema:Code a rdfs:Class ; 11 | rdfs:label "Code" ; 12 | schema:sameAs ; 13 | schema:supersededBy schema:SoftwareSourceCode ; 14 | rdfs:comment "Computer programming source code. Example: Full (compile ready) solutions, code snippet samples, scripts, templates." ; 15 | rdfs:subClassOf schema:CreativeWork . 16 | 17 | schema:CreativeWork a rdfs:Class ; 18 | rdfs:label "CreativeWork" ; 19 | dct:source ; 20 | schema:sameAs ; 21 | rdfs:comment "The most generic kind of creative work, including books, movies, photographs, software programs, etc." ; 22 | rdfs:subClassOf schema:Thing . 23 | 24 | schema:Thing a rdfs:Class ; 25 | rdfs:label "Thing" ; 26 | schema:sameAs ; 27 | rdfs:comment "The most generic type of item." . 28 | 29 | schema:Article rdfs:subClassOf schema:CreativeWork . 30 | 31 | schema:Atlas rdfs:subClassOf schema:CreativeWork . 32 | 33 | schema:Blog rdfs:subClassOf schema:CreativeWork . 34 | 35 | schema:Book rdfs:subClassOf schema:CreativeWork . 36 | 37 | schema:Chapter rdfs:subClassOf schema:CreativeWork . 38 | 39 | schema:Claim rdfs:subClassOf schema:CreativeWork . 40 | 41 | schema:Clip rdfs:subClassOf schema:CreativeWork . 42 | 43 | schema:Code rdfs:subClassOf schema:CreativeWork . 44 | 45 | schema:Collection rdfs:subClassOf schema:CreativeWork . 46 | 47 | schema:ComicStory rdfs:subClassOf schema:CreativeWork . 48 | 49 | schema:Conversation rdfs:subClassOf schema:CreativeWork . 50 | 51 | schema:Course rdfs:subClassOf schema:CreativeWork . 52 | 53 | schema:CreativeWorkSeason rdfs:subClassOf schema:CreativeWork . 54 | 55 | schema:CreativeWorkSeries rdfs:subClassOf schema:CreativeWork . 56 | 57 | schema:DataCatalog rdfs:subClassOf schema:CreativeWork . 58 | 59 | schema:Dataset rdfs:subClassOf schema:CreativeWork . 60 | 61 | schema:DefinedTermSet rdfs:subClassOf schema:CreativeWork . 62 | 63 | schema:Diet rdfs:subClassOf schema:CreativeWork . 64 | 65 | schema:DigitalDocument rdfs:subClassOf schema:CreativeWork . 66 | 67 | schema:Episode rdfs:subClassOf schema:CreativeWork . 68 | 69 | schema:ExercisePlan rdfs:subClassOf schema:CreativeWork . 70 | 71 | schema:Game rdfs:subClassOf schema:CreativeWork . 72 | 73 | schema:HowTo rdfs:subClassOf schema:CreativeWork . 74 | 75 | schema:HowToDirection rdfs:subClassOf schema:CreativeWork . 76 | 77 | schema:HowToSection rdfs:subClassOf schema:CreativeWork . 78 | 79 | schema:HowToStep rdfs:subClassOf schema:CreativeWork . 80 | 81 | schema:HowToTip rdfs:subClassOf schema:CreativeWork . 82 | 83 | schema:Legislation rdfs:subClassOf schema:CreativeWork . 84 | 85 | schema:Map rdfs:subClassOf schema:CreativeWork . 86 | 87 | schema:Menu rdfs:subClassOf schema:CreativeWork . 88 | 89 | schema:MenuSection rdfs:subClassOf schema:CreativeWork . 90 | 91 | schema:Message rdfs:subClassOf schema:CreativeWork . 92 | 93 | schema:Movie rdfs:subClassOf schema:CreativeWork . 94 | 95 | schema:MusicComposition rdfs:subClassOf schema:CreativeWork . 96 | 97 | schema:MusicPlaylist rdfs:subClassOf schema:CreativeWork . 98 | 99 | schema:MusicRecording rdfs:subClassOf schema:CreativeWork . 100 | 101 | schema:Painting rdfs:subClassOf schema:CreativeWork . 102 | 103 | schema:Photograph rdfs:subClassOf schema:CreativeWork . 104 | 105 | schema:PublicationIssue rdfs:subClassOf schema:CreativeWork . 106 | 107 | schema:PublicationVolume rdfs:subClassOf schema:CreativeWork . 108 | 109 | schema:Question rdfs:subClassOf schema:CreativeWork . 110 | 111 | schema:Quotation rdfs:subClassOf schema:CreativeWork . 112 | 113 | schema:Sculpture rdfs:subClassOf schema:CreativeWork . 114 | 115 | schema:Season rdfs:subClassOf schema:CreativeWork . 116 | 117 | schema:SoftwareApplication rdfs:subClassOf schema:CreativeWork . 118 | 119 | schema:SoftwareSourceCode rdfs:subClassOf schema:CreativeWork . 120 | 121 | schema:TVSeason rdfs:subClassOf schema:CreativeWork . 122 | 123 | schema:TVSeries rdfs:subClassOf schema:CreativeWork . 124 | 125 | schema:Thesis rdfs:subClassOf schema:CreativeWork . 126 | 127 | schema:VisualArtwork rdfs:subClassOf schema:CreativeWork . 128 | 129 | schema:WebPage rdfs:subClassOf schema:CreativeWork . 130 | 131 | schema:WebPageElement rdfs:subClassOf schema:CreativeWork . 132 | 133 | schema:WebSite rdfs:subClassOf schema:CreativeWork . 134 | 135 | schema:accessMode a rdf:Property ; 136 | rdfs:label "accessMode" ; 137 | dct:source ; 138 | schema:category "issue-1110" ; 139 | schema:domainIncludes schema:CreativeWork ; 140 | schema:rangeIncludes schema:Text ; 141 | schema:sameAs ; 142 | rdfs:comment "The human sensory perceptual system or cognitive faculty through which a person may process or perceive information. Expected values include: auditory, tactile, textual, visual, colorDependent, chartOnVisual, chemOnVisual, diagramOnVisual, mathOnVisual, musicOnVisual, textOnVisual." . 143 | 144 | schema:accessModeSufficient a rdf:Property ; 145 | rdfs:label "accessModeSufficient" ; 146 | dct:source ; 147 | schema:category "issue-1110" ; 148 | schema:domainIncludes schema:CreativeWork ; 149 | schema:rangeIncludes schema:Text ; 150 | schema:sameAs ; 151 | rdfs:comment "A list of single or combined accessModes that are sufficient to understand all the intellectual content of a resource. Expected values include: auditory, tactile, textual, visual." . 152 | 153 | schema:accessibilityAPI a rdf:Property ; 154 | rdfs:label "accessibilityAPI" ; 155 | schema:domainIncludes schema:CreativeWork ; 156 | schema:rangeIncludes schema:Text ; 157 | schema:sameAs ; 158 | rdfs:comment "Indicates that the resource is compatible with the referenced accessibility API (WebSchemas wiki lists possible values)." . 159 | 160 | schema:accessibilityControl a rdf:Property ; 161 | rdfs:label "accessibilityControl" ; 162 | schema:domainIncludes schema:CreativeWork ; 163 | schema:rangeIncludes schema:Text ; 164 | schema:sameAs ; 165 | rdfs:comment "Identifies input methods that are sufficient to fully control the described resource (WebSchemas wiki lists possible values)." . 166 | 167 | schema:accessibilityFeature a rdf:Property ; 168 | rdfs:label "accessibilityFeature" ; 169 | schema:domainIncludes schema:CreativeWork ; 170 | schema:rangeIncludes schema:Text ; 171 | schema:sameAs ; 172 | rdfs:comment "Content features of the resource, such as accessible media, alternatives and supported enhancements for accessibility (WebSchemas wiki lists possible values)." . 173 | 174 | schema:accessibilityHazard a rdf:Property ; 175 | rdfs:label "accessibilityHazard" ; 176 | schema:domainIncludes schema:CreativeWork ; 177 | schema:rangeIncludes schema:Text ; 178 | schema:sameAs ; 179 | rdfs:comment "A characteristic of the described resource that is physiologically dangerous to some users. Related to WCAG 2.0 guideline 2.3 (WebSchemas wiki lists possible values)." . 180 | 181 | schema:accessibilitySummary a rdf:Property ; 182 | rdfs:label "accessibilitySummary" ; 183 | dct:source ; 184 | schema:category "issue-1110" ; 185 | schema:domainIncludes schema:CreativeWork ; 186 | schema:rangeIncludes schema:Text ; 187 | schema:sameAs ; 188 | rdfs:comment "A human-readable summary of specific accessibility features or deficiencies, consistent with the other accessibility metadata but expressing subtleties such as \"short descriptions are present but long descriptions will be needed for non-visual users\" or \"short descriptions are present and no long descriptions are needed.\"" . 189 | 190 | schema:accountablePerson a rdf:Property ; 191 | rdfs:label "accountablePerson" ; 192 | schema:domainIncludes schema:CreativeWork ; 193 | schema:rangeIncludes schema:Person ; 194 | schema:sameAs ; 195 | rdfs:comment "Specifies the Person that is legally accountable for the CreativeWork." . 196 | 197 | schema:actionableFeedbackPolicy schema:rangeIncludes schema:CreativeWork . 198 | 199 | schema:additionalType a rdf:Property ; 200 | rdfs:label "additionalType" ; 201 | schema:domainIncludes schema:Thing ; 202 | schema:rangeIncludes schema:URL ; 203 | schema:sameAs ; 204 | rdfs:comment "An additional type for the item, typically used for adding more specific types from external vocabularies in microdata syntax. This is a relationship between something and a class that the thing is in. In RDFa syntax, it is better to use the native RDFa syntax - the 'typeof' attribute - for multiple types. Schema.org tools may have only weaker understanding of extra types, in particular those defined externally." ; 205 | rdfs:subPropertyOf rdf:type . 206 | 207 | schema:aggregateRating a rdf:Property ; 208 | rdfs:label "aggregateRating" ; 209 | schema:domainIncludes schema:Brand, 210 | schema:CreativeWork, 211 | schema:Event, 212 | schema:Offer, 213 | schema:Organization, 214 | schema:Place, 215 | schema:Product, 216 | schema:Service ; 217 | schema:rangeIncludes schema:AggregateRating ; 218 | schema:sameAs ; 219 | rdfs:comment "The overall rating, based on a collection of reviews or ratings, of the item." . 220 | 221 | schema:alternateName a rdf:Property ; 222 | rdfs:label "alternateName" ; 223 | schema:domainIncludes schema:Thing ; 224 | schema:rangeIncludes schema:Text ; 225 | schema:sameAs ; 226 | rdfs:comment "An alias for the item." . 227 | 228 | schema:alternativeHeadline a rdf:Property ; 229 | rdfs:label "alternativeHeadline" ; 230 | schema:domainIncludes schema:CreativeWork ; 231 | schema:rangeIncludes schema:Text ; 232 | schema:sameAs ; 233 | rdfs:comment "A secondary title of the CreativeWork." . 234 | 235 | schema:appearance schema:rangeIncludes schema:CreativeWork . 236 | 237 | schema:associatedMedia a rdf:Property ; 238 | rdfs:label "associatedMedia" ; 239 | schema:domainIncludes schema:CreativeWork ; 240 | schema:rangeIncludes schema:MediaObject ; 241 | schema:sameAs ; 242 | rdfs:comment "A media object that encodes this CreativeWork. This property is a synonym for encoding." . 243 | 244 | schema:audience a rdf:Property ; 245 | rdfs:label "audience" ; 246 | schema:domainIncludes schema:CreativeWork, 247 | schema:Event, 248 | schema:LodgingBusiness, 249 | schema:PlayAction, 250 | schema:Product, 251 | schema:Service ; 252 | schema:rangeIncludes schema:Audience ; 253 | schema:sameAs ; 254 | rdfs:comment "An intended audience, i.e. a group for whom something was created." . 255 | 256 | schema:audio a rdf:Property ; 257 | rdfs:label "audio" ; 258 | schema:domainIncludes schema:CreativeWork ; 259 | schema:rangeIncludes schema:AudioObject ; 260 | schema:sameAs ; 261 | rdfs:comment "An embedded audio object." . 262 | 263 | schema:author a rdf:Property ; 264 | rdfs:label "author" ; 265 | schema:domainIncludes schema:CreativeWork, 266 | schema:Rating ; 267 | schema:rangeIncludes schema:Organization, 268 | schema:Person ; 269 | schema:sameAs ; 270 | rdfs:comment "The author of this content or rating. Please note that author is special in that HTML 5 provides a special mechanism for indicating authorship via the rel tag. That is equivalent to this and may be used interchangeably." . 271 | 272 | schema:awards a rdf:Property ; 273 | rdfs:label "awards" ; 274 | schema:domainIncludes schema:CreativeWork, 275 | schema:Organization, 276 | schema:Person, 277 | schema:Product ; 278 | schema:rangeIncludes schema:Text ; 279 | schema:sameAs ; 280 | schema:supersededBy schema:award ; 281 | rdfs:comment "Awards won by or for this item." . 282 | 283 | schema:backstory schema:rangeIncludes schema:CreativeWork . 284 | 285 | schema:character a rdf:Property ; 286 | rdfs:label "character" ; 287 | schema:domainIncludes schema:CreativeWork ; 288 | schema:rangeIncludes schema:Person ; 289 | schema:sameAs ; 290 | rdfs:comment "Fictional person connected with a creative work." . 291 | 292 | schema:cheatCode schema:rangeIncludes schema:CreativeWork . 293 | 294 | schema:citation a rdf:Property ; 295 | rdfs:label "citation" ; 296 | schema:domainIncludes schema:CreativeWork ; 297 | schema:rangeIncludes schema:CreativeWork, 298 | schema:Text ; 299 | schema:sameAs ; 300 | rdfs:comment "A citation or reference to another creative work, such as another publication, web page, scholarly article, etc." . 301 | 302 | schema:comment a rdf:Property ; 303 | rdfs:label "comment" ; 304 | schema:domainIncludes schema:CreativeWork, 305 | schema:RsvpAction ; 306 | schema:rangeIncludes schema:Comment ; 307 | schema:sameAs ; 308 | rdfs:comment "Comments, typically from users." . 309 | 310 | schema:commentCount a rdf:Property ; 311 | rdfs:label "commentCount" ; 312 | schema:domainIncludes schema:CreativeWork ; 313 | schema:rangeIncludes schema:Integer ; 314 | schema:sameAs ; 315 | rdfs:comment "The number of comments this CreativeWork (e.g. Article, Question or Answer) has received. This is most applicable to works published in Web sites with commenting system; additional comments may exist elsewhere." . 316 | 317 | schema:contentRating a rdf:Property ; 318 | rdfs:label "contentRating" ; 319 | schema:domainIncludes schema:CreativeWork ; 320 | schema:rangeIncludes schema:Rating, 321 | schema:Text ; 322 | schema:sameAs ; 323 | rdfs:comment "Official rating of a piece of content—for example,'MPAA PG-13'." . 324 | 325 | schema:contentReferenceTime a rdf:Property ; 326 | rdfs:label "contentReferenceTime" ; 327 | dct:source ; 328 | schema:category "issue-1050" ; 329 | schema:domainIncludes schema:CreativeWork ; 330 | schema:isPartOf ; 331 | schema:rangeIncludes schema:DateTime ; 332 | schema:sameAs ; 333 | rdfs:comment "The specific time described by a creative work, for works (e.g. articles, video objects etc.) that emphasise a particular moment within an Event." . 334 | 335 | schema:contributor a rdf:Property ; 336 | rdfs:label "contributor" ; 337 | schema:domainIncludes schema:CreativeWork, 338 | schema:Event ; 339 | schema:rangeIncludes schema:Organization, 340 | schema:Person ; 341 | schema:sameAs ; 342 | rdfs:comment "A secondary contributor to the CreativeWork or Event." . 343 | 344 | schema:copyrightHolder a rdf:Property ; 345 | rdfs:label "copyrightHolder" ; 346 | schema:domainIncludes schema:CreativeWork ; 347 | schema:rangeIncludes schema:Organization, 348 | schema:Person ; 349 | schema:sameAs ; 350 | rdfs:comment "The party holding the legal copyright to the CreativeWork." . 351 | 352 | schema:copyrightYear a rdf:Property ; 353 | rdfs:label "copyrightYear" ; 354 | schema:domainIncludes schema:CreativeWork ; 355 | schema:rangeIncludes schema:Number ; 356 | schema:sameAs ; 357 | rdfs:comment "The year during which the claimed copyright for the CreativeWork was first asserted." . 358 | 359 | schema:correction a rdf:Property ; 360 | rdfs:label "correction" ; 361 | dct:source , 362 | ; 363 | schema:category "issue-1688", 364 | "issue-1950" ; 365 | schema:domainIncludes schema:CreativeWork ; 366 | schema:isPartOf ; 367 | schema:rangeIncludes schema:CorrectionComment, 368 | schema:Text, 369 | schema:URL ; 370 | schema:sameAs ; 371 | rdfs:comment "Indicates a correction to a CreativeWork, either via a CorrectionComment, textually or in another document." . 372 | 373 | schema:correctionsPolicy schema:rangeIncludes schema:CreativeWork . 374 | 375 | schema:creator a rdf:Property ; 376 | rdfs:label "creator" ; 377 | schema:domainIncludes schema:CreativeWork, 378 | schema:UserComments ; 379 | schema:rangeIncludes schema:Organization, 380 | schema:Person ; 381 | schema:sameAs ; 382 | rdfs:comment "The creator/author of this CreativeWork. This is the same as the Author property for CreativeWork." . 383 | 384 | schema:dateCreated a rdf:Property ; 385 | rdfs:label "dateCreated" ; 386 | schema:domainIncludes schema:CreativeWork, 387 | schema:DataFeedItem ; 388 | schema:rangeIncludes schema:Date, 389 | schema:DateTime ; 390 | schema:sameAs ; 391 | rdfs:comment "The date on which the CreativeWork was created or the item was added to a DataFeed." . 392 | 393 | schema:dateModified a rdf:Property ; 394 | rdfs:label "dateModified" ; 395 | schema:domainIncludes schema:CreativeWork, 396 | schema:DataFeedItem ; 397 | schema:rangeIncludes schema:Date, 398 | schema:DateTime ; 399 | schema:sameAs ; 400 | rdfs:comment "The date on which the CreativeWork was most recently modified or when the item's entry was modified within a DataFeed." . 401 | 402 | schema:datePublished a rdf:Property ; 403 | rdfs:label "datePublished" ; 404 | schema:domainIncludes schema:CreativeWork ; 405 | schema:rangeIncludes schema:Date ; 406 | schema:sameAs ; 407 | rdfs:comment "Date of first broadcast/publication." . 408 | 409 | schema:disambiguatingDescription a rdf:Property ; 410 | rdfs:label "disambiguatingDescription" ; 411 | schema:domainIncludes schema:Thing ; 412 | schema:rangeIncludes schema:Text ; 413 | schema:sameAs ; 414 | rdfs:comment "A sub property of description. A short description of the item used to disambiguate from other, similar items. Information from other properties (in particular, name) may be necessary for the description to be useful for disambiguation." ; 415 | rdfs:subPropertyOf schema:description . 416 | 417 | schema:discusses schema:rangeIncludes schema:CreativeWork . 418 | 419 | schema:discussionUrl a rdf:Property ; 420 | rdfs:label "discussionUrl" ; 421 | schema:domainIncludes schema:CreativeWork ; 422 | schema:rangeIncludes schema:URL ; 423 | schema:sameAs ; 424 | rdfs:comment "A link to the page containing the comments of the CreativeWork." . 425 | 426 | schema:diversityPolicy schema:rangeIncludes schema:CreativeWork . 427 | 428 | schema:documentation schema:rangeIncludes schema:CreativeWork . 429 | 430 | schema:editor a rdf:Property ; 431 | rdfs:label "editor" ; 432 | schema:domainIncludes schema:CreativeWork ; 433 | schema:rangeIncludes schema:Person ; 434 | schema:sameAs ; 435 | rdfs:comment "Specifies the Person who edited the CreativeWork." . 436 | 437 | schema:educationalAlignment a rdf:Property ; 438 | rdfs:label "educationalAlignment" ; 439 | schema:domainIncludes schema:CreativeWork ; 440 | schema:rangeIncludes schema:AlignmentObject ; 441 | schema:sameAs ; 442 | rdfs:comment "An alignment to an established educational framework." . 443 | 444 | schema:educationalUse a rdf:Property ; 445 | rdfs:label "educationalUse" ; 446 | schema:domainIncludes schema:CreativeWork ; 447 | schema:rangeIncludes schema:Text ; 448 | schema:sameAs ; 449 | rdfs:comment "The purpose of a work in the context of education; for example, 'assignment', 'group work'." . 450 | 451 | schema:encodesCreativeWork schema:rangeIncludes schema:CreativeWork . 452 | 453 | schema:encodings a rdf:Property ; 454 | rdfs:label "encodings" ; 455 | schema:domainIncludes schema:CreativeWork ; 456 | schema:rangeIncludes schema:MediaObject ; 457 | schema:sameAs ; 458 | schema:supersededBy schema:encoding ; 459 | rdfs:comment "A media object that encodes this CreativeWork." . 460 | 461 | schema:ethicsPolicy schema:rangeIncludes schema:CreativeWork . 462 | 463 | schema:expires a rdf:Property ; 464 | rdfs:label "expires" ; 465 | schema:domainIncludes schema:CreativeWork ; 466 | schema:rangeIncludes schema:Date ; 467 | schema:sameAs ; 468 | rdfs:comment "Date the content expires and is no longer useful or available. For example a VideoObject or NewsArticle whose availability or relevance is time-limited, or a ClaimReview fact check whose publisher wants to indicate that it may no longer be relevant (or helpful to highlight) after some date." . 469 | 470 | schema:fileFormat a rdf:Property ; 471 | rdfs:label "fileFormat" ; 472 | schema:domainIncludes schema:CreativeWork ; 473 | schema:rangeIncludes schema:Text, 474 | schema:URL ; 475 | schema:sameAs ; 476 | schema:supersededBy schema:encodingFormat ; 477 | rdfs:comment "Media type, typically MIME format (see IANA site) of the content e.g. application/zip of a SoftwareApplication binary. In cases where a CreativeWork has several media type representations, 'encoding' can be used to indicate each MediaObject alongside particular fileFormat information. Unregistered or niche file formats can be indicated instead via the most appropriate URL, e.g. defining Web page or a Wikipedia entry." . 478 | 479 | schema:firstAppearance schema:rangeIncludes schema:CreativeWork . 480 | 481 | schema:funder a rdf:Property ; 482 | rdfs:label "funder" ; 483 | schema:domainIncludes schema:CreativeWork, 484 | schema:Event, 485 | schema:MonetaryGrant, 486 | schema:Organization, 487 | schema:Person ; 488 | schema:rangeIncludes schema:Organization, 489 | schema:Person ; 490 | schema:sameAs ; 491 | rdfs:comment "A person or organization that supports (sponsors) something through some kind of financial contribution." ; 492 | rdfs:subPropertyOf schema:sponsor . 493 | 494 | schema:gameTip schema:rangeIncludes schema:CreativeWork . 495 | 496 | schema:genre a rdf:Property ; 497 | rdfs:label "genre" ; 498 | schema:domainIncludes schema:BroadcastChannel, 499 | schema:CreativeWork, 500 | schema:MusicGroup ; 501 | schema:rangeIncludes schema:Text, 502 | schema:URL ; 503 | schema:sameAs ; 504 | rdfs:comment "Genre of the creative work, broadcast channel or group." . 505 | 506 | schema:headline a rdf:Property ; 507 | rdfs:label "headline" ; 508 | schema:domainIncludes schema:CreativeWork ; 509 | schema:rangeIncludes schema:Text ; 510 | schema:sameAs ; 511 | rdfs:comment "Headline of the article." . 512 | 513 | schema:identifier a rdf:Property ; 514 | rdfs:label "identifier" ; 515 | schema:domainIncludes schema:Thing ; 516 | schema:rangeIncludes schema:PropertyValue, 517 | schema:Text, 518 | schema:URL ; 519 | schema:sameAs ; 520 | rdfs:comment "The identifier property represents any kind of identifier for any kind of Thing, such as ISBNs, GTIN codes, UUIDs etc. Schema.org provides dedicated properties for representing many of these, either as textual strings or as URL (URI) links. See background notes for more details." ; 521 | owl:equivalentProperty dct:identifier . 522 | 523 | schema:image a rdf:Property ; 524 | rdfs:label "image" ; 525 | schema:domainIncludes schema:Thing ; 526 | schema:rangeIncludes schema:ImageObject, 527 | schema:URL ; 528 | schema:sameAs ; 529 | rdfs:comment "An image of the item. This can be a URL or a fully described ImageObject." . 530 | 531 | schema:inLanguage a rdf:Property ; 532 | rdfs:label "inLanguage" ; 533 | schema:domainIncludes schema:CommunicateAction, 534 | schema:CreativeWork, 535 | schema:Event, 536 | schema:LinkRole, 537 | schema:WriteAction ; 538 | schema:rangeIncludes schema:Language, 539 | schema:Text ; 540 | schema:sameAs ; 541 | rdfs:comment "The language of the content or performance or used in an action. Please use one of the language codes from the IETF BCP 47 standard. See also availableLanguage." . 542 | 543 | schema:interactionStatistic a rdf:Property ; 544 | rdfs:label "interactionStatistic" ; 545 | schema:domainIncludes schema:CreativeWork ; 546 | schema:rangeIncludes schema:InteractionCounter ; 547 | schema:sameAs ; 548 | rdfs:comment "The number of interactions for the CreativeWork using the WebSite or SoftwareApplication. The most specific child type of InteractionCounter should be used." . 549 | 550 | schema:interactivityType a rdf:Property ; 551 | rdfs:label "interactivityType" ; 552 | schema:domainIncludes schema:CreativeWork ; 553 | schema:rangeIncludes schema:Text ; 554 | schema:sameAs ; 555 | rdfs:comment "The predominant mode of learning supported by the learning resource. Acceptable values are 'active', 'expositive', or 'mixed'." . 556 | 557 | schema:isAccessibleForFree a rdf:Property ; 558 | rdfs:label "isAccessibleForFree" ; 559 | schema:domainIncludes schema:CreativeWork, 560 | schema:Event, 561 | schema:Place, 562 | schema:PublicationEvent ; 563 | schema:rangeIncludes schema:Boolean ; 564 | schema:sameAs ; 565 | rdfs:comment "A flag to signal that the item, event, or place is accessible for free." . 566 | 567 | schema:isBasedOnUrl a rdf:Property ; 568 | rdfs:label "isBasedOnUrl" ; 569 | schema:domainIncludes schema:CreativeWork ; 570 | schema:rangeIncludes schema:CreativeWork, 571 | schema:Product, 572 | schema:URL ; 573 | schema:sameAs ; 574 | schema:supersededBy schema:isBasedOn ; 575 | rdfs:comment "A resource that was used in the creation of this resource. This term can be repeated for multiple sources. For example, http://example.com/great-multiplication-intro.html." . 576 | 577 | schema:isFamilyFriendly a rdf:Property ; 578 | rdfs:label "isFamilyFriendly" ; 579 | schema:domainIncludes schema:CreativeWork ; 580 | schema:rangeIncludes schema:Boolean ; 581 | schema:sameAs ; 582 | rdfs:comment "Indicates whether this content is family friendly." . 583 | 584 | schema:keywords a rdf:Property ; 585 | rdfs:label "keywords" ; 586 | schema:domainIncludes schema:CreativeWork ; 587 | schema:rangeIncludes schema:Text ; 588 | schema:sameAs ; 589 | rdfs:comment "Keywords or tags used to describe this content. Multiple entries in a keywords list are typically delimited by commas." . 590 | 591 | schema:learningResourceType a rdf:Property ; 592 | rdfs:label "learningResourceType" ; 593 | schema:domainIncludes schema:CreativeWork ; 594 | schema:rangeIncludes schema:Text ; 595 | schema:sameAs ; 596 | rdfs:comment "The predominant type or kind characterizing the learning resource. For example, 'presentation', 'handout'." . 597 | 598 | schema:license a rdf:Property ; 599 | rdfs:label "license" ; 600 | schema:domainIncludes schema:CreativeWork ; 601 | schema:rangeIncludes schema:CreativeWork, 602 | schema:URL ; 603 | schema:sameAs ; 604 | rdfs:comment "A license document that applies to this content, typically indicated by URL." . 605 | 606 | schema:locationCreated a rdf:Property ; 607 | rdfs:label "locationCreated" ; 608 | schema:domainIncludes schema:CreativeWork ; 609 | schema:rangeIncludes schema:Place ; 610 | schema:sameAs ; 611 | rdfs:comment "The location where the CreativeWork was created, which may not be the same as the location depicted in the CreativeWork." . 612 | 613 | schema:lyrics schema:rangeIncludes schema:CreativeWork . 614 | 615 | schema:masthead schema:rangeIncludes schema:CreativeWork . 616 | 617 | schema:material a rdf:Property ; 618 | rdfs:label "material" ; 619 | schema:domainIncludes schema:CreativeWork, 620 | schema:Product ; 621 | schema:rangeIncludes schema:Product, 622 | schema:Text, 623 | schema:URL ; 624 | schema:sameAs ; 625 | rdfs:comment "A material that something is made from, e.g. leather, wool, cotton, paper." . 626 | 627 | schema:mentions a rdf:Property ; 628 | rdfs:label "mentions" ; 629 | schema:domainIncludes schema:CreativeWork ; 630 | schema:rangeIncludes schema:Thing ; 631 | schema:sameAs ; 632 | rdfs:comment "Indicates that the CreativeWork contains a reference to, but is not necessarily about a concept." . 633 | 634 | schema:messageAttachment schema:rangeIncludes schema:CreativeWork . 635 | 636 | schema:missionCoveragePrioritiesPolicy schema:rangeIncludes schema:CreativeWork . 637 | 638 | schema:name a rdf:Property ; 639 | rdfs:label "name" ; 640 | schema:domainIncludes schema:Thing ; 641 | schema:rangeIncludes schema:Text ; 642 | schema:sameAs ; 643 | rdfs:comment "The name of the item." ; 644 | rdfs:subPropertyOf ; 645 | owl:equivalentProperty dct:title . 646 | 647 | schema:noBylinesPolicy schema:rangeIncludes schema:CreativeWork . 648 | 649 | schema:offers a rdf:Property ; 650 | rdfs:label "offers" ; 651 | schema:domainIncludes schema:AggregateOffer, 652 | schema:CreativeWork, 653 | schema:Event, 654 | schema:MenuItem, 655 | schema:Product, 656 | schema:Service, 657 | schema:Trip ; 658 | schema:rangeIncludes schema:Offer ; 659 | schema:sameAs ; 660 | rdfs:comment "An offer to provide this item—for example, an offer to sell a product, rent the DVD of a movie, perform a service, or give away tickets to an event." . 661 | 662 | schema:ownershipFundingInfo schema:rangeIncludes schema:CreativeWork . 663 | 664 | schema:position a rdf:Property ; 665 | rdfs:label "position" ; 666 | schema:domainIncludes schema:CreativeWork, 667 | schema:ListItem ; 668 | schema:rangeIncludes schema:Integer, 669 | schema:Text ; 670 | schema:sameAs ; 671 | rdfs:comment "The position of an item in a series or sequence of items." . 672 | 673 | schema:potentialAction a rdf:Property ; 674 | rdfs:label "potentialAction" ; 675 | schema:domainIncludes schema:Thing ; 676 | schema:rangeIncludes schema:Action ; 677 | schema:sameAs ; 678 | rdfs:comment "Indicates a potential Action, which describes an idealized action in which this thing would play an 'object' role." . 679 | 680 | schema:producer a rdf:Property ; 681 | rdfs:label "producer" ; 682 | schema:domainIncludes schema:CreativeWork ; 683 | schema:rangeIncludes schema:Organization, 684 | schema:Person ; 685 | schema:sameAs ; 686 | rdfs:comment "The person or organization who produced the work (e.g. music album, movie, tv/radio series etc.)." . 687 | 688 | schema:provider a rdf:Property ; 689 | rdfs:label "provider" ; 690 | schema:domainIncludes schema:CreativeWork, 691 | schema:Invoice, 692 | schema:ParcelDelivery, 693 | schema:Reservation, 694 | schema:Service, 695 | schema:Trip ; 696 | schema:rangeIncludes schema:Organization, 697 | schema:Person ; 698 | schema:sameAs ; 699 | rdfs:comment "The service provider, service operator, or service performer; the goods producer. Another party (a seller) may offer those services or goods on behalf of the provider. A provider may also serve as the seller." . 700 | 701 | schema:publication a rdf:Property ; 702 | rdfs:label "publication" ; 703 | schema:domainIncludes schema:CreativeWork ; 704 | schema:rangeIncludes schema:PublicationEvent ; 705 | schema:sameAs ; 706 | rdfs:comment "A publication event associated with the item." . 707 | 708 | schema:publisher a rdf:Property ; 709 | rdfs:label "publisher" ; 710 | schema:domainIncludes schema:CreativeWork ; 711 | schema:rangeIncludes schema:Organization, 712 | schema:Person ; 713 | schema:sameAs ; 714 | rdfs:comment "The publisher of the creative work." . 715 | 716 | schema:publisherImprint a rdf:Property ; 717 | rdfs:label "publisherImprint"@en ; 718 | schema:category "Comics"@en ; 719 | schema:domainIncludes schema:CreativeWork ; 720 | schema:isPartOf ; 721 | schema:rangeIncludes schema:Organization ; 722 | schema:sameAs ; 723 | rdfs:comment "The publishing division which published the comic." . 724 | 725 | schema:publishingPrinciples a rdf:Property ; 726 | rdfs:label "publishingPrinciples" ; 727 | schema:domainIncludes schema:CreativeWork, 728 | schema:Organization, 729 | schema:Person ; 730 | schema:rangeIncludes schema:CreativeWork, 731 | schema:URL ; 732 | schema:sameAs ; 733 | rdfs:comment """The publishingPrinciples property indicates (typically via URL) a document describing the editorial principles of an Organization (or individual e.g. a Person writing a blog) that relate to their activities as a publisher, e.g. ethics or diversity policies. When applied to a CreativeWork (e.g. NewsArticle) the principles are those of the party primarily responsible for the creation of the CreativeWork.

734 | 735 | While such policies are most typically expressed in natural language, sometimes related information (e.g. indicating a funder) can be expressed using schema.org terminology.""" . 736 | 737 | schema:recipeInstructions schema:rangeIncludes schema:CreativeWork . 738 | 739 | schema:recordedAt a rdf:Property ; 740 | rdfs:label "recordedAt" ; 741 | schema:domainIncludes schema:CreativeWork ; 742 | schema:inverseOf schema:recordedIn ; 743 | schema:rangeIncludes schema:Event ; 744 | schema:sameAs ; 745 | rdfs:comment "The Event where the CreativeWork was recorded. The CreativeWork may capture all or part of the event." . 746 | 747 | schema:releasedEvent a rdf:Property ; 748 | rdfs:label "releasedEvent" ; 749 | schema:domainIncludes schema:CreativeWork ; 750 | schema:rangeIncludes schema:PublicationEvent ; 751 | schema:sameAs ; 752 | rdfs:comment "The place and time the release was issued, expressed as a PublicationEvent." . 753 | 754 | schema:reviews a rdf:Property ; 755 | rdfs:label "reviews" ; 756 | schema:domainIncludes schema:CreativeWork, 757 | schema:Offer, 758 | schema:Organization, 759 | schema:Place, 760 | schema:Product ; 761 | schema:rangeIncludes schema:Review ; 762 | schema:sameAs ; 763 | schema:supersededBy schema:review ; 764 | rdfs:comment "Review of the item." . 765 | 766 | schema:sameAs a rdf:Property ; 767 | rdfs:label "sameAs" ; 768 | schema:domainIncludes schema:Thing ; 769 | schema:rangeIncludes schema:URL ; 770 | schema:sameAs ; 771 | rdfs:comment "URL of a reference Web page that unambiguously indicates the item's identity. E.g. the URL of the item's Wikipedia page, Wikidata entry, or official website." . 772 | 773 | schema:schemaVersion a rdf:Property ; 774 | rdfs:label "schemaVersion" ; 775 | schema:domainIncludes schema:CreativeWork ; 776 | schema:rangeIncludes schema:Text, 777 | schema:URL ; 778 | schema:sameAs ; 779 | rdfs:comment "Indicates (by URL or string) a particular version of a schema used in some CreativeWork. For example, a document could declare a schemaVersion using an URL such as http://schema.org/version/2.0/ if precise indication of schema version was required by some application." . 780 | 781 | schema:sdDatePublished a rdf:Property ; 782 | rdfs:label "sdDatePublished" ; 783 | dct:source ; 784 | schema:category "issue-1886" ; 785 | schema:domainIncludes schema:CreativeWork ; 786 | schema:isPartOf ; 787 | schema:rangeIncludes schema:Date ; 788 | schema:sameAs ; 789 | rdfs:comment "Indicates the date on which the current structured data was generated / published. Typically used alongside sdPublisher" . 790 | 791 | schema:sdLicense a rdf:Property ; 792 | rdfs:label "sdLicense" ; 793 | dct:source ; 794 | schema:category "issue-1886" ; 795 | schema:domainIncludes schema:CreativeWork ; 796 | schema:isPartOf ; 797 | schema:rangeIncludes schema:CreativeWork, 798 | schema:URL ; 799 | schema:sameAs ; 800 | rdfs:comment "A license document that applies to this structured data, typically indicated by URL." . 801 | 802 | schema:sdPublisher a rdf:Property ; 803 | rdfs:label "sdPublisher" ; 804 | dct:source ; 805 | schema:category "issue-1886" ; 806 | schema:domainIncludes schema:CreativeWork ; 807 | schema:isPartOf ; 808 | schema:rangeIncludes schema:Organization, 809 | schema:Person ; 810 | schema:sameAs ; 811 | rdfs:comment """Indicates the party responsible for generating and publishing the current structured data markup, typically in cases where the structured data is derived automatically from existing published content but published on a different site. For example, student projects and open data initiatives often re-publish existing content with more explicitly structured metadata. The 812 | sdPublisher property helps make such practices more explicit.""" . 813 | 814 | schema:sharedContent schema:rangeIncludes schema:CreativeWork . 815 | 816 | schema:softwareHelp schema:rangeIncludes schema:CreativeWork . 817 | 818 | schema:sourceOrganization a rdf:Property ; 819 | rdfs:label "sourceOrganization" ; 820 | schema:domainIncludes schema:CreativeWork ; 821 | schema:rangeIncludes schema:Organization ; 822 | schema:sameAs ; 823 | rdfs:comment "The Organization on whose behalf the creator was working." . 824 | 825 | schema:spatialCoverage a rdf:Property ; 826 | rdfs:label "spatialCoverage" ; 827 | schema:domainIncludes schema:CreativeWork ; 828 | schema:rangeIncludes schema:Place ; 829 | schema:sameAs ; 830 | rdfs:comment """The spatialCoverage of a CreativeWork indicates the place(s) which are the focus of the content. It is a subproperty of 831 | contentLocation intended primarily for more technical and detailed materials. For example with a Dataset, it indicates 832 | areas that the dataset describes: a dataset of New York weather would have spatialCoverage which was the place: the state of New York.""" ; 833 | rdfs:subPropertyOf schema:contentLocation ; 834 | owl:equivalentProperty dct:spatial . 835 | 836 | schema:step schema:rangeIncludes schema:CreativeWork . 837 | 838 | schema:steps schema:rangeIncludes schema:CreativeWork . 839 | 840 | schema:temporalCoverage a rdf:Property ; 841 | rdfs:label "temporalCoverage" ; 842 | schema:domainIncludes schema:CreativeWork ; 843 | schema:rangeIncludes schema:DateTime, 844 | schema:Text, 845 | schema:URL ; 846 | schema:sameAs ; 847 | rdfs:comment """The temporalCoverage of a CreativeWork indicates the period that the content applies to, i.e. that it describes, either as a DateTime or as a textual string indicating a time period in ISO 8601 time interval format. In 848 | the case of a Dataset it will typically indicate the relevant time period in a precise notation (e.g. for a 2011 census dataset, the year 2011 would be written "2011/2012"). Other forms of content e.g. ScholarlyArticle, Book, TVSeries or TVEpisode may indicate their temporalCoverage in broader terms - textually or via well-known URL. 849 | Written works such as books may sometimes have precise temporal coverage too, e.g. a work set in 1939 - 1945 can be indicated in ISO 8601 interval format format via "1939/1945".

850 | 851 | Open-ended date ranges can be written with ".." in place of the end date. For example, "2015-11/.." indicates a range beginning in November 2015 and with no specified final date. This is tentative and might be updated in future when ISO 8601 is officially updated.""" ; 852 | owl:equivalentProperty dct:temporal . 853 | 854 | schema:text a rdf:Property ; 855 | rdfs:label "text" ; 856 | schema:domainIncludes schema:CreativeWork ; 857 | schema:rangeIncludes schema:Text ; 858 | schema:sameAs ; 859 | rdfs:comment "The textual content of this CreativeWork." . 860 | 861 | schema:thumbnailUrl a rdf:Property ; 862 | rdfs:label "thumbnailUrl" ; 863 | schema:domainIncludes schema:CreativeWork ; 864 | schema:rangeIncludes schema:URL ; 865 | schema:sameAs ; 866 | rdfs:comment "A thumbnail image relevant to the Thing." . 867 | 868 | schema:timeRequired a rdf:Property ; 869 | rdfs:label "timeRequired" ; 870 | schema:domainIncludes schema:CreativeWork ; 871 | schema:rangeIncludes schema:Duration ; 872 | schema:sameAs ; 873 | rdfs:comment "Approximate or typical time it takes to work with or through this learning resource for the typical intended target audience, e.g. 'P30M', 'P1H25M'." . 874 | 875 | schema:translator a rdf:Property ; 876 | rdfs:label "translator" ; 877 | schema:domainIncludes schema:CreativeWork, 878 | schema:Event ; 879 | schema:rangeIncludes schema:Organization, 880 | schema:Person ; 881 | schema:sameAs ; 882 | rdfs:comment "Organization or person who adapts a creative work to different languages, regional differences and technical requirements of a target market, or that translates during some event." . 883 | 884 | schema:typicalAgeRange a rdf:Property ; 885 | rdfs:label "typicalAgeRange" ; 886 | schema:domainIncludes schema:CreativeWork, 887 | schema:Event ; 888 | schema:rangeIncludes schema:Text ; 889 | schema:sameAs ; 890 | rdfs:comment "The typical expected age range, e.g. '7-9', '11-'." . 891 | 892 | schema:unnamedSourcesPolicy schema:rangeIncludes schema:CreativeWork . 893 | 894 | schema:url a rdf:Property ; 895 | rdfs:label "url" ; 896 | schema:domainIncludes schema:Thing ; 897 | schema:rangeIncludes schema:URL ; 898 | schema:sameAs ; 899 | rdfs:comment "URL of the item." . 900 | 901 | schema:verificationFactCheckingPolicy schema:rangeIncludes schema:CreativeWork . 902 | 903 | schema:version a rdf:Property ; 904 | rdfs:label "version" ; 905 | schema:domainIncludes schema:CreativeWork ; 906 | schema:rangeIncludes schema:Number, 907 | schema:Text ; 908 | schema:sameAs ; 909 | rdfs:comment "The version of the CreativeWork embodied by a specified resource." . 910 | 911 | schema:video a rdf:Property ; 912 | rdfs:label "video" ; 913 | schema:domainIncludes schema:CreativeWork ; 914 | schema:rangeIncludes schema:VideoObject ; 915 | schema:sameAs ; 916 | rdfs:comment "An embedded video object." . 917 | 918 | schema:workFeatured schema:rangeIncludes schema:CreativeWork . 919 | 920 | schema:workPerformed schema:rangeIncludes schema:CreativeWork . 921 | 922 | schema:Comment rdfs:subClassOf schema:CreativeWork . 923 | 924 | schema:award a rdf:Property ; 925 | rdfs:label "award" ; 926 | schema:domainIncludes schema:CreativeWork, 927 | schema:Organization, 928 | schema:Person, 929 | schema:Product, 930 | schema:Service ; 931 | schema:rangeIncludes schema:Text ; 932 | schema:sameAs ; 933 | rdfs:comment "An award won by or for this item." . 934 | 935 | schema:contentLocation a rdf:Property ; 936 | rdfs:label "contentLocation" ; 937 | schema:domainIncludes schema:CreativeWork ; 938 | schema:rangeIncludes schema:Place ; 939 | schema:sameAs ; 940 | rdfs:comment "The location depicted or described in the content. For example, the location in a photograph or painting." . 941 | 942 | schema:description a rdf:Property ; 943 | rdfs:label "description" ; 944 | schema:domainIncludes schema:Thing ; 945 | schema:rangeIncludes schema:Text ; 946 | schema:sameAs ; 947 | rdfs:comment "A description of the item." ; 948 | owl:equivalentProperty dct:description . 949 | 950 | schema:encoding a rdf:Property ; 951 | rdfs:label "encoding" ; 952 | schema:domainIncludes schema:CreativeWork ; 953 | schema:rangeIncludes schema:MediaObject ; 954 | schema:sameAs ; 955 | rdfs:comment "A media object that encodes this CreativeWork. This property is a synonym for associatedMedia." . 956 | 957 | schema:encodingFormat a rdf:Property ; 958 | rdfs:label "encodingFormat" ; 959 | schema:domainIncludes schema:CreativeWork, 960 | schema:MediaObject ; 961 | schema:rangeIncludes schema:Text, 962 | schema:URL ; 963 | schema:sameAs ; 964 | rdfs:comment """Media type typically expressed using a MIME format (see IANA site and MDN reference) e.g. application/zip for a SoftwareApplication binary, audio/mpeg for .mp3 etc.).

965 | 966 | In cases where a CreativeWork has several media type representations, encoding can be used to indicate each MediaObject alongside particular encodingFormat information.

967 | 968 | Unregistered or niche encoding and file formats can be indicated instead via the most appropriate URL, e.g. defining Web page or a Wikipedia/Wikidata entry.""" . 969 | 970 | schema:exampleOfWork a rdf:Property ; 971 | rdfs:label "exampleOfWork" ; 972 | dct:source ; 973 | schema:domainIncludes schema:CreativeWork ; 974 | schema:inverseOf schema:workExample ; 975 | schema:rangeIncludes schema:CreativeWork ; 976 | schema:sameAs ; 977 | rdfs:comment "A creative work that this work is an example/instance/realization/derivation of." . 978 | 979 | schema:hasPart a rdf:Property ; 980 | rdfs:label "hasPart" ; 981 | dct:source ; 982 | schema:category "issue-1810" ; 983 | schema:domainIncludes schema:CreativeWork, 984 | schema:Trip ; 985 | schema:inverseOf schema:isPartOf ; 986 | schema:rangeIncludes schema:CreativeWork, 987 | schema:Trip ; 988 | schema:sameAs ; 989 | rdfs:comment "Indicates an item or CreativeWork that is part of this item, or CreativeWork (in some sense)." . 990 | 991 | schema:isBasedOn a rdf:Property ; 992 | rdfs:label "isBasedOn" ; 993 | schema:domainIncludes schema:CreativeWork ; 994 | schema:rangeIncludes schema:CreativeWork, 995 | schema:Product, 996 | schema:URL ; 997 | schema:sameAs ; 998 | rdfs:comment "A resource that was used in the creation of this resource. This term can be repeated for multiple sources. For example, http://example.com/great-multiplication-intro.html." . 999 | 1000 | schema:isPartOf a rdf:Property ; 1001 | rdfs:label "isPartOf" ; 1002 | schema:category "issue-1810" ; 1003 | schema:domainIncludes schema:CreativeWork, 1004 | schema:Trip ; 1005 | schema:inverseOf schema:hasPart ; 1006 | schema:rangeIncludes schema:CreativeWork, 1007 | schema:Trip ; 1008 | schema:sameAs ; 1009 | rdfs:comment "Indicates an item or CreativeWork that this item, or CreativeWork (in some sense), is part of." . 1010 | 1011 | schema:mainEntity a rdf:Property ; 1012 | rdfs:label "mainEntity" ; 1013 | schema:domainIncludes schema:CreativeWork ; 1014 | schema:inverseOf schema:mainEntityOfPage ; 1015 | schema:rangeIncludes schema:Thing ; 1016 | schema:sameAs ; 1017 | rdfs:comment "Indicates the primary entity described in some page or other CreativeWork." ; 1018 | rdfs:subPropertyOf schema:about . 1019 | 1020 | schema:mainEntityOfPage a rdf:Property ; 1021 | rdfs:label "mainEntityOfPage" ; 1022 | schema:domainIncludes schema:Thing ; 1023 | schema:inverseOf schema:mainEntity ; 1024 | schema:rangeIncludes schema:CreativeWork, 1025 | schema:URL ; 1026 | schema:sameAs ; 1027 | rdfs:comment "Indicates a page (or other CreativeWork) for which this thing is the main entity being described. See background notes for details." . 1028 | 1029 | schema:recordedIn schema:rangeIncludes schema:CreativeWork . 1030 | 1031 | schema:review a rdf:Property ; 1032 | rdfs:label "review" ; 1033 | schema:domainIncludes schema:Brand, 1034 | schema:CreativeWork, 1035 | schema:Event, 1036 | schema:Offer, 1037 | schema:Organization, 1038 | schema:Place, 1039 | schema:Product, 1040 | schema:Service ; 1041 | schema:rangeIncludes schema:Review ; 1042 | schema:sameAs ; 1043 | rdfs:comment "A review of the item." . 1044 | 1045 | schema:sponsor a rdf:Property ; 1046 | rdfs:label "sponsor" ; 1047 | schema:domainIncludes schema:CreativeWork, 1048 | schema:Event, 1049 | schema:Grant, 1050 | schema:MedicalStudy, 1051 | schema:Organization, 1052 | schema:Person ; 1053 | schema:rangeIncludes schema:Organization, 1054 | schema:Person ; 1055 | schema:sameAs ; 1056 | rdfs:comment "A person or organization that supports a thing through a pledge, promise, or financial contribution. e.g. a sponsor of a Medical Study or a corporate sponsor of an event." . 1057 | 1058 | schema:subjectOf a rdf:Property ; 1059 | rdfs:label "subjectOf" ; 1060 | dct:source ; 1061 | schema:category "issue-1670" ; 1062 | schema:domainIncludes schema:Thing ; 1063 | schema:inverseOf schema:about ; 1064 | schema:isPartOf ; 1065 | schema:rangeIncludes schema:CreativeWork, 1066 | schema:Event ; 1067 | schema:sameAs ; 1068 | rdfs:comment "A CreativeWork or Event about this Thing.." . 1069 | 1070 | schema:translationOfWork a rdf:Property ; 1071 | rdfs:label "translationOfWork"@en ; 1072 | schema:domainIncludes schema:CreativeWork ; 1073 | schema:inverseOf schema:workTranslation ; 1074 | schema:isPartOf ; 1075 | schema:rangeIncludes schema:CreativeWork ; 1076 | schema:sameAs ; 1077 | rdfs:comment "The work that this work has been translated from. e.g. 物种起源 is a translationOf “On the Origin of Species”" . 1078 | 1079 | schema:workExample a rdf:Property ; 1080 | rdfs:label "workExample" ; 1081 | dct:source ; 1082 | schema:domainIncludes schema:CreativeWork ; 1083 | schema:inverseOf schema:exampleOfWork ; 1084 | schema:rangeIncludes schema:CreativeWork ; 1085 | schema:sameAs ; 1086 | rdfs:comment "Example/instance/realization/derivation of the concept of this creative work. eg. The paperback edition, first edition, or eBook." . 1087 | 1088 | schema:workTranslation a rdf:Property ; 1089 | rdfs:label "workTranslation"@en ; 1090 | schema:domainIncludes schema:CreativeWork ; 1091 | schema:inverseOf schema:translationOfWork ; 1092 | schema:isPartOf ; 1093 | schema:rangeIncludes schema:CreativeWork ; 1094 | schema:sameAs ; 1095 | rdfs:comment "A work that is a translation of the content of this work. e.g. 西遊記 has an English workTranslation “Journey to the West”,a German workTranslation “Monkeys Pilgerfahrt” and a Vietnamese translation Tây du ký bình khảo." . 1096 | 1097 | schema:Review rdfs:subClassOf schema:CreativeWork . 1098 | 1099 | schema:about a rdf:Property ; 1100 | rdfs:label "about" ; 1101 | dct:source ; 1102 | schema:category "issue-1670" ; 1103 | schema:domainIncludes schema:CommunicateAction, 1104 | schema:CreativeWork, 1105 | schema:Event ; 1106 | schema:inverseOf schema:subjectOf ; 1107 | schema:rangeIncludes schema:Thing ; 1108 | schema:sameAs ; 1109 | rdfs:comment "The subject matter of the content." . 1110 | 1111 | schema:MediaObject rdfs:subClassOf schema:CreativeWork . 1112 | -------------------------------------------------------------------------------- /ontologie/linkedin_ontologie.ttl: -------------------------------------------------------------------------------- 1 | @prefix dct: . 2 | @prefix owl: . 3 | @prefix rdf: . 4 | @prefix rdfa: . 5 | @prefix rdfs: . 6 | @prefix schema: . 7 | @prefix xml: . 8 | @prefix xsd: . 9 | @prefix dbo: . 10 | @prefix wikidata: . 11 | @prefix ns5: . 12 | 13 | 14 | a owl:Class ; 15 | rdfs:label "Event"@en ; 16 | rdfs:comment "An event is an occurrence that brings about a change in the state of affairs for one or more people and/or other agents. Events are assumed to occur over a period of time and may not have precise start and end points."@en ; 17 | rdfs:isDefinedBy ; 18 | rdfs:subClassOf , , , . 19 | 20 | 21 | a owl:Class ; 22 | rdfs:label "Individual Event"@en ; 23 | rdfs:comment "A type of event that is principally about a single person, group or organization. Other agents may be involved but the event is most significant for the principal agent."@en ; 24 | rdfs:subClassOf , [ 25 | a owl:Restriction ; 26 | owl:cardinality "1"^^xsd:nonNegativeInteger ; 27 | owl:onProperty 28 | ] ; 29 | rdfs:isDefinedBy . 30 | 31 | 32 | a owl:Class ; 33 | rdfs:label "Employment"@en ; 34 | rdfs:comment "The event of a person entering an occupational relationship with an employer."@en ; 35 | rdfs:subClassOf ; 36 | rdfs:isDefinedBy . 37 | 38 | dbo:Organisation owl:equivalentClass schema:Organization ; 39 | rdfs:label "\uC870\uC9C1"@ko , 40 | "organiza\u00E7\u00E3o"@pt , 41 | "Organisation"@de , 42 | "\u03BF\u03C1\u03B3\u03AC\u03BD\u03C9\u03C3\u03B7"@el , 43 | "organisation"@en , 44 | "organisation"@fr , 45 | "\u7D44\u7E54"@ja , 46 | "organizacija"@sl , 47 | "organisatie"@nl , 48 | "\u041E\u0440\u0433\u0430\u043D\u0438\u0437\u0430\u0446\u0438\u044F"@ru , 49 | "organizaci\u00F3n"@es ; 50 | rdfs:isDefinedBy dbo: . 51 | 52 | dbo:Company rdf:type owl:Class ; 53 | rdfs:label "empresa"@es , 54 | "comhlacht"@ga , 55 | "empresa"@pt , 56 | "entreprise"@fr , 57 | "\uD68C\uC0AC"@ko , 58 | "company"@en , 59 | "Unternehmen"@de , 60 | "bedrijf"@nl , 61 | "\u03B5\u03C4\u03B1\u03B9\u03C1\u03AF\u03B1"@el , 62 | "\u4F1A\u793E"@ja ; 63 | rdfs:isDefinedBy dbo: ; 64 | owl:sameAs dbo:Company ; 65 | rdfs:subClassOf dbo:Organisation . 66 | 67 | dbo:Country owl:equivalentClass wikidata:Q6256 ; 68 | rdfs:label "pays"@fr , 69 | "t\u00EDr"@ga , 70 | "land"@nl , 71 | "dr\u017Eava"@sl , 72 | "\uB098\uB77C"@ko , 73 | "\u56FD"@ja , 74 | "\u03C7\u03CE\u03C1\u03B1"@el , 75 | "Staat"@de , 76 | "pa\u00EDs"@es , 77 | "country"@en , 78 | "\u0413\u043E\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u043E"@ru ; 79 | rdfs:isDefinedBy dbo: ; 80 | owl:sameAs dbo:Country ; 81 | rdfs:subClassOf dbo:PopulatedPlace ; 82 | rdfs:subClassOf dbo:Place . 83 | 84 | dbo:country rdf:type owl:ObjectProperty , 85 | rdf:Property . 86 | dbo:country rdfs:subPropertyOf ns5:hasLocation . 87 | dbo:country owl:equivalentProperty wikidata:P17 ; 88 | rdfs:label "pays"@fr , 89 | "Land"@de , 90 | "\u03C7\u03CE\u03C1\u03B1"@el , 91 | "kraj"@pl , 92 | "pa\u00EDs"@pt , 93 | "pa\u00EDs"@es , 94 | "country"@en , 95 | "land"@nl , 96 | "estat"@ca , 97 | "t\u00EDr"@ga ; 98 | rdfs:range dbo:Country ; 99 | rdfs:isDefinedBy dbo: ; 100 | rdfs:comment "The country where the thing is located."@en ; 101 | owl:sameAs dbo:country . 102 | 103 | dbo:Place owl:equivalentClass schema:Place , 104 | dbo:Location ; 105 | rdfs:label "lugar"@es , 106 | "place"@en , 107 | "\u00E1it"@ga , 108 | "miejsce"@pl , 109 | "lieu"@fr , 110 | "plaats"@nl , 111 | "lekua"@eu , 112 | "lloc"@ca , 113 | "\u0645\u0643\u0627\u0646"@ar , 114 | "\u03C0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE"@el , 115 | "lugar"@pt , 116 | "Ort"@de , 117 | "\u7ACB\u5730"@ja ; 118 | rdfs:isDefinedBy dbo: ; 119 | rdfs:comment "uma localiza\u00E7\u00E3o"@pt , 120 | "Immobile things or locations."@en ; 121 | owl:sameAs dbo:Place ; 122 | rdfs:subClassOf owl:Thing . 123 | 124 | dbo:PopulatedPlace rdf:type owl:Class ; 125 | rdfs:label "bebouwde omgeving"@nl , 126 | "lieu habit\u00E9"@fr , 127 | "\u062A\u062C\u0645\u0639 \u0633\u0643\u0627\u0646\u064A"@ar , 128 | "\u03C0\u03C5\u03BA\u03BD\u03BF\u03BA\u03B1\u03C4\u03BF\u03B9\u03BA\u03B7\u03BC\u03AD\u03BD\u03B7 \u03C0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE"@el , 129 | "populated place"@en , 130 | "bewohnter Ort"@de ; 131 | rdfs:isDefinedBy dbo: ; 132 | rdfs:comment "\u03A0\u03C5\u03BA\u03BD\u03BF\u03BA\u03B1\u03C4\u03BF\u03B9\u03BA\u03B7\u03BC\u03AD\u03BD\u03B7 \u03C0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE, \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B7 \u03C0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE \u03AE \u03C4\u03BF \u03BC\u03AD\u03C1\u03BF\u03C2 \u03BC\u03B5 \u03BC\u03B5\u03B3\u03AC\u03BB\u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03CC \u03BA\u03C4\u03B9\u03C1\u03AF\u03C9\u03BD \u03BA\u03B1\u03B9 \u03BC\u03B5\u03B3\u03AC\u03BB\u03BF \u03BC\u03CC\u03BD\u03B9\u03BC\u03BF \u03C0\u03BB\u03B7\u03B8\u03C5\u03C3\u03BC\u03CC, \u03C3\u03B5 \u03C3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7 \u03BC\u03B5 \u03C4\u03B7\u03BD \u03B3\u03B5\u03C9\u03B3\u03C1\u03B1\u03C6\u03B9\u03BA\u03AE \u03C0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE \u03C0\u03BF\u03C5 \u03BA\u03B1\u03C4\u03B1\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 (\u03BC\u03B5\u03B3\u03B1\u03BB\u03BF\u03CD\u03C0\u03BF\u03BB\u03B7, \u03C0\u03CC\u03BB\u03B7 \u03AE \u03C7\u03C9\u03C1\u03B9\u03CC)."@el , 133 | "As defined by the United States Geological Survey, a populated place is a place or area with clustered or scattered buildings and a permanent human population (city, settlement, town, or village) referenced with geographic coordinates (http://en.wikipedia.org/wiki/Populated_place)."@en ; 134 | owl:sameAs dbo:PopulatedPlace ; 135 | rdfs:subClassOf dbo:Place . 136 | 137 | dbo:Settlement owl:equivalentClass wikidata:Q486972 ; 138 | rdfs:label "\u5C45\u4F4F\u5730"@ja , 139 | "nederzetting"@nl , 140 | "settlement"@en , 141 | "zone peupl\u00E9e"@fr , 142 | "bardas"@ga , 143 | "Siedlung"@de , 144 | "\u03BF\u03B9\u03BA\u03B9\u03C3\u03BC\u03CC\u03C2"@el ; 145 | rdfs:isDefinedBy dbo: ; 146 | owl:sameAs dbo:Settlement ; 147 | rdfs:subClassOf dbo:PopulatedPlace ; 148 | rdfs:subClassOf dbo:Place . 149 | 150 | dbo:City rdf:type owl:Class . 151 | dbo:City owl:equivalentClass schema:City . 152 | dbo:City owl:equivalentClass wikidata:Q515 . 153 | dbo:City rdfs:label "cathair"@ga , 154 | "\u03C0\u03CC\u03BB\u03B7"@el , 155 | "\uB3C4\uC2DC"@ko , 156 | "ville"@fr , 157 | "ciudad"@es , 158 | "\u5E02"@ja , 159 | "cidade"@pt , 160 | "\u0936\u0939\u0930"@hi , 161 | "citt\u00E0"@it , 162 | "city"@en , 163 | "stad"@nl , 164 | "Stadt"@de , 165 | "miasto"@pl , 166 | "cidade"@gl ; 167 | rdfs:isDefinedBy dbo: ; 168 | rdfs:comment "a relatively large and permanent settlement, particularly a large urban settlement"@en , 169 | "un asentamiento permanente y relativamente grande, especialmente un gran asentamiento urbano"@es , 170 | "Actualmente consid\u00E9rase como unha entidade urbana con alta densidade de poboaci\u00F3n na que predominan fundamentalmente a industria e os servizos."@gl ; 171 | owl:sameAs dbo:City ; 172 | rdfs:subClassOf dbo:Settlement ; 173 | rdfs:subClassOf dbo:Place . 174 | 175 | schema:Person a rdfs:Class ; 176 | rdfs:label "Person" ; 177 | dct:source ; 178 | schema:sameAs ; 179 | rdfs:comment "A person (alive, dead, undead, or fictional)." ; 180 | rdfs:subClassOf schema:Thing ; 181 | owl:equivalentClass . 182 | 183 | schema:Thing a rdfs:Class ; 184 | rdfs:label "Thing" ; 185 | schema:sameAs ; 186 | rdfs:comment "The most generic type of item." . 187 | 188 | schema:Patient rdfs:subClassOf schema:Person . 189 | 190 | schema:accountablePerson schema:rangeIncludes schema:Person . 191 | 192 | schema:acquiredFrom schema:rangeIncludes schema:Person . 193 | 194 | schema:actor schema:rangeIncludes schema:Person . 195 | 196 | schema:actors schema:rangeIncludes schema:Person . 197 | 198 | schema:additionalName a rdf:Property ; 199 | rdfs:label "additionalName" ; 200 | schema:domainIncludes schema:Person ; 201 | schema:rangeIncludes schema:Text ; 202 | schema:sameAs ; 203 | rdfs:comment "An additional name for a Person, can be used for a middle name." . 204 | 205 | schema:additionalType a rdf:Property ; 206 | rdfs:label "additionalType" ; 207 | schema:domainIncludes schema:Thing ; 208 | schema:rangeIncludes schema:URL ; 209 | schema:sameAs ; 210 | rdfs:comment "An additional type for the item, typically used for adding more specific types from external vocabularies in microdata syntax. This is a relationship between something and a class that the thing is in. In RDFa syntax, it is better to use the native RDFa syntax - the 'typeof' attribute - for multiple types. Schema.org tools may have only weaker understanding of extra types, in particular those defined externally." ; 211 | rdfs:subPropertyOf rdf:type . 212 | 213 | schema:address a rdf:Property ; 214 | rdfs:label "address" ; 215 | schema:domainIncludes schema:GeoCoordinates, 216 | schema:GeoShape, 217 | schema:Organization, 218 | schema:Person, 219 | schema:Place ; 220 | schema:rangeIncludes schema:PostalAddress, 221 | schema:Text ; 222 | schema:sameAs ; 223 | rdfs:comment "Physical address of the item." . 224 | 225 | schema:affiliation a rdf:Property ; 226 | rdfs:label "affiliation" ; 227 | schema:domainIncludes schema:Person ; 228 | schema:rangeIncludes schema:Organization ; 229 | schema:sameAs ; 230 | rdfs:comment "An organization that this person is affiliated with. For example, a school/university, a club, or a team." ; 231 | rdfs:subPropertyOf schema:memberOf . 232 | 233 | schema:agent schema:rangeIncludes schema:Person . 234 | 235 | schema:alternateName a rdf:Property ; 236 | rdfs:label "alternateName" ; 237 | schema:domainIncludes schema:Thing ; 238 | schema:rangeIncludes schema:Text ; 239 | schema:sameAs ; 240 | rdfs:comment "An alias for the item." . 241 | 242 | schema:alumniOf a rdf:Property ; 243 | rdfs:label "alumniOf" ; 244 | schema:domainIncludes schema:Person ; 245 | schema:inverseOf schema:alumni ; 246 | schema:rangeIncludes schema:EducationalOrganization, 247 | schema:Organization ; 248 | schema:sameAs ; 249 | rdfs:comment "An organization that the person is an alumni of." . 250 | 251 | schema:artist schema:rangeIncludes schema:Person . 252 | 253 | schema:athlete schema:rangeIncludes schema:Person . 254 | 255 | schema:attendee schema:rangeIncludes schema:Person . 256 | 257 | schema:attendees schema:rangeIncludes schema:Person . 258 | 259 | schema:author schema:rangeIncludes schema:Person . 260 | 261 | schema:awards a rdf:Property ; 262 | rdfs:label "awards" ; 263 | schema:domainIncludes schema:CreativeWork, 264 | schema:Organization, 265 | schema:Person, 266 | schema:Product ; 267 | schema:rangeIncludes schema:Text ; 268 | schema:sameAs ; 269 | schema:supersededBy schema:award ; 270 | rdfs:comment "Awards won by or for this item." . 271 | 272 | schema:awayTeam schema:rangeIncludes schema:Person . 273 | 274 | schema:bccRecipient schema:rangeIncludes schema:Person . 275 | 276 | schema:birthDate a rdf:Property ; 277 | rdfs:label "birthDate" ; 278 | schema:domainIncludes schema:Person ; 279 | schema:rangeIncludes schema:Date ; 280 | schema:sameAs ; 281 | rdfs:comment "Date of birth." . 282 | 283 | schema:birthPlace a rdf:Property ; 284 | rdfs:label "birthPlace" ; 285 | schema:domainIncludes schema:Person ; 286 | schema:rangeIncludes schema:Place ; 287 | schema:sameAs ; 288 | rdfs:comment "The place where the person was born." . 289 | 290 | schema:bookingAgent schema:rangeIncludes schema:Person . 291 | 292 | schema:borrower schema:rangeIncludes schema:Person . 293 | 294 | schema:brand a rdf:Property ; 295 | rdfs:label "brand" ; 296 | schema:domainIncludes schema:Organization, 297 | schema:Person, 298 | schema:Product, 299 | schema:Service ; 300 | schema:rangeIncludes schema:Brand, 301 | schema:Organization ; 302 | schema:sameAs ; 303 | rdfs:comment "The brand(s) associated with a product or service, or the brand(s) maintained by an organization or business person." . 304 | 305 | schema:broker schema:rangeIncludes schema:Person . 306 | 307 | schema:buyer schema:rangeIncludes schema:Person . 308 | 309 | schema:candidate schema:rangeIncludes schema:Person . 310 | 311 | schema:ccRecipient schema:rangeIncludes schema:Person . 312 | 313 | schema:character schema:rangeIncludes schema:Person . 314 | 315 | schema:children a rdf:Property ; 316 | rdfs:label "children" ; 317 | schema:domainIncludes schema:Person ; 318 | schema:rangeIncludes schema:Person ; 319 | schema:sameAs ; 320 | rdfs:comment "A child of the person." . 321 | 322 | schema:coach schema:rangeIncludes schema:Person . 323 | 324 | schema:colleagues a rdf:Property ; 325 | rdfs:label "colleagues" ; 326 | schema:domainIncludes schema:Person ; 327 | schema:rangeIncludes schema:Person ; 328 | schema:sameAs ; 329 | schema:supersededBy schema:colleague ; 330 | rdfs:comment "A colleague of the person." . 331 | 332 | schema:colorist schema:rangeIncludes schema:Person . 333 | 334 | schema:competitor schema:rangeIncludes schema:Person . 335 | 336 | schema:composer schema:rangeIncludes schema:Person . 337 | 338 | schema:contactPoints a rdf:Property ; 339 | rdfs:label "contactPoints" ; 340 | schema:domainIncludes schema:Organization, 341 | schema:Person ; 342 | schema:rangeIncludes schema:ContactPoint ; 343 | schema:sameAs ; 344 | schema:supersededBy schema:contactPoint ; 345 | rdfs:comment "A contact point for a person or organization." . 346 | 347 | schema:contributor schema:rangeIncludes schema:Person . 348 | 349 | schema:copyrightHolder schema:rangeIncludes schema:Person . 350 | 351 | schema:creator schema:rangeIncludes schema:Person . 352 | 353 | schema:creditedTo schema:rangeIncludes schema:Person . 354 | 355 | schema:customer schema:rangeIncludes schema:Person . 356 | 357 | schema:deathDate a rdf:Property ; 358 | rdfs:label "deathDate" ; 359 | schema:domainIncludes schema:Person ; 360 | schema:rangeIncludes schema:Date ; 361 | schema:sameAs ; 362 | rdfs:comment "Date of death." . 363 | 364 | schema:deathPlace a rdf:Property ; 365 | rdfs:label "deathPlace" ; 366 | schema:domainIncludes schema:Person ; 367 | schema:rangeIncludes schema:Place ; 368 | schema:sameAs ; 369 | rdfs:comment "The place where the person died." . 370 | 371 | schema:director schema:rangeIncludes schema:Person . 372 | 373 | schema:directors schema:rangeIncludes schema:Person . 374 | 375 | schema:disambiguatingDescription a rdf:Property ; 376 | rdfs:label "disambiguatingDescription" ; 377 | schema:domainIncludes schema:Thing ; 378 | schema:rangeIncludes schema:Text ; 379 | schema:sameAs ; 380 | rdfs:comment "A sub property of description. A short description of the item used to disambiguate from other, similar items. Information from other properties (in particular, name) may be necessary for the description to be useful for disambiguation." ; 381 | rdfs:subPropertyOf schema:description . 382 | 383 | schema:duns a rdf:Property ; 384 | rdfs:label "duns" ; 385 | dct:source ; 386 | schema:domainIncludes schema:Organization, 387 | schema:Person ; 388 | schema:rangeIncludes schema:Text ; 389 | schema:sameAs ; 390 | rdfs:comment "The Dun & Bradstreet DUNS number for identifying an organization or business person." ; 391 | rdfs:subPropertyOf schema:identifier . 392 | 393 | schema:editor schema:rangeIncludes schema:Person . 394 | 395 | schema:email a rdf:Property ; 396 | rdfs:label "email" ; 397 | schema:domainIncludes schema:ContactPoint, 398 | schema:Organization, 399 | schema:Person ; 400 | schema:rangeIncludes schema:Text ; 401 | schema:sameAs ; 402 | rdfs:comment "Email address." . 403 | 404 | schema:employee schema:rangeIncludes schema:Person . 405 | 406 | schema:employees schema:rangeIncludes schema:Person . 407 | 408 | schema:endorsee schema:rangeIncludes schema:Person . 409 | 410 | schema:endorsers schema:rangeIncludes schema:Person . 411 | 412 | schema:familyName a rdf:Property ; 413 | rdfs:label "familyName" ; 414 | schema:domainIncludes schema:Person ; 415 | schema:rangeIncludes schema:Text ; 416 | schema:sameAs ; 417 | rdfs:comment "Family name. In the U.S., the last name of an Person. This can be used along with givenName instead of the name property." . 418 | 419 | schema:faxNumber a rdf:Property ; 420 | rdfs:label "faxNumber" ; 421 | schema:domainIncludes schema:ContactPoint, 422 | schema:Organization, 423 | schema:Person, 424 | schema:Place ; 425 | schema:rangeIncludes schema:Text ; 426 | schema:sameAs ; 427 | rdfs:comment "The fax number." . 428 | 429 | schema:followee schema:rangeIncludes schema:Person . 430 | 431 | schema:follows a rdf:Property ; 432 | rdfs:label "follows" ; 433 | schema:domainIncludes schema:Person ; 434 | schema:rangeIncludes schema:Person ; 435 | schema:sameAs ; 436 | rdfs:comment "The most generic uni-directional social relation." . 437 | 438 | schema:founder schema:rangeIncludes schema:Person . 439 | 440 | schema:founders schema:rangeIncludes schema:Person . 441 | 442 | schema:funder a rdf:Property ; 443 | rdfs:label "funder" ; 444 | schema:domainIncludes schema:CreativeWork, 445 | schema:Event, 446 | schema:MonetaryGrant, 447 | schema:Organization, 448 | schema:Person ; 449 | schema:rangeIncludes schema:Organization, 450 | schema:Person ; 451 | schema:sameAs ; 452 | rdfs:comment "A person or organization that supports (sponsors) something through some kind of financial contribution." ; 453 | rdfs:subPropertyOf schema:sponsor . 454 | 455 | schema:gender a rdf:Property ; 456 | rdfs:label "gender" ; 457 | schema:domainIncludes schema:Person ; 458 | schema:rangeIncludes schema:GenderType, 459 | schema:Text ; 460 | schema:sameAs ; 461 | rdfs:comment "Gender of the person. While http://schema.org/Male and http://schema.org/Female may be used, text strings are also acceptable for people who do not identify as a binary gender." . 462 | 463 | schema:givenName a rdf:Property ; 464 | rdfs:label "givenName" ; 465 | schema:domainIncludes schema:Person ; 466 | schema:rangeIncludes schema:Text ; 467 | schema:sameAs ; 468 | rdfs:comment "Given name. In the U.S., the first name of a Person. This can be used along with familyName instead of the name property." . 469 | 470 | schema:globalLocationNumber a rdf:Property ; 471 | rdfs:label "globalLocationNumber" ; 472 | dct:source ; 473 | schema:domainIncludes schema:Organization, 474 | schema:Person, 475 | schema:Place ; 476 | schema:rangeIncludes schema:Text ; 477 | schema:sameAs ; 478 | rdfs:comment "The Global Location Number (GLN, sometimes also referred to as International Location Number or ILN) of the respective organization, person, or place. The GLN is a 13-digit number used to identify parties and physical locations." ; 479 | rdfs:subPropertyOf schema:identifier . 480 | 481 | schema:grantee schema:rangeIncludes schema:Person . 482 | 483 | schema:hasOccupation a rdf:Property ; 484 | rdfs:label "hasOccupation" ; 485 | dct:source ; 486 | schema:category "issue-1698" ; 487 | schema:domainIncludes schema:Person ; 488 | schema:isPartOf ; 489 | schema:rangeIncludes schema:Occupation ; 490 | schema:sameAs ; 491 | rdfs:comment "The Person's occupation. For past professions, use Role for expressing dates." . 492 | 493 | schema:hasOfferCatalog a rdf:Property ; 494 | rdfs:label "hasOfferCatalog" ; 495 | schema:domainIncludes schema:Organization, 496 | schema:Person, 497 | schema:Service ; 498 | schema:rangeIncludes schema:OfferCatalog ; 499 | schema:sameAs ; 500 | rdfs:comment "Indicates an OfferCatalog listing for this Organization, Person, or Service." . 501 | 502 | schema:hasPOS a rdf:Property ; 503 | rdfs:label "hasPOS" ; 504 | dct:source ; 505 | schema:domainIncludes schema:Organization, 506 | schema:Person ; 507 | schema:rangeIncludes schema:Place ; 508 | schema:sameAs ; 509 | rdfs:comment "Points-of-Sales operated by the organization or person." . 510 | 511 | schema:height a rdf:Property ; 512 | rdfs:label "height" ; 513 | schema:domainIncludes schema:MediaObject, 514 | schema:Person, 515 | schema:Product, 516 | schema:VisualArtwork ; 517 | schema:rangeIncludes schema:Distance, 518 | schema:QuantitativeValue ; 519 | schema:sameAs ; 520 | rdfs:comment "The height of the item." . 521 | 522 | schema:homeLocation a rdf:Property ; 523 | rdfs:label "homeLocation" ; 524 | schema:domainIncludes schema:Person ; 525 | schema:rangeIncludes schema:ContactPoint, 526 | schema:Place ; 527 | schema:sameAs ; 528 | rdfs:comment "A contact location for a person's residence." ; 529 | rdfs:subPropertyOf schema:location . 530 | 531 | schema:homeTeam schema:rangeIncludes schema:Person . 532 | 533 | schema:honorificPrefix a rdf:Property ; 534 | rdfs:label "honorificPrefix" ; 535 | schema:domainIncludes schema:Person ; 536 | schema:rangeIncludes schema:Text ; 537 | schema:sameAs ; 538 | rdfs:comment "An honorific prefix preceding a Person's name such as Dr/Mrs/Mr." . 539 | 540 | schema:honorificSuffix a rdf:Property ; 541 | rdfs:label "honorificSuffix" ; 542 | schema:domainIncludes schema:Person ; 543 | schema:rangeIncludes schema:Text ; 544 | schema:sameAs ; 545 | rdfs:comment "An honorific suffix preceding a Person's name such as M.D. /PhD/MSCSW." . 546 | 547 | schema:illustrator schema:rangeIncludes schema:Person . 548 | 549 | schema:image a rdf:Property ; 550 | rdfs:label "image" ; 551 | schema:domainIncludes schema:Thing ; 552 | schema:rangeIncludes schema:ImageObject, 553 | schema:URL ; 554 | schema:sameAs ; 555 | rdfs:comment "An image of the item. This can be a URL or a fully described ImageObject." . 556 | 557 | schema:inker schema:rangeIncludes schema:Person . 558 | 559 | schema:instructor schema:rangeIncludes schema:Person . 560 | 561 | schema:isicV4 a rdf:Property ; 562 | rdfs:label "isicV4" ; 563 | dct:source ; 564 | schema:domainIncludes schema:Organization, 565 | schema:Person, 566 | schema:Place ; 567 | schema:rangeIncludes schema:Text ; 568 | schema:sameAs ; 569 | rdfs:comment "The International Standard of Industrial Classification of All Economic Activities (ISIC), Revision 4 code for a particular organization, business person, or place." . 570 | 571 | schema:jobTitle a rdf:Property ; 572 | rdfs:label "jobTitle" ; 573 | schema:domainIncludes schema:Person ; 574 | schema:rangeIncludes schema:Text ; 575 | schema:sameAs ; 576 | rdfs:comment "The job title of the person (for example, Financial Manager)." . 577 | 578 | schema:knows a rdf:Property ; 579 | rdfs:label "knows" ; 580 | schema:domainIncludes schema:Person ; 581 | schema:rangeIncludes schema:Person ; 582 | schema:sameAs ; 583 | rdfs:comment "The most generic bi-directional social/work relation." . 584 | 585 | schema:knowsAbout a rdf:Property ; 586 | rdfs:label "knowsAbout" ; 587 | dct:source , 588 | ; 589 | schema:category "issue-1688" ; 590 | schema:domainIncludes schema:Organization, 591 | schema:Person ; 592 | schema:isPartOf ; 593 | schema:rangeIncludes schema:Text, 594 | schema:Thing, 595 | schema:URL ; 596 | schema:sameAs ; 597 | rdfs:comment "Of a Person, and less typically of an Organization, to indicate a topic that is known about - suggesting possible expertise but not implying it. We do not distinguish skill levels here, or yet relate this to educational content, events, objectives or JobPosting descriptions." . 598 | 599 | schema:knowsLanguage a rdf:Property ; 600 | rdfs:label "knowsLanguage" ; 601 | dct:source , 602 | ; 603 | schema:category "issue-1688" ; 604 | schema:domainIncludes schema:Organization, 605 | schema:Person ; 606 | schema:isPartOf ; 607 | schema:rangeIncludes schema:Language, 608 | schema:Text ; 609 | schema:sameAs ; 610 | rdfs:comment "Of a Person, and less typically of an Organization, to indicate a known language. We do not distinguish skill levels or reading/writing/speaking/signing here. Use language codes from the IETF BCP 47 standard." . 611 | 612 | schema:landlord schema:rangeIncludes schema:Person . 613 | 614 | schema:legislationPassedBy schema:rangeIncludes schema:Person . 615 | 616 | schema:legislationResponsible schema:rangeIncludes schema:Person . 617 | 618 | schema:lender schema:rangeIncludes schema:Person . 619 | 620 | schema:letterer schema:rangeIncludes schema:Person . 621 | 622 | schema:loser schema:rangeIncludes schema:Person . 623 | 624 | schema:lyricist schema:rangeIncludes schema:Person . 625 | 626 | schema:mainEntityOfPage a rdf:Property ; 627 | rdfs:label "mainEntityOfPage" ; 628 | schema:domainIncludes schema:Thing ; 629 | schema:inverseOf schema:mainEntity ; 630 | schema:rangeIncludes schema:CreativeWork, 631 | schema:URL ; 632 | schema:sameAs ; 633 | rdfs:comment "Indicates a page (or other CreativeWork) for which this thing is the main entity being described. See background notes for details." . 634 | 635 | schema:makesOffer a rdf:Property ; 636 | rdfs:label "makesOffer" ; 637 | dct:source ; 638 | schema:domainIncludes schema:Organization, 639 | schema:Person ; 640 | schema:inverseOf schema:offeredBy ; 641 | schema:rangeIncludes schema:Offer ; 642 | schema:sameAs ; 643 | rdfs:comment "A pointer to products or services offered by the organization or person." . 644 | 645 | schema:members schema:rangeIncludes schema:Person . 646 | 647 | schema:merchant schema:rangeIncludes schema:Person . 648 | 649 | schema:musicBy schema:rangeIncludes schema:Person . 650 | 651 | schema:musicGroupMember schema:rangeIncludes schema:Person . 652 | 653 | schema:naics a rdf:Property ; 654 | rdfs:label "naics" ; 655 | dct:source ; 656 | schema:domainIncludes schema:Organization, 657 | schema:Person ; 658 | schema:rangeIncludes schema:Text ; 659 | schema:sameAs ; 660 | rdfs:comment "The North American Industry Classification System (NAICS) code for a particular organization or business person." . 661 | 662 | schema:name a rdf:Property ; 663 | rdfs:label "name" ; 664 | schema:domainIncludes schema:Thing ; 665 | schema:rangeIncludes schema:Text ; 666 | schema:sameAs ; 667 | rdfs:comment "The name of the item." ; 668 | rdfs:subPropertyOf ; 669 | owl:equivalentProperty dct:title . 670 | 671 | schema:nationality a rdf:Property ; 672 | rdfs:label "nationality" ; 673 | schema:domainIncludes schema:Person ; 674 | schema:rangeIncludes schema:Country ; 675 | schema:sameAs ; 676 | rdfs:comment "Nationality of the person." . 677 | 678 | schema:netWorth a rdf:Property ; 679 | rdfs:label "netWorth" ; 680 | schema:domainIncludes schema:Person ; 681 | schema:rangeIncludes schema:MonetaryAmount, 682 | schema:PriceSpecification ; 683 | schema:sameAs ; 684 | rdfs:comment "The total financial value of the person as calculated by subtracting assets from liabilities." . 685 | 686 | schema:opponent schema:rangeIncludes schema:Person . 687 | 688 | schema:organizer schema:rangeIncludes schema:Person . 689 | 690 | schema:owns a rdf:Property ; 691 | rdfs:label "owns" ; 692 | dct:source ; 693 | schema:domainIncludes schema:Organization, 694 | schema:Person ; 695 | schema:rangeIncludes schema:OwnershipInfo, 696 | schema:Product ; 697 | schema:sameAs ; 698 | rdfs:comment "Products owned by the organization or person." . 699 | 700 | schema:parents a rdf:Property ; 701 | rdfs:label "parents" ; 702 | schema:domainIncludes schema:Person ; 703 | schema:rangeIncludes schema:Person ; 704 | schema:sameAs ; 705 | schema:supersededBy schema:parent ; 706 | rdfs:comment "A parents of the person." . 707 | 708 | schema:participant schema:rangeIncludes schema:Person . 709 | 710 | schema:penciler schema:rangeIncludes schema:Person . 711 | 712 | schema:performer schema:rangeIncludes schema:Person . 713 | 714 | schema:performerIn a rdf:Property ; 715 | rdfs:label "performerIn" ; 716 | schema:domainIncludes schema:Person ; 717 | schema:rangeIncludes schema:Event ; 718 | schema:sameAs ; 719 | rdfs:comment "Event that this person is a performer or participant in." . 720 | 721 | schema:performers schema:rangeIncludes schema:Person . 722 | 723 | schema:potentialAction a rdf:Property ; 724 | rdfs:label "potentialAction" ; 725 | schema:domainIncludes schema:Thing ; 726 | schema:rangeIncludes schema:Action ; 727 | schema:sameAs ; 728 | rdfs:comment "Indicates a potential Action, which describes an idealized action in which this thing would play an 'object' role." . 729 | 730 | schema:producer schema:rangeIncludes schema:Person . 731 | 732 | schema:provider schema:rangeIncludes schema:Person . 733 | 734 | schema:publishedBy schema:rangeIncludes schema:Person . 735 | 736 | schema:publisher schema:rangeIncludes schema:Person . 737 | 738 | schema:publishingPrinciples a rdf:Property ; 739 | rdfs:label "publishingPrinciples" ; 740 | schema:domainIncludes schema:CreativeWork, 741 | schema:Organization, 742 | schema:Person ; 743 | schema:rangeIncludes schema:CreativeWork, 744 | schema:URL ; 745 | schema:sameAs ; 746 | rdfs:comment """The publishingPrinciples property indicates (typically via URL) a document describing the editorial principles of an Organization (or individual e.g. a Person writing a blog) that relate to their activities as a publisher, e.g. ethics or diversity policies. When applied to a CreativeWork (e.g. NewsArticle) the principles are those of the party primarily responsible for the creation of the CreativeWork.

747 | 748 | While such policies are most typically expressed in natural language, sometimes related information (e.g. indicating a funder) can be expressed using schema.org terminology.""" . 749 | 750 | schema:readBy schema:rangeIncludes schema:Person . 751 | 752 | schema:recipient schema:rangeIncludes schema:Person . 753 | 754 | schema:relatedTo a rdf:Property ; 755 | rdfs:label "relatedTo" ; 756 | schema:domainIncludes schema:Person ; 757 | schema:rangeIncludes schema:Person ; 758 | schema:sameAs ; 759 | rdfs:comment "The most generic familial relation." . 760 | 761 | schema:reviewedBy schema:rangeIncludes schema:Person . 762 | 763 | schema:sameAs a rdf:Property ; 764 | rdfs:label "sameAs" ; 765 | schema:domainIncludes schema:Thing ; 766 | schema:rangeIncludes schema:URL ; 767 | schema:sameAs ; 768 | rdfs:comment "URL of a reference Web page that unambiguously indicates the item's identity. E.g. the URL of the item's Wikipedia page, Wikidata entry, or official website." . 769 | 770 | schema:sdPublisher schema:rangeIncludes schema:Person . 771 | 772 | schema:seeks a rdf:Property ; 773 | rdfs:label "seeks" ; 774 | dct:source ; 775 | schema:domainIncludes schema:Organization, 776 | schema:Person ; 777 | schema:rangeIncludes schema:Demand ; 778 | schema:sameAs ; 779 | rdfs:comment "A pointer to products or services sought by the organization or person (demand)." . 780 | 781 | schema:seller schema:rangeIncludes schema:Person . 782 | 783 | schema:sender schema:rangeIncludes schema:Person . 784 | 785 | schema:siblings a rdf:Property ; 786 | rdfs:label "siblings" ; 787 | schema:domainIncludes schema:Person ; 788 | schema:rangeIncludes schema:Person ; 789 | schema:sameAs ; 790 | schema:supersededBy schema:sibling ; 791 | rdfs:comment "A sibling of the person." . 792 | 793 | schema:spokenByCharacter schema:rangeIncludes schema:Person . 794 | 795 | schema:spouse a rdf:Property ; 796 | rdfs:label "spouse" ; 797 | schema:domainIncludes schema:Person ; 798 | schema:rangeIncludes schema:Person ; 799 | schema:sameAs ; 800 | rdfs:comment "The person's spouse." . 801 | 802 | schema:subjectOf a rdf:Property ; 803 | rdfs:label "subjectOf" ; 804 | dct:source ; 805 | schema:category "issue-1670" ; 806 | schema:domainIncludes schema:Thing ; 807 | schema:inverseOf schema:about ; 808 | schema:isPartOf ; 809 | schema:rangeIncludes schema:CreativeWork, 810 | schema:Event ; 811 | schema:sameAs ; 812 | rdfs:comment "A CreativeWork or Event about this Thing.." . 813 | 814 | schema:taxID a rdf:Property ; 815 | rdfs:label "taxID" ; 816 | dct:source ; 817 | schema:domainIncludes schema:Organization, 818 | schema:Person ; 819 | schema:rangeIncludes schema:Text ; 820 | schema:sameAs ; 821 | rdfs:comment "The Tax / Fiscal ID of the organization or person, e.g. the TIN in the US or the CIF/NIF in Spain." ; 822 | rdfs:subPropertyOf schema:identifier . 823 | 824 | schema:telephone a rdf:Property ; 825 | rdfs:label "telephone" ; 826 | schema:domainIncludes schema:ContactPoint, 827 | schema:Organization, 828 | schema:Person, 829 | schema:Place ; 830 | schema:rangeIncludes schema:Text ; 831 | schema:sameAs ; 832 | rdfs:comment "The telephone number." . 833 | 834 | schema:toRecipient schema:rangeIncludes schema:Person . 835 | 836 | schema:translator schema:rangeIncludes schema:Person . 837 | 838 | schema:underName schema:rangeIncludes schema:Person . 839 | 840 | schema:url a rdf:Property ; 841 | rdfs:label "url" ; 842 | schema:domainIncludes schema:Thing ; 843 | schema:rangeIncludes schema:URL ; 844 | schema:sameAs ; 845 | rdfs:comment "URL of the item." . 846 | 847 | schema:vatID a rdf:Property ; 848 | rdfs:label "vatID" ; 849 | dct:source ; 850 | schema:domainIncludes schema:Organization, 851 | schema:Person ; 852 | schema:rangeIncludes schema:Text ; 853 | schema:sameAs ; 854 | rdfs:comment "The Value-added Tax ID of the organization or person." . 855 | 856 | schema:vendor schema:rangeIncludes schema:Person . 857 | 858 | schema:weight a rdf:Property ; 859 | rdfs:label "weight" ; 860 | dct:source ; 861 | schema:domainIncludes schema:Person, 862 | schema:Product ; 863 | schema:rangeIncludes schema:QuantitativeValue ; 864 | schema:sameAs ; 865 | rdfs:comment "The weight of the product or person." . 866 | 867 | schema:winner schema:rangeIncludes schema:Person . 868 | 869 | schema:workLocation a rdf:Property ; 870 | rdfs:label "workLocation" ; 871 | schema:domainIncludes schema:Person ; 872 | schema:rangeIncludes schema:ContactPoint, 873 | schema:Place ; 874 | schema:sameAs ; 875 | rdfs:comment "A contact location for a person's place of work." ; 876 | rdfs:subPropertyOf schema:location . 877 | 878 | schema:worksFor a rdf:Property ; 879 | rdfs:label "worksFor" ; 880 | schema:domainIncludes schema:Person ; 881 | schema:rangeIncludes schema:Organization ; 882 | schema:sameAs ; 883 | rdfs:comment "Organizations that the person works for." . 884 | 885 | schema:alumni schema:rangeIncludes schema:Person . 886 | 887 | schema:award a rdf:Property ; 888 | rdfs:label "award" ; 889 | schema:domainIncludes schema:CreativeWork, 890 | schema:Organization, 891 | schema:Person, 892 | schema:Product, 893 | schema:Service ; 894 | schema:rangeIncludes schema:Text ; 895 | schema:sameAs ; 896 | rdfs:comment "An award won by or for this item." . 897 | 898 | schema:colleague a rdf:Property ; 899 | rdfs:label "colleague" ; 900 | schema:domainIncludes schema:Person ; 901 | schema:rangeIncludes schema:Person, 902 | schema:URL ; 903 | schema:sameAs ; 904 | rdfs:comment "A colleague of the person." . 905 | 906 | schema:contactPoint a rdf:Property ; 907 | rdfs:label "contactPoint" ; 908 | schema:domainIncludes schema:HealthInsurancePlan, 909 | schema:Organization, 910 | schema:Person ; 911 | schema:rangeIncludes schema:ContactPoint ; 912 | schema:sameAs ; 913 | rdfs:comment "A contact point for a person or organization." . 914 | 915 | schema:description a rdf:Property ; 916 | rdfs:label "description" ; 917 | schema:domainIncludes schema:Thing ; 918 | schema:rangeIncludes schema:Text ; 919 | schema:sameAs ; 920 | rdfs:comment "A description of the item." ; 921 | owl:equivalentProperty dct:description . 922 | 923 | schema:member schema:rangeIncludes schema:Person . 924 | 925 | schema:memberOf a rdf:Property ; 926 | rdfs:label "memberOf" ; 927 | schema:domainIncludes schema:Organization, 928 | schema:Person ; 929 | schema:inverseOf schema:member ; 930 | schema:rangeIncludes schema:Organization, 931 | schema:ProgramMembership ; 932 | schema:sameAs ; 933 | rdfs:comment "An Organization (or ProgramMembership) to which this Person or Organization belongs." . 934 | 935 | schema:offeredBy schema:rangeIncludes schema:Person . 936 | 937 | schema:parent a rdf:Property ; 938 | rdfs:label "parent" ; 939 | schema:domainIncludes schema:Person ; 940 | schema:rangeIncludes schema:Person ; 941 | schema:sameAs ; 942 | rdfs:comment "A parent of this person." . 943 | 944 | schema:sibling a rdf:Property ; 945 | rdfs:label "sibling" ; 946 | schema:domainIncludes schema:Person ; 947 | schema:rangeIncludes schema:Person ; 948 | schema:sameAs ; 949 | rdfs:comment "A sibling of the person." . 950 | 951 | schema:sponsor a rdf:Property ; 952 | rdfs:label "sponsor" ; 953 | schema:domainIncludes schema:CreativeWork, 954 | schema:Event, 955 | schema:Grant, 956 | schema:MedicalStudy, 957 | schema:Organization, 958 | schema:Person ; 959 | schema:rangeIncludes schema:Organization, 960 | schema:Person ; 961 | schema:sameAs ; 962 | rdfs:comment "A person or organization that supports a thing through a pledge, promise, or financial contribution. e.g. a sponsor of a Medical Study or a corporate sponsor of an event." . 963 | 964 | schema:identifier a rdf:Property ; 965 | rdfs:label "identifier" ; 966 | schema:domainIncludes schema:Thing ; 967 | schema:rangeIncludes schema:PropertyValue, 968 | schema:Text, 969 | schema:URL ; 970 | schema:sameAs ; 971 | rdfs:comment "The identifier property represents any kind of identifier for any kind of Thing, such as ISBNs, GTIN codes, UUIDs etc. Schema.org provides dedicated properties for representing many of these, either as textual strings or as URL (URI) links. See background notes for more details." ; 972 | owl:equivalentProperty dct:identifier . 973 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.8.18 2 | gunicorn==19.7.1 3 | jsonpath-rw==1.4.0 4 | rdflib==4.2.2 5 | requests==2.18.4 6 | python-linkedin==4.1 7 | django-ipware==2.1.0 8 | python-memcached==1.59 9 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-2.7.14 -------------------------------------------------------------------------------- /server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/server/__init__.py -------------------------------------------------------------------------------- /server/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /server/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/server/migrations/__init__.py -------------------------------------------------------------------------------- /server/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /server/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # No tests for the moment 4 | -------------------------------------------------------------------------------- /server/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from . import views 3 | 4 | urlpatterns = [ 5 | url(r'^twitter/mapping/extended', views.twitter_extended_mapping, name='twitter_extended_mapping'), 6 | url(r'^twitter/mapping', views.twitter_mapping, name='twitter_mapping'), 7 | url(r'^twitter/extended', views.extended_twitter_tpf_server, name='extended_twitter_tpf_server'), 8 | url(r'^twitter/', views.twitter_tpf_server, name='twitter_tpf_server'), 9 | url(r'^github/mapping/extended', views.github_extended_mapping, name='github_extended_mapping'), 10 | url(r'^github/mapping', views.github_mapping, name='github_mapping'), 11 | url(r'^github/extended', views.extended_github_tpf_server, name='extended_github_tpf_server'), 12 | url(r'^github/', views.github_tpf_server, name='github_tpf_server'), 13 | url(r'^linkedin/mapping/extended', views.linkedin_extended_mapping, name='linkedin_extended_mapping'), 14 | url(r'^linkedin/mapping', views.linkedin_mapping, name='linkedin_mapping'), 15 | url(r'^linkedin/authentification/', views.linkedin_authentication_tpf_server, name='linkedin_authentication_tpf_server'), 16 | url(r'^linkedin/extended', views.extended_linkedin_tpf_server, name='extended_linkedin_tpf_server'), 17 | url(r'^linkedin/', views.linkedin_tpf_server, name='linkedin_tpf_server') 18 | 19 | ] 20 | -------------------------------------------------------------------------------- /server/views.py: -------------------------------------------------------------------------------- 1 | from odmtp.odmtp import Odmtp 2 | from odmtp.modules.trimmer_xr2rml_twitter import TrimmerXr2rmlTwitter 3 | from odmtp.modules.trimmer_xr2rml_github import TrimmerXr2rmlGithub 4 | from odmtp.modules.trimmer_xr2rml_linkedin import TrimmerXr2rmllinkedin 5 | 6 | from odmtp.modules.tp2query_twitter import Tp2QueryTwitter 7 | from odmtp.modules.tp2query_github import Tp2QueryGithub 8 | from odmtp.modules.tp2query_linkedin import Tp2QueryLinkedin 9 | 10 | from odmtp.modules.mapper_twitter_xr2rml import MapperTwitterXr2rml 11 | from odmtp.modules.mapper_github_xr2rml import MapperGithubXr2rml 12 | from odmtp.modules.mapper_linkedin_xr2rml import MapperlinkedinXr2rml 13 | 14 | from tpf.tpq import TriplePatternQuery 15 | from tpf.fragment import Fragment 16 | 17 | from utils.management_token import get_client_ip, linkedin_verification_ip_token_date 18 | from utils.rml_closer import OWLLiteCloser, RDFSCloser 19 | 20 | from django.http.response import HttpResponse 21 | from django.views.decorators.http import require_http_methods 22 | from django.shortcuts import redirect 23 | 24 | from linkedin import linkedin 25 | from django.conf import settings 26 | from datetime import datetime 27 | from rdflib import Graph 28 | import json 29 | import os 30 | 31 | 32 | @require_http_methods(['GET', 'HEAD', 'OPTIONS']) 33 | def twitter_tpf_server(request): 34 | tpq = TriplePatternQuery(request.GET.get('page', '1'), 35 | request.GET.get('subject'), 36 | request.GET.get('predicate'), 37 | request.GET.get('object')) 38 | fragment = Fragment() 39 | odmtp = request.session.get('odmtp_twitter') 40 | if not odmtp: 41 | odmtp = Odmtp(TrimmerXr2rmlTwitter(), Tp2QueryTwitter(), MapperTwitterXr2rml()) 42 | request.session['odmtp_twitter'] = odmtp 43 | odmtp.match(tpq, fragment, request) 44 | response = HttpResponse( 45 | fragment.serialize(), 46 | content_type='application/trig; charset=utf-8') 47 | response['Content-Disposition'] = 'attachment; filename="twitter_tpf_fragment.trig"' 48 | response['Access-Control-Allow-Origin'] = '*' 49 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 50 | return response 51 | 52 | 53 | @require_http_methods(['GET', 'HEAD', 'OPTIONS']) 54 | def extended_twitter_tpf_server(request): 55 | tpq = TriplePatternQuery(request.GET.get('page', '1'), 56 | request.GET.get('subject'), 57 | request.GET.get('predicate'), 58 | request.GET.get('object')) 59 | fragment = Fragment() 60 | odmtp = request.session.get('extended_odmtp_twitter') 61 | if not odmtp: 62 | odmtp = Odmtp(TrimmerXr2rmlTwitter(True), Tp2QueryTwitter(), MapperTwitterXr2rml()) 63 | request.session['extended_odmtp_twitter'] = odmtp 64 | odmtp.match(tpq, fragment, request, extended=True) 65 | response = HttpResponse( 66 | fragment.serialize(), 67 | content_type='application/trig; charset=utf-8') 68 | response['Content-Disposition'] = 'attachment; filename="twitter_tpf_fragment.trig"' 69 | response['Access-Control-Allow-Origin'] = '*' 70 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 71 | return response 72 | 73 | 74 | @require_http_methods(['GET']) 75 | def twitter_mapping(request): 76 | mapping = Graph().parse('./mapping/mapping_tweet.ttl', format='ttl') 77 | response = HttpResponse( 78 | mapping.serialize(format='turtle'), 79 | content_type='text/turtle; charset=utf-8') 80 | response['Access-Control-Allow-Origin'] = '*' 81 | return response 82 | 83 | 84 | @require_http_methods(['GET']) 85 | def twitter_extended_mapping(request): 86 | extended_mapping = Graph().parse('./mapping/mapping_tweet.ttl', format='ttl') 87 | rml_closer = OWLLiteCloser() 88 | rml_closer.setOnto(Graph().parse('./ontologie/twitter_ontologie.ttl', format='ttl')) 89 | rml_closer.setRML(extended_mapping) 90 | rml_closer.enrich() 91 | extended_mapping = rml_closer.rml 92 | rml_closer = RDFSCloser() 93 | rml_closer.setOnto(Graph().parse('./ontologie/twitter_ontologie.ttl', format='ttl')) 94 | rml_closer.setRML(extended_mapping) 95 | rml_closer.enrich() 96 | extended_mapping = rml_closer.rml 97 | response = HttpResponse( 98 | extended_mapping.serialize(format='turtle'), 99 | content_type='text/turtle; charset=utf-8') 100 | response['Access-Control-Allow-Origin'] = '*' 101 | return response 102 | 103 | 104 | @require_http_methods(['GET', 'HEAD', 'OPTIONS']) 105 | def github_tpf_server(request): 106 | tpq = TriplePatternQuery(request.GET.get('page', '1'), 107 | request.GET.get('subject'), 108 | request.GET.get('predicate'), 109 | request.GET.get('object')) 110 | fragment = Fragment() 111 | odmtp = request.session.get('odmtp_github') 112 | if not odmtp: 113 | odmtp = Odmtp(TrimmerXr2rmlGithub(), Tp2QueryGithub(), MapperGithubXr2rml()) 114 | request.session['odmtp_github'] = odmtp 115 | odmtp.match(tpq, fragment, request) 116 | response = HttpResponse( 117 | fragment.serialize(), 118 | content_type='application/trig; charset=utf-8') 119 | response['Content-Disposition'] = 'attachment; filename="github_tpf_fragment.trig"' 120 | response['Access-Control-Allow-Origin'] = '*' 121 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 122 | return response 123 | 124 | 125 | @require_http_methods(['GET', 'HEAD', 'OPTIONS']) 126 | def extended_github_tpf_server(request): 127 | tpq = TriplePatternQuery(request.GET.get('page', '1'), 128 | request.GET.get('subject'), 129 | request.GET.get('predicate'), 130 | request.GET.get('object')) 131 | fragment = Fragment() 132 | odmtp = request.session.get('extended_odmtp_github') 133 | if not odmtp: 134 | odmtp = Odmtp(TrimmerXr2rmlGithub(True), Tp2QueryGithub(), MapperGithubXr2rml()) 135 | request.session['extended_odmtp_github'] = odmtp 136 | odmtp.match(tpq, fragment, request, extended=True) 137 | response = HttpResponse( 138 | fragment.serialize(), 139 | content_type='application/trig; charset=utf-8') 140 | response['Content-Disposition'] = 'attachment; filename="github_tpf_fragment.trig"' 141 | response['Access-Control-Allow-Origin'] = '*' 142 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 143 | return response 144 | 145 | 146 | @require_http_methods(['GET']) 147 | def github_mapping(request): 148 | mapping = Graph().parse('./mapping/mapping_github.ttl', format='ttl') 149 | response = HttpResponse( 150 | mapping.serialize(format='turtle'), 151 | content_type='text/turtle; charset=utf-8') 152 | response['Access-Control-Allow-Origin'] = '*' 153 | return response 154 | 155 | 156 | @require_http_methods(['GET']) 157 | def github_extended_mapping(request): 158 | extended_mapping = Graph().parse('./mapping/mapping_github.ttl', format='ttl') 159 | rml_closer = OWLLiteCloser() 160 | rml_closer.setOnto(Graph().parse('./ontologie/github_ontologie.ttl', format='ttl')) 161 | rml_closer.setRML(extended_mapping) 162 | rml_closer.enrich() 163 | extended_mapping = rml_closer.rml 164 | rml_closer = RDFSCloser() 165 | rml_closer.setOnto(Graph().parse('./ontologie/github_ontologie.ttl', format='ttl')) 166 | rml_closer.setRML(extended_mapping) 167 | rml_closer.enrich() 168 | extended_mapping = rml_closer.rml 169 | response = HttpResponse( 170 | extended_mapping.serialize(format='turtle'), 171 | content_type='text/turtle; charset=utf-8') 172 | response['Access-Control-Allow-Origin'] = '*' 173 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 174 | return response 175 | 176 | 177 | @require_http_methods(['GET', 'HEAD', 'OPTIONS']) 178 | def linkedin_tpf_server(request): 179 | tpq = TriplePatternQuery(request.GET.get('page', '1'), 180 | request.GET.get('subject'), 181 | request.GET.get('predicate'), 182 | request.GET.get('object')) 183 | fragment = Fragment() 184 | try: 185 | odmtp = request.session.get('odmtp_linkedin') 186 | if not odmtp: 187 | odmtp = Odmtp(TrimmerXr2rmllinkedin(), Tp2QueryLinkedin(), MapperlinkedinXr2rml()) 188 | request.session['odmtp_linkedin'] = odmtp 189 | odmtp.match(tpq, fragment, request) 190 | response = HttpResponse( 191 | fragment.serialize(), 192 | content_type='application/trig; charset=utf-8') 193 | response['Content-Disposition'] = 'attachment; filename="linkedin_tpf_fragment.trig"' 194 | except ValueError: 195 | response = HttpResponse("You need to be authenticated first. Go to linkedin/authentification/") 196 | response['Access-Control-Allow-Origin'] = '*' 197 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 198 | return response 199 | 200 | 201 | @require_http_methods(['GET', 'HEAD', 'OPTIONS']) 202 | def extended_linkedin_tpf_server(request): 203 | tpq = TriplePatternQuery(request.GET.get('page', '1'), 204 | request.GET.get('subject'), 205 | request.GET.get('predicate'), 206 | request.GET.get('object')) 207 | fragment = Fragment() 208 | try: 209 | odmtp = request.session.get('extended_odmtp_linkedin') 210 | if not odmtp: 211 | odmtp = Odmtp(TrimmerXr2rmllinkedin(True), Tp2QueryLinkedin(), MapperlinkedinXr2rml()) 212 | request.session['extended_odmtp_linkedin'] = odmtp 213 | odmtp.match(tpq, fragment, request, extended=True) 214 | response = HttpResponse( 215 | fragment.serialize(), 216 | content_type='application/trig; charset=utf-8') 217 | response['Content-Disposition'] = 'attachment; filename="linkedin_tpf_fragment.trig"' 218 | except ValueError: 219 | response = HttpResponse("You need to be authenticated first. Go to linkedin/authentification/") 220 | response['Access-Control-Allow-Origin'] = '*' 221 | response['Access-Control-Allow-Headers'] = 'Accept-Datetime,Accept' 222 | return response 223 | 224 | 225 | @require_http_methods(['GET']) 226 | def linkedin_mapping(request): 227 | mapping = Graph().parse('./mapping/mapping_linkedin.ttl', format='ttl') 228 | response = HttpResponse( 229 | mapping.serialize(format='turtle'), 230 | content_type='text/turtle; charset=utf-8') 231 | response['Access-Control-Allow-Origin'] = '*' 232 | return response 233 | 234 | 235 | @require_http_methods(['GET']) 236 | def linkedin_extended_mapping(request): 237 | extended_mapping = Graph().parse('./mapping/mapping_linkedin.ttl', format='ttl') 238 | rml_closer = OWLLiteCloser() 239 | rml_closer.setOnto(Graph().parse('./ontologie/linkedin_ontologie.ttl', format='ttl')) 240 | rml_closer.setRML(extended_mapping) 241 | rml_closer.enrich() 242 | extended_mapping = rml_closer.rml 243 | rml_closer = RDFSCloser() 244 | rml_closer.setOnto(Graph().parse('./ontologie/linkedin_ontologie.ttl', format='ttl')) 245 | rml_closer.setRML(extended_mapping) 246 | rml_closer.enrich() 247 | extended_mapping = rml_closer.rml 248 | response = HttpResponse( 249 | extended_mapping.serialize(format='turtle'), 250 | content_type='text/turtle; charset=utf-8') 251 | response['Access-Control-Allow-Origin'] = '*' 252 | return response 253 | 254 | 255 | @require_http_methods(['GET']) 256 | def linkedin_authentication_tpf_server(request): 257 | authentication = linkedin.LinkedInAuthentication(settings.CLIENT_ID_LINKEDIN, settings.CLIENT_SECRET_LINKEDIN, "http://{}/linkedin/authentification/".format(request.get_host()), ['r_emailaddress', 'r_basicprofile', 'w_share', 'rw_company_admin']) 258 | authorization_code = request.GET.get('code', None) 259 | if authorization_code: 260 | authentication.authorization_code = authorization_code 261 | linkedin_token = authentication.get_access_token() 262 | ip = get_client_ip(request) 263 | json_data = open(os.path.abspath('utils/users.json'), 'r') 264 | users = json.load(json_data) 265 | users[ip] = {} 266 | users[ip]['token'] = linkedin_token[0] 267 | today = datetime.now() 268 | users[ip]['Date'] = today.strftime('%Y-%m-%d %H:%M:%S.%f') 269 | f = open(os.path.abspath('utils/users.json'), "w") 270 | f.write(json.dumps(users, indent=4)) 271 | f.close() 272 | json_data.close() 273 | response = redirect('http://client.linkeddatafragments.org/#datasources=http%3A%2F%2Fodmtp.priloo.univ-nantes.fr%2Flinkedin%2F&query=SELECT%20%3Fs%20%3Fp%20%3Fo%0AWHERE%20%7B%0A%20%3Fs%20%3Fp%20%3Fo%0A%7D') 274 | else: 275 | if not linkedin_verification_ip_token_date(request): 276 | linkedin.LinkedInApplication(authentication) 277 | response = redirect(authentication.authorization_url) 278 | else: 279 | ip = get_client_ip(request) 280 | json_data = open(os.path.abspath('utils/users.json'), 'r') 281 | users = json.load(json_data) 282 | response = redirect('http://client.linkeddatafragments.org/#datasources=http%3A%2F%2Fodmtp.priloo.univ-nantes.fr%2Flinkedin%2F&query=SELECT%20%3Fs%20%3Fp%20%3Fo%0AWHERE%20%7B%0A%20%3Fs%20%3Fp%20%3Fo%0A%7D') 283 | json_data.close() 284 | response['Access-Control-Allow-Origin'] = '*' 285 | return response 286 | -------------------------------------------------------------------------------- /tpf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/tpf/__init__.py -------------------------------------------------------------------------------- /tpf/fragment.py: -------------------------------------------------------------------------------- 1 | from rdflib import Dataset, Namespace 2 | 3 | 4 | class Fragment(object): 5 | 6 | HYDRA = Namespace("http://www.w3.org/ns/hydra/core#") 7 | VOID = Namespace("http://rdfs.org/ns/void#") 8 | FOAF = Namespace("http://xmlns.com/foaf/0.1/") 9 | DCTERMS = Namespace("http://purl.org/dc/terms/") 10 | 11 | def __init__(self): 12 | self.rdf_graph = Dataset() 13 | 14 | def add_data_triple(self, subject, predicate, obj): 15 | self.rdf_graph.add((subject, predicate, obj)) 16 | 17 | def add_graph(self, identifier): 18 | self.rdf_graph.graph(identifier) 19 | 20 | def add_meta_quad(self, graph, subject, predicate, obj): 21 | self.rdf_graph.add((graph, subject, predicate, obj)) 22 | 23 | def add_prefix(self, prefix, uri): 24 | self.rdf_graph.bind(prefix, uri) 25 | 26 | def serialize(self): 27 | return self.rdf_graph.serialize(format="trig", encoding="utf-8") 28 | -------------------------------------------------------------------------------- /tpf/tpq.py: -------------------------------------------------------------------------------- 1 | from rdflib import URIRef, Literal 2 | 3 | from django.core.validators import URLValidator 4 | from django.core.exceptions import ValidationError 5 | 6 | 7 | class TriplePatternQuery(object): 8 | 9 | def __init__(self, page, subject, predicate, obj): 10 | """Turn http parameters into a triple pattern query object using RDFlib objects.""" 11 | self.page = int(page) 12 | self.subject = URIRef(subject) if subject else None 13 | self.predicate = URIRef(predicate) if predicate else None 14 | self.obj = URIRef(obj) if obj else None 15 | if self.obj is not None: 16 | validator = URLValidator() 17 | try: 18 | validator(self.obj) 19 | self.obj = URIRef(self.obj) 20 | except ValidationError: 21 | self.obj = string_to_literal(self.obj, validator) 22 | 23 | def page(self): 24 | """Return Int page number.""" 25 | return self.page 26 | 27 | def subject(self): 28 | """Return RDFlib.URIRef subject.""" 29 | return self.subject 30 | 31 | def predicate(self): 32 | """Return RDFlib.URIRef predicate.""" 33 | return self.predicate 34 | 35 | def obj(self): 36 | """Return RDFlib.URIRef or RDFlib.Literal object.""" 37 | return self.obj 38 | 39 | 40 | def string_to_literal(string, urlvalidator): 41 | splited_literal = string.split('"') 42 | value = splited_literal[1] 43 | datatype = splited_literal[2].split('^^')[1] if splited_literal[2] else None 44 | try: 45 | urlvalidator(datatype) 46 | datatype = URIRef(datatype) 47 | except ValidationError: 48 | datatype = None 49 | return Literal(value, datatype=datatype) 50 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benj-moreau/odmtp-tpf/cd6d4deef23441bedf85fb3773e5a952f48fe11d/utils/__init__.py -------------------------------------------------------------------------------- /utils/github_api.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from urllib2 import urlopen, Request, HTTPError 4 | from django.conf import settings 5 | 6 | 7 | class ClientException(Exception): 8 | pass 9 | 10 | 11 | class GithubApi(object): 12 | """This class implements the Github api v3 authentication & request.""" 13 | 14 | def request(self, url): 15 | """Send an unauthenticated request to the Github API.""" 16 | request = Request(url) 17 | request.add_header('Authorization', 18 | 'Basic %s' % settings.TOKEN_GITHUB.decode('utf-8')) 19 | try: 20 | response = urlopen(request) 21 | except HTTPError: 22 | raise ClientException 23 | raw_data = response.read().decode('utf-8') 24 | data = json.loads(raw_data) 25 | return data 26 | -------------------------------------------------------------------------------- /utils/management_token.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import ipware 3 | import json 4 | import os 5 | 6 | USERS_FILE_PATH = './utils/users.json' 7 | 8 | 9 | def get_client_ip(request): 10 | client_ip, is_routable = ipware.get_client_ip(request) 11 | return client_ip 12 | 13 | 14 | def linkedin_verification_ip_token_date(request): 15 | ip = get_client_ip(request) 16 | my_file = os.path.isfile(USERS_FILE_PATH) 17 | if my_file: 18 | json_data = open(USERS_FILE_PATH, 'r') 19 | else: 20 | json_data = open(USERS_FILE_PATH, 'w') 21 | json_data.write("{}") 22 | json_data.close() 23 | json_data = open(USERS_FILE_PATH, 'r') 24 | users = json.load(json_data) 25 | if ip in users: 26 | user = users[ip] 27 | today = datetime.datetime.now() 28 | date_use = datetime.datetime.strptime(user['Date'], "%Y-%m-%d %H:%M:%S.%f") 29 | tmp = date_use+datetime.timedelta(days=60) 30 | if tmp > today: 31 | response = True 32 | else: 33 | del users[ip] 34 | f = open(USERS_FILE_PATH, "w") 35 | f.write(json.dumps(users, indent=4)) 36 | f.close() 37 | json_data.close() 38 | response = False 39 | else: 40 | response = False 41 | return response 42 | -------------------------------------------------------------------------------- /utils/rml_closer.py: -------------------------------------------------------------------------------- 1 | import rdflib 2 | 3 | from rdflib import RDFS, OWL, Namespace, URIRef 4 | 5 | RR = Namespace("http://www.w3.org/ns/r2rml#") 6 | RML = Namespace("http://semweb.mmlab.be/ns/rml#") 7 | QL = Namespace("http://semweb.mmlab.be/ns/ql#") 8 | 9 | # ================================================== 10 | # RML_CLOSER: https://github.com/edesmontils/RML-Closer/ 11 | # ================================================== 12 | 13 | class RMLCloser(object): 14 | """docstring for RMLCloser""" 15 | def __init__(self): 16 | super(RMLCloser, self).__init__() 17 | self.mappings = None 18 | self.onto = rdflib.Graph() 19 | self.rml = rdflib.Graph() 20 | self.rules1 = set() # rules r(m,s,l) 21 | self.rules2 = set() # rules r(m,s,l,pom,p) 22 | 23 | def init(self): 24 | self.mappings = dict() 25 | for m,s in self.rml.subject_objects(RR.subjectMap) : 26 | l = set() 27 | for o in self.rml.objects(m,RR.predicateObjectMap) : 28 | l.add(o) 29 | self.mappings[m] = (s,l) 30 | 31 | def enrich(self) : 32 | if self.mappings is None : self.init() 33 | change = True 34 | while change : 35 | change = False 36 | for (m, (s,l)) in self.mappings.items() : 37 | for r in self.rules1 : 38 | change = change or r(m,s,l) 39 | for pom in l : 40 | for p in self.rml.objects(pom,RR['predicate']) : 41 | for r in self.rules2 : 42 | change = change or r(m,s,l,pom,p) 43 | 44 | 45 | def loadRML(self,fileName) : 46 | self.rml.parse(fileName,format="ttl") 47 | # print("RML graph has %s statements." % len(self.rml)) 48 | 49 | def loadOnto(self,fileName) : 50 | self.onto.parse(fileName,format="ttl") 51 | # print("Ontology graph has %s statements." % len(self.onto)) 52 | 53 | def setRML(self, r) : 54 | assert isinstance(r,rdflib.Graph), "(setRML) r must be an rdflib.Graph" 55 | self.rml = r 56 | 57 | def setOnto(self, o) : 58 | assert isinstance(o,rdflib.Graph), "(setOnto) o must be an rdflib.Graph" 59 | self.onto = o 60 | 61 | #================================================== 62 | #================================================== 63 | 64 | class RDFSCloser(RMLCloser): 65 | """docstring for RDFSCloser""" 66 | def __init__(self): 67 | super(RDFSCloser, self).__init__() 68 | self.rules1 = (self.subsomptionRule, ) 69 | self.rules2 = (self.subpropertyRule, ) 70 | 71 | # =========================================================================================== 72 | # Gestion de la subsomption des concepts 73 | # =========================================================================================== 74 | # [ 75 | # (?m rr:subjectMap ?s) (?s rr:class ?C) 76 | # (?C rdfs:subClassOf ?D) 77 | # -> 78 | # (?s rr:class ?D) 79 | # ] 80 | def subsomptionRule(self,m,s,lpom) : 81 | change = False 82 | for c in self.rml.objects(s,RR['class']) : 83 | for d in self.onto.objects(c,RDFS.subClassOf) : 84 | t = (s,RR['class'],d) 85 | # print("(subClass) find: ",t) 86 | if t not in self.rml : 87 | # print("added") 88 | self.rml.add( t ) 89 | change = True 90 | return change 91 | 92 | # =========================================================================================== 93 | # Gestion de la subsomption des relations 94 | # =========================================================================================== 95 | # [ 96 | # (?m rr:predicateObjectMap ?s) (?s rr:predicate ?p) 97 | # (?p rdfs:subPropertyOf ?q) 98 | # -> 99 | # (?s rr:predicate ?q) 100 | # ] 101 | def subpropertyRule(self,m,s,lpom, pom, p): 102 | change = False 103 | for q in self.onto.objects(p, RDFS.subPropertyOf): 104 | t = (pom,RR['predicate'],q) 105 | # print("(subProperty) find: ",t) 106 | if t not in self.rml : 107 | # print("added") 108 | self.rml.add( t ) 109 | change = True 110 | return change 111 | 112 | 113 | # =========================================================================================== 114 | # Domains 115 | #{ ?x ?pred ?y . ?pred rdfs:domain ?c . } 116 | # => { ?x a ?c . } . 117 | # =========================================================================================== 118 | # [ 119 | # (?m rr:predicateObjectMap ?s) (?s rr:predicate ?p) (?m rr:subjectMap ?s) 120 | # (?p rdfs:domain ?d) noValue(?s rr:class ?d) 121 | # -> 122 | # (?s rr:class ?d) 123 | # ] 124 | def domainRule(self,m,s,lpom,pom,p) : 125 | change = False 126 | 127 | for d in self.onto.objects(p,RDFS.domain) : 128 | t = (s,RR['class'],d) 129 | # print("(domain) find: ",t) 130 | if t not in self.rml : 131 | # print("added") 132 | self.rml.add( t ) 133 | change = True 134 | return change 135 | 136 | # =========================================================================================== 137 | # Ranges 138 | #{ ?x ?pred ?y . ?pred rdfs:range ?c . } 139 | # => { ?y a ?c . } . 140 | # =========================================================================================== 141 | # [ 142 | # (?m rr:predicateObjectMap ?pom) (?po rr:predicate ?p) (?p rdfs:range ?d) 143 | # (?pom rr:objectMap ?o) (?o rr:parentTriplesMap ?m2) 144 | # (?m2 rr:subjectMap ?s2) noValue(?s rr:class ?d) 145 | # -> 146 | # (?s2 rr:class ?d) 147 | # ] 148 | def rangeRule(self,m,s,lpom,pom,p): 149 | change = False 150 | for d in self.onto.objects(p,RDFS.range) : 151 | for o in self.rml.objects(pom,RR.objectMap) : 152 | for m2 in self.rml.objects(o,RR.parentTriplesMap) : 153 | (s2,_) = self.mappings[m2] 154 | t = (s2,RR['class'],d) 155 | # print("(range) find: ",t) 156 | if t not in self.rml : 157 | # print("added") 158 | self.rml.add( t ) 159 | change = True 160 | return change 161 | 162 | 163 | #================================================== 164 | #================================================== 165 | 166 | class OWLLiteCloser(RDFSCloser): 167 | """docstring for OWLLiteCloser""" 168 | def __init__(self): 169 | super(OWLLiteCloser, self).__init__() 170 | self.rules1 += (self.sameAsClassRule, self.equivalentClassRule) 171 | self.rules2 += (self.sameAsPropertyRule, self.equivalentPropertyRule) 172 | 173 | # =========================================================================================== 174 | # sameAs : 175 | #{ ?s a ?C . ?C owl:sameAs ?D . } => { ?s a ?D .} . 176 | # =========================================================================================== 177 | # [ 178 | # (?m rr:subjectMap ?s) (?s rr:class ?C) 179 | # (?C owl:sameAs ?D) noValue(?s rr:class ?D) 180 | # -> 181 | # (?s rr:class ?D) 182 | # ] 183 | def sameAsClassRule(self,m,s,lpom) : 184 | change = False 185 | for c in self.rml.objects(s,RR['class']) : 186 | for d in self.onto.objects(c,OWL.sameAs) : 187 | t = (s,RR['class'],d) 188 | # print("(sameAs Class) find: ",t) 189 | if t not in self.rml : 190 | # print("added") 191 | self.rml.add( t ) 192 | change = True 193 | return change 194 | 195 | # =========================================================================================== 196 | # equivalentClass 197 | #{ ?x a ?class . ?class owl:equivalentClass ?equiv . } 198 | # => { ?x a ?equiv . } . 199 | # =========================================================================================== 200 | # [ 201 | # (?m rr:subjectMap ?s) (?s rr:class ?C) 202 | # (?C owl:equivalentClass ?D) noValue(?s rr:class ?D) 203 | # -> 204 | # (?s rr:class ?D) 205 | # ] 206 | def equivalentClassRule(self,m,s,lpom) : 207 | change = False 208 | for c in self.rml.objects(s,RR['class']) : 209 | for d in self.onto.objects(c,OWL.equivalentClass) : 210 | t = (s,RR['class'],d) 211 | # print("(equivalentClass) find: ",t) 212 | if t not in self.rml : 213 | # print("added") 214 | self.rml.add( t ) 215 | change = True 216 | return change 217 | 218 | # =========================================================================================== 219 | # sameAs : { ?s ?p ?o . ?p owl:sameAs ?x . } => { ?s ?x ?o .} . 220 | # =========================================================================================== 221 | # [ 222 | # (?m rr:predicateObjectMap ?s) (?s rr:predicate ?p) 223 | # (?p owl:sameAs ?q) noValue(?s rr:predicate ?q) 224 | # -> 225 | # (?s rr:predicate ?q) 226 | # ] 227 | def sameAsPropertyRule(self,m,s,lpom, pom, p): 228 | change = False 229 | for q in self.onto.objects(p,OWL.sameAs) : 230 | t = (pom,RR['predicate'],q) 231 | # print("(sameAs Property) find: ",t) 232 | if t not in self.rml : 233 | # print("added") 234 | self.rml.add( t ) 235 | change = True 236 | return change 237 | 238 | # =========================================================================================== 239 | # equivalentProperty 240 | #{ ?x ?pred ?y . ?pred owl:equivalentProperty ?equiv . } 241 | # => { ?x ?equiv ?y . } . 242 | # =========================================================================================== 243 | # [ 244 | # (?m rr:predicateObjectMap ?s) (?s rr:predicate ?p) 245 | # (?p owl:equivalentProperty ?q) noValue(?s rr:predicate ?q) 246 | # -> 247 | # (?s rr:predicate ?q) 248 | # ] 249 | def equivalentPropertyRule(self,m,s,lpom, pom, p): 250 | change = False 251 | for q in self.onto.objects(p,OWL.equivalentProperty) : 252 | t = (pom,RR['predicate'],q) 253 | # print("(equivalent Property) find: ",t) 254 | if t not in self.rml : 255 | # print("added") 256 | self.rml.add( t ) 257 | change = True 258 | return change 259 | -------------------------------------------------------------------------------- /utils/twitter_api.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from urllib2 import urlopen, Request, HTTPError 4 | from django.conf import settings 5 | 6 | 7 | API_ENDPOINT = 'https://api.twitter.com' 8 | API_VERSION = '1.1' 9 | REQUEST_TOKEN_URL = '%s/oauth2/token' % API_ENDPOINT 10 | REQUEST_RATE_LIMIT = '%s/%s/application/rate_limit_status.json' % \ 11 | (API_ENDPOINT, API_VERSION) 12 | 13 | 14 | class ClientException(Exception): 15 | pass 16 | 17 | 18 | class TwitterApi(object): 19 | """This class implements the Twitter's Application-only authentication & request.""" 20 | 21 | def __init__(self): 22 | self.access_token = '' 23 | 24 | def request(self, url): 25 | """Send an authenticated request to the Twitter API.""" 26 | if not self.access_token: 27 | self.access_token = self._get_access_token() 28 | request = Request(url) 29 | request.add_header('Authorization', 'Bearer %s' % self.access_token) 30 | try: 31 | response = urlopen(request) 32 | except HTTPError: 33 | raise ClientException 34 | raw_data = response.read().decode('utf-8') 35 | data = json.loads(raw_data) 36 | return data 37 | 38 | def rate_limit_status(self, resource=''): 39 | """Return a dict of rate limits by resource.""" 40 | response = self.request(REQUEST_RATE_LIMIT) 41 | if resource: 42 | resource_family = resource.split('/')[1] 43 | return response['resources'][resource_family][resource] 44 | return response 45 | 46 | def get_access_token(self): 47 | request = Request(REQUEST_TOKEN_URL) 48 | request.add_header('Content-Type', 49 | 'application/x-www-form-urlencoded;charset=UTF-8') 50 | request.add_header('Authorization', 51 | 'Basic %s' % settings.ENCODED_BEARER_TOKEN_TWITTER.decode('utf-8')) 52 | 53 | request_data = 'grant_type=client_credentials'.encode('ascii') 54 | request.data = request_data 55 | 56 | response = urlopen(request) 57 | raw_data = response.read().decode('utf-8') 58 | data = json.loads(raw_data) 59 | return data['access_token'] 60 | 61 | def set_access_token(self, access_token): 62 | self.access_token = access_token 63 | -------------------------------------------------------------------------------- /utils/xr2rml_mapper.py: -------------------------------------------------------------------------------- 1 | from rdflib import Graph, URIRef, Namespace, RDF 2 | 3 | from utils.xr2rml_mapping import Xr2rmlMapping 4 | from utils.rml_closer import OWLLiteCloser 5 | 6 | rr = Namespace("http://www.w3.org/ns/r2rml#") 7 | rml = Namespace("http://semweb.mmlab.be/ns/rml#") 8 | xrr = Namespace("http://www.i3s.unice.fr/ns/xr2rml#") 9 | 10 | 11 | class Xr2rmlMapper(object): 12 | """This class partialy implements the XR2RML mapping langage.""" 13 | 14 | def __init__(self, filename, ontology_filename=None): 15 | self.mapping = Graph() 16 | self.preprocessed_mapping = Graph() 17 | with open(filename, 'r') as content_file: 18 | file_content = content_file.read() 19 | self.mapping.parse(format="turtle", data=file_content) 20 | if ontology_filename: 21 | with open(ontology_filename, 'r') as content_file: 22 | ontology_content = content_file.read() 23 | ontology = Graph().parse(format="turtle", data=ontology_content) 24 | rml_closer = OWLLiteCloser() 25 | rml_closer.setOnto(ontology) 26 | rml_closer.setRML(self.mapping) 27 | rml_closer.enrich() 28 | self.mapping = rml_closer.rml 29 | self.logical_sources = {} 30 | self._preprocess_mapping() 31 | 32 | def get_mapping(self): 33 | return Xr2rmlMapping(self.preprocessed_mapping, self.logical_sources) 34 | 35 | def _preprocess_mapping(self): 36 | resources = {} 37 | for s in self.mapping.subjects(): 38 | if isinstance(s, URIRef) and s not in resources: 39 | for node in self.mapping.objects(subject=s, predicate=rr.subjectMap): 40 | for template in self.mapping.objects(subject=node, predicate=rr.template): 41 | resources[s] = template 42 | for type_class in self.mapping.objects(subject=node, predicate=rr['class']): 43 | self.preprocessed_mapping.add((resources[s], RDF.type, type_class)) 44 | for node in self.mapping.objects(subject=s, predicate=xrr.logicalSource): 45 | subject_prefix = resources[s].split('{')[0] 46 | self.logical_sources[subject_prefix] = {} 47 | for query in self.mapping.objects(subject=node, predicate=xrr.query): 48 | self.logical_sources[subject_prefix]['query'] = query 49 | for iterator in self.mapping.objects(subject=node, predicate=rml.iterator): 50 | self.logical_sources[subject_prefix]['iterator'] = iterator 51 | for s in resources: 52 | for node in self.mapping.objects(subject=s, predicate=rr.predicateObjectMap): 53 | predicate = None 54 | for predicate_object in self.mapping.objects(subject=node, predicate=rr.predicate): 55 | predicate = predicate_object 56 | for object_map in self.mapping.objects(subject=node, predicate=rr.objectMap): 57 | for reference in self.mapping.objects(subject=object_map, predicate=xrr.reference): 58 | self.preprocessed_mapping.add((resources[s], predicate, reference)) 59 | for parent in self.mapping.objects(subject=object_map, predicate=rr.parentTriplesMap): 60 | if parent != resources[s]: 61 | self.preprocessed_mapping.add((resources[s], predicate, resources[parent])) 62 | -------------------------------------------------------------------------------- /utils/xr2rml_mapping.py: -------------------------------------------------------------------------------- 1 | class Xr2rmlMapping(object): 2 | """This class represents a xr2rml mapping.""" 3 | 4 | def __init__(self, mapping_graph, logical_sources): 5 | self.mapping = mapping_graph 6 | self.logical_sources = logical_sources 7 | 8 | def mapping(self): 9 | return self.mapping 10 | 11 | def logical_sources(self): 12 | return self.logical_sources 13 | 14 | def print_mapping(self): 15 | print(self.logical_sources) 16 | for s, p, o in self.mapping: 17 | print("s=%s" % s) 18 | print("p=%s" % p) 19 | print("o=%s" % o) 20 | --------------------------------------------------------------------------------