├── .github └── workflows │ ├── maven-publish.yml │ └── maven.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── LICENSE.md ├── README.md ├── _config.yml ├── examples └── owl2sparql-examples.html ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── aksw │ │ └── owl2sparql │ │ ├── OWLAxiomToSPARQLConverter.java │ │ ├── OWLClassExpressionToSPARQLConverter.java │ │ ├── OWLObjectPropertyExpressionConverter.java │ │ ├── style │ │ ├── AllQuantorTranslation.java │ │ ├── EqualityRendering.java │ │ ├── NominalTranslation.java │ │ └── OWLThingRendering.java │ │ └── util │ │ ├── OWLClassExpressionMinimizer.java │ │ ├── PermutationsOfN.java │ │ ├── VarGenerator.java │ │ └── VariablesMapping.java └── resources │ └── log4j.properties └── test ├── java └── org │ └── aksw │ └── owl2sparql │ ├── OWLAxiomToSPARQLConverterTest.java │ └── example │ ├── HTMLTableBuilder.java │ └── OWLClassExpressionConversionExamples.java └── resources └── log4j.properties /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up JDK 1.8 18 | uses: actions/setup-java@v1 19 | with: 20 | java-version: 1.8 21 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 22 | settings-path: ${{ github.workspace }} # location for the settings.xml file 23 | 24 | - name: Build with Maven 25 | run: mvn -B package --file pom.xml 26 | 27 | - name: Publish to GitHub Packages Apache Maven 28 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 29 | env: 30 | GITHUB_TOKEN: ${{ github.token }} 31 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ master, develop ] 9 | pull_request: 10 | branches: [ master, develop ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Build with Maven 24 | run: mvn -B package --file pom.xml 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to OWL2SPARQL 2 | 3 | ## Have a question or problem? 4 | If you have questions about how to use OWL2SPARQL, feel free to send an email to buehmann@informatik.uni-leipzig.de, or [open an issue on the tracker](https://github.com/aksw/owl2sparql/issues). 5 | 6 | ## Found an issue? 7 | If you find a bug in OWL2SPARQL, please [open an issue on GitHub](https://github.com/aksw/owl2sparql/issues). If you would like to create a fix yourself, pull requests are welcome. 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OWL2SPARQL - "Yet another OWL To SPARQL Query rewriter?!" 2 | 3 | [![Build Status](https://github.com/SmartDataAnalytics/OWL2SPARQL/workflows/Java%20CI%20with%20Maven/badge.svg)](https://github.com/SmartDataAnalytics/OWL2SPARQL/workflows/Java%20CI%20with%20Maven) 4 | 5 | Coverity Scan Build Status 7 | 8 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/9b16e876e6784a80b6d6a15b70df2ab2)](https://www.codacy.com/app/conpcomplete/OWL2SPARQL?utm_source=github.com&utm_medium=referral&utm_content=AKSW/OWL2SPARQL&utm_campaign=Badge_Grade) 9 | 10 | This project provides a simple converter from OWL axioms and OWL class expressions to SPARQL queries. 11 | 12 | ## Maven Settings 13 | ```XML 14 | 15 | 16 | maven.aksw.internal 17 | University Leipzig, AKSW Maven2 Repository 18 | http://maven.aksw.org/archiva/repository/internal 19 | 20 | 21 | 22 | maven.aksw.snapshots 23 | University Leipzig, AKSW Maven2 Repository 24 | http://maven.aksw.org/archiva/repository/snapshots 25 | 26 | 27 | 28 | 29 | 30 | org.aksw.owl2sparql 31 | owl2sparql-core 32 | 0.1 33 | 34 | 35 | ... 36 | 37 | ``` 38 | 39 | ## From OWL axiom to SPARQL query 40 | 41 | ### Usage 42 | ```Java 43 | // create the converter 44 | OWLAxiomToSPARQLConverter converter = new OWLAxiomToSPARQLConverter("?s","?o"); 45 | 46 | // provide some OWL axiom using OWL API datastructures 47 | OWLAxiom axiom = ...; 48 | 49 | // convert the axiom into a SPARQL query 50 | String queryString = converter.convert(axiom); 51 | ``` 52 | 53 | ### Example 54 | OWL axiom (in Manchester OWL Syntax) 55 | ``` 56 | PREFIX: : 57 | ObjectProperty: r 58 | Domain: A 59 | ``` 60 | SPARQL query 61 | ```sparql 62 | PREFIX : 63 | SELECT DISTINCT ?s 64 | WHERE 65 | { ?s :r ?s0 . 66 | ?s a :A 67 | } 68 | ``` 69 | ## From OWL class expression to SPARQL query 70 | 71 | ### Usage 72 | ```Java 73 | // create the converter 74 | OWLClassExpressionToSPARQLConverter converter = new OWLClassExpressionToSPARQLConverter(); 75 | 76 | // provide some OWL class expression using OWL API datastructures 77 | OWLClassExpression ce = ...; 78 | 79 | // convert the class expression into a SPARQL query 80 | String queryString = converter.convert(ce); 81 | ``` 82 | 83 | ### Example 84 | OWL class expression (in Manchester OWL Syntax) 85 | ``` 86 | PREFIX: : 87 | A and ( B or not (r some B)) 88 | ``` 89 | SPARQL query 90 | ```sparql 91 | PREFIX : 92 | SELECT DISTINCT ?x 93 | WHERE 94 | { ?x a :A 95 | { ?x a :B } 96 | UNION 97 | { ?x ?p ?o 98 | FILTER NOT EXISTS { 99 | ?x :r ?s0 . 100 | ?s0 a :B 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | ## License 107 | The source code of this repo is published under the [Apache License Version 2.0](https://github.com/AKSW/owl2sparql/blob/master/LICENSE). 108 | 109 | This project makes use of several dependencies: When in doubt, please cross-check with the respective projects: 110 | * [OWL API](https://github.com/owlcs/owlapi) (Apache License 2.0 and GNU LGPL Version 3.0) 111 | * [Apache Jena](https://jena.apache.org/) (Apache License 2.0) 112 | * [Guava](http://code.google.com/p/guava-libraries/) (Apache License 2.0) 113 | 114 | ## More Examples 115 | 116 | 117 | 118 | 119 | 126 | 140 | 150 | 162 | 172 | 184 | 196 | 206 | 224 | 235 | 249 | 264 | 281 | 293 | 303 | 317 | 326 | 332 | 341 | 353 | 361 | 369 | 380 | 391 | 399 | 414 | 423 | 431 | 437 | 448 | 457 | 465 | 473 | 482 | 490 | 498 | 509 | 519 |
Class ExpressionSPARQL Query
A
BASE    <http://example.org/ontology/>
120 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
121 | 
122 | SELECT DISTINCT  ?x
123 | WHERE
124 |   { ?x rdf:type <A>}
125 | 
A
127 |  and (B or (not (r some Thing)))
BASE    <http://example.org/ontology/>
128 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
129 | 
130 | SELECT DISTINCT  ?x
131 | WHERE
132 |   { ?x rdf:type <A>
133 |       { ?x rdf:type <B>}
134 |     UNION
135 |       { ?x ?p ?o
136 |         FILTER NOT EXISTS {?x <r> ?s0}
137 |       }
138 |   }
139 | 
A
141 |  and (not (B))
BASE    <http://example.org/ontology/>
142 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
143 | 
144 | SELECT DISTINCT  ?x
145 | WHERE
146 |   { ?x rdf:type <A>
147 |     FILTER NOT EXISTS {?x rdf:type <B>}
148 |   }
149 | 
A
151 |  and (not (r some B))
BASE    <http://example.org/ontology/>
152 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
153 | 
154 | SELECT DISTINCT  ?x
155 | WHERE
156 |   { ?x rdf:type <A>
157 |     FILTER NOT EXISTS {?x <r> ?s0 .
158 |       ?s0 rdf:type <B>
159 |     }
160 |   }
161 | 
A
163 |  and (r some  Self )
BASE    <http://example.org/ontology/>
164 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
165 | 
166 | SELECT DISTINCT  ?x
167 | WHERE
168 |   { ?x rdf:type <A> .
169 |     ?x <r> ?x
170 |   }
171 | 
A
173 |  and (t some boolean)
BASE    <http://example.org/ontology/>
174 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
175 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
176 | 
177 | SELECT DISTINCT  ?x
178 | WHERE
179 |   { ?x rdf:type <A> .
180 |     ?x <t> ?s0
181 |     FILTER ( datatype(?s0) = xsd:boolean )
182 |   }
183 | 
A
185 |  and (t some  not boolean)
BASE    <http://example.org/ontology/>
186 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
187 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
188 | 
189 | SELECT DISTINCT  ?x
190 | WHERE
191 |   { ?x rdf:type <A> .
192 |     ?x <t> ?s0
193 |     FILTER ( datatype(?s0) != xsd:boolean )
194 |   }
195 | 
A
197 |  and (t value 1)
BASE    <http://example.org/ontology/>
198 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
199 | 
200 | SELECT DISTINCT  ?x
201 | WHERE
202 |   { ?x rdf:type <A> .
203 |     ?x <t> 1
204 |   }
205 | 
A
207 |  and (t min 2 boolean)
BASE    <http://example.org/ontology/>
208 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
209 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
210 | 
211 | SELECT DISTINCT  ?x
212 | WHERE
213 |   { ?x rdf:type <A>
214 |     { SELECT  ?x
215 |       WHERE
216 |         { ?x <t> ?s0
217 |           FILTER ( datatype(?s0) = xsd:boolean )
218 |         }
219 |       GROUP BY ?x
220 |       HAVING ( COUNT(?s0) >= 2 )
221 |     }
222 |   }
223 | 
B
225 |  and (r some B)
BASE    <http://example.org/ontology/>
226 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
227 | 
228 | SELECT DISTINCT  ?x
229 | WHERE
230 |   { ?x rdf:type <B> .
231 |     ?x <r> ?s0 .
232 |     ?s0 rdf:type <B>
233 |   }
234 | 
B
236 |  and (r some B)
237 |  and (s some A)
BASE    <http://example.org/ontology/>
238 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
239 | 
240 | SELECT DISTINCT  ?x
241 | WHERE
242 |   { ?x rdf:type <B> .
243 |     ?x <r> ?s0 .
244 |     ?s0 rdf:type <B> .
245 |     ?x <s> ?s1 .
246 |     ?s1 rdf:type <A>
247 |   }
248 | 
B
250 |  and (r some 
251 |     (C
252 |      and (s some A)))
BASE    <http://example.org/ontology/>
253 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
254 | 
255 | SELECT DISTINCT  ?x
256 | WHERE
257 |   { ?x rdf:type <B> .
258 |     ?x <r> ?s0 .
259 |     ?s0 rdf:type <C> .
260 |     ?s0 <s> ?s1 .
261 |     ?s1 rdf:type <A>
262 |   }
263 | 
Place
265 |  and (language min 2 Language)
BASE    <http://example.org/ontology/>
266 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
267 | 
268 | SELECT DISTINCT  ?x
269 | WHERE
270 |   { ?x rdf:type <Place>
271 |     { SELECT  ?x
272 |       WHERE
273 |         { ?x <language> ?s0 .
274 |           ?s0 rdf:type <Language>
275 |         }
276 |       GROUP BY ?x
277 |       HAVING ( COUNT(?s0) >= 2 )
278 |     }
279 |   }
280 | 
(not (A))
282 |  and (r some (s some (not (B))))
BASE    <http://example.org/ontology/>
283 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
284 | 
285 | SELECT DISTINCT  ?x
286 | WHERE
287 |   { FILTER NOT EXISTS {?x rdf:type <A>}
288 |     ?x <r> ?s0 .
289 |     ?s0 <s> ?s1
290 |     FILTER NOT EXISTS {?s1 rdf:type <B>}
291 |   }
292 | 
A or B
BASE    <http://example.org/ontology/>
294 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
295 | 
296 | SELECT DISTINCT  ?x
297 | WHERE
298 |   {   { ?x rdf:type <A>}
299 |     UNION
300 |       { ?x rdf:type <B>}
301 |   }
302 | 
(not (A)) or (not (B))
BASE    <http://example.org/ontology/>
304 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
305 | 
306 | SELECT DISTINCT  ?x
307 | WHERE
308 |   {   { ?x ?p ?o
309 |         FILTER NOT EXISTS {?x rdf:type <A>}
310 |       }
311 |     UNION
312 |       { ?x ?p ?o
313 |         FILTER NOT EXISTS {?x rdf:type <B>}
314 |       }
315 |   }
316 | 
not (B)
BASE    <http://example.org/ontology/>
318 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
319 | 
320 | SELECT DISTINCT  ?x
321 | WHERE
322 |   { ?x ?p ?o
323 |     FILTER NOT EXISTS {?x rdf:type <B>}
324 |   }
325 | 
{a , b}
BASE    <http://example.org/ontology/>
327 | 
328 | SELECT DISTINCT  ?x
329 | WHERE
330 |   { VALUES ?x { <a> <b> }}
331 | 
r some B
BASE    <http://example.org/ontology/>
333 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
334 | 
335 | SELECT DISTINCT  ?x
336 | WHERE
337 |   { ?x <r> ?s0 .
338 |     ?s0 rdf:type <B>
339 |   }
340 | 
r some 
342 |     (A
343 |      and (not (B)))
BASE    <http://example.org/ontology/>
344 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
345 | 
346 | SELECT DISTINCT  ?x
347 | WHERE
348 |   { ?x <r> ?s0 .
349 |     ?s0 rdf:type <A>
350 |     FILTER NOT EXISTS {?s0 rdf:type <B>}
351 |   }
352 | 
r some ({a})
354 | (logically equivalent to
355 | r value a)
BASE    <http://example.org/ontology/>
356 | 
357 | SELECT DISTINCT  ?x
358 | WHERE
359 |   { ?x <r> <a>}
360 | 
r some ({a , b})
BASE    <http://example.org/ontology/>
362 | 
363 | SELECT DISTINCT  ?x
364 | WHERE
365 |   { ?x <r> ?s0
366 |     VALUES ?s0 { <a> <b> }
367 |   }
368 | 
language only Language
BASE    <http://example.org/ontology/>
370 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
371 | 
372 | SELECT DISTINCT  ?x
373 | WHERE
374 |   { ?x ?p ?o
375 |     FILTER NOT EXISTS {?x <language> ?s1
376 |       FILTER NOT EXISTS {?s1 rdf:type <Language>}
377 |     }
378 |   }
379 | 
r only B
BASE    <http://example.org/ontology/>
381 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
382 | 
383 | SELECT DISTINCT  ?x
384 | WHERE
385 |   { ?x ?p ?o
386 |     FILTER NOT EXISTS {?x <r> ?s1
387 |       FILTER NOT EXISTS {?s1 rdf:type <B>}
388 |     }
389 |   }
390 | 
r only Thing
392 | (logically equivalent to
393 | Thing)
BASE    <http://example.org/ontology/>
394 | 
395 | SELECT DISTINCT  ?x
396 | WHERE
397 |   { ?x ?p ?o}
398 | 
r only 
400 |     (A
401 |      and (s only Thing))
402 | (logically equivalent to
403 | r only A)
BASE    <http://example.org/ontology/>
404 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
405 | 
406 | SELECT DISTINCT  ?x
407 | WHERE
408 |   { ?x ?p ?o
409 |     FILTER NOT EXISTS {?x <r> ?s1
410 |       FILTER NOT EXISTS {?s1 rdf:type <A>}
411 |     }
412 |   }
413 | 
r only 
415 |     (A or (s only Thing))
416 | (logically equivalent to
417 | Thing)
BASE    <http://example.org/ontology/>
418 | 
419 | SELECT DISTINCT  ?x
420 | WHERE
421 |   { ?x ?p ?o}
422 | 
r only (s only Thing)
424 | (logically equivalent to
425 | Thing)
BASE    <http://example.org/ontology/>
426 | 
427 | SELECT DISTINCT  ?x
428 | WHERE
429 |   { ?x ?p ?o}
430 | 
r value a
BASE    <http://example.org/ontology/>
432 | 
433 | SELECT DISTINCT  ?x
434 | WHERE
435 |   { ?x <r> <a>}
436 | 
language min 2 Language
BASE    <http://example.org/ontology/>
438 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
439 | 
440 | SELECT DISTINCT  ?x
441 | WHERE
442 |   { ?x <language> ?s0 .
443 |     ?s0 rdf:type <Language>
444 |   }
445 | GROUP BY ?x
446 | HAVING ( COUNT(?s0) >= 2 )
447 | 
t some (integer or (boolean and {1 , 2}))
BASE    <http://example.org/ontology/>
449 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
450 | 
451 | SELECT DISTINCT  ?x
452 | WHERE
453 |   { ?x <t> ?s0
454 |     FILTER ( ( datatype(?s0) = xsd:integer ) || ( ( datatype(?s0) = xsd:boolean ) && ( ?s0 IN (1, 2) ) ) )
455 |   }
456 | 
t some  not ({1 , 2})
BASE    <http://example.org/ontology/>
458 | 
459 | SELECT DISTINCT  ?x
460 | WHERE
461 |   { ?x <t> ?s0
462 |     FILTER ( ?s0 NOT IN (1, 2) )
463 |   }
464 | 
t some {1 , 2}
BASE    <http://example.org/ontology/>
466 | 
467 | SELECT DISTINCT  ?x
468 | WHERE
469 |   { ?x <t> ?s0
470 |     FILTER ( ?s0 IN (1, 2) )
471 |   }
472 | 
t some (boolean and {1 , 2})
BASE    <http://example.org/ontology/>
474 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
475 | 
476 | SELECT DISTINCT  ?x
477 | WHERE
478 |   { ?x <t> ?s0
479 |     FILTER ( ( datatype(?s0) = xsd:boolean ) && ( ?s0 IN (1, 2) ) )
480 |   }
481 | 
t some PlainLiteral[length 10]
BASE    <http://example.org/ontology/>
483 | 
484 | SELECT DISTINCT  ?x
485 | WHERE
486 |   { ?x <t> ?s0
487 |     FILTER strlen(( str(?s0) = 10 ))
488 |   }
489 | 
t some integer[>= 3 , < 10]
BASE    <http://example.org/ontology/>
491 | 
492 | SELECT DISTINCT  ?x
493 | WHERE
494 |   { ?x <t> ?s0
495 |     FILTER ( ( ?s0 >= 3 ) && ( ?s0 < 10 ) )
496 |   }
497 | 
t only boolean
BASE    <http://example.org/ontology/>
499 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
500 | 
501 | SELECT DISTINCT  ?x
502 | WHERE
503 |   { ?x ?p ?o
504 |     FILTER NOT EXISTS {?x <t> ?s1
505 |       FILTER ( datatype(?s1) != xsd:boolean )
506 |     }
507 |   }
508 | 
t only {1}
BASE    <http://example.org/ontology/>
510 | 
511 | SELECT DISTINCT  ?x
512 | WHERE
513 |   { ?x ?p ?o
514 |     FILTER NOT EXISTS {?x <t> ?s1
515 |       FILTER ( ?s1 NOT IN (1) )
516 |     }
517 |   }
518 | 
520 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /examples/owl2sparql-examples.html: -------------------------------------------------------------------------------- 1 | OWL To SPARQL Converter 2 | 3 | 4 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | 74 | 84 | 96 | 106 | 118 | 130 | 140 | 158 | 169 | 183 | 198 | 215 | 227 | 237 | 251 | 260 | 266 | 275 | 287 | 295 | 303 | 314 | 325 | 333 | 348 | 357 | 365 | 371 | 382 | 391 | 399 | 407 | 416 | 424 | 432 | 443 | 453 |
Class ExpressionSPARQL Query
A
BASE    <http://example.org/ontology/>
 54 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 55 | 
 56 | SELECT DISTINCT  ?x
 57 | WHERE
 58 |   { ?x rdf:type <A>}
 59 | 
A
 61 |  and (B or (not (r some Thing)))
BASE    <http://example.org/ontology/>
 62 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 63 | 
 64 | SELECT DISTINCT  ?x
 65 | WHERE
 66 |   { ?x rdf:type <A>
 67 |       { ?x rdf:type <B>}
 68 |     UNION
 69 |       { ?x ?p ?o
 70 |         FILTER NOT EXISTS {?x <r> ?s0}
 71 |       }
 72 |   }
 73 | 
A
 75 |  and (not (B))
BASE    <http://example.org/ontology/>
 76 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 77 | 
 78 | SELECT DISTINCT  ?x
 79 | WHERE
 80 |   { ?x rdf:type <A>
 81 |     FILTER NOT EXISTS {?x rdf:type <B>}
 82 |   }
 83 | 
A
 85 |  and (not (r some B))
BASE    <http://example.org/ontology/>
 86 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 87 | 
 88 | SELECT DISTINCT  ?x
 89 | WHERE
 90 |   { ?x rdf:type <A>
 91 |     FILTER NOT EXISTS {?x <r> ?s0 .
 92 |       ?s0 rdf:type <B>
 93 |     }
 94 |   }
 95 | 
A
 97 |  and (r some  Self )
BASE    <http://example.org/ontology/>
 98 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 99 | 
100 | SELECT DISTINCT  ?x
101 | WHERE
102 |   { ?x rdf:type <A> .
103 |     ?x <r> ?x
104 |   }
105 | 
A
107 |  and (t some boolean)
BASE    <http://example.org/ontology/>
108 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
109 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
110 | 
111 | SELECT DISTINCT  ?x
112 | WHERE
113 |   { ?x rdf:type <A> .
114 |     ?x <t> ?s0
115 |     FILTER ( datatype(?s0) = xsd:boolean )
116 |   }
117 | 
A
119 |  and (t some  not boolean)
BASE    <http://example.org/ontology/>
120 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
121 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
122 | 
123 | SELECT DISTINCT  ?x
124 | WHERE
125 |   { ?x rdf:type <A> .
126 |     ?x <t> ?s0
127 |     FILTER ( datatype(?s0) != xsd:boolean )
128 |   }
129 | 
A
131 |  and (t value 1)
BASE    <http://example.org/ontology/>
132 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
133 | 
134 | SELECT DISTINCT  ?x
135 | WHERE
136 |   { ?x rdf:type <A> .
137 |     ?x <t> 1
138 |   }
139 | 
A
141 |  and (t min 2 boolean)
BASE    <http://example.org/ontology/>
142 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
143 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
144 | 
145 | SELECT DISTINCT  ?x
146 | WHERE
147 |   { ?x rdf:type <A>
148 |     { SELECT  ?x
149 |       WHERE
150 |         { ?x <t> ?s0
151 |           FILTER ( datatype(?s0) = xsd:boolean )
152 |         }
153 |       GROUP BY ?x
154 |       HAVING ( COUNT(?s0) >= 2 )
155 |     }
156 |   }
157 | 
B
159 |  and (r some B)
BASE    <http://example.org/ontology/>
160 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
161 | 
162 | SELECT DISTINCT  ?x
163 | WHERE
164 |   { ?x rdf:type <B> .
165 |     ?x <r> ?s0 .
166 |     ?s0 rdf:type <B>
167 |   }
168 | 
B
170 |  and (r some B)
171 |  and (s some A)
BASE    <http://example.org/ontology/>
172 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
173 | 
174 | SELECT DISTINCT  ?x
175 | WHERE
176 |   { ?x rdf:type <B> .
177 |     ?x <r> ?s0 .
178 |     ?s0 rdf:type <B> .
179 |     ?x <s> ?s1 .
180 |     ?s1 rdf:type <A>
181 |   }
182 | 
B
184 |  and (r some 
185 |     (C
186 |      and (s some A)))
BASE    <http://example.org/ontology/>
187 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
188 | 
189 | SELECT DISTINCT  ?x
190 | WHERE
191 |   { ?x rdf:type <B> .
192 |     ?x <r> ?s0 .
193 |     ?s0 rdf:type <C> .
194 |     ?s0 <s> ?s1 .
195 |     ?s1 rdf:type <A>
196 |   }
197 | 
Place
199 |  and (language min 2 Language)
BASE    <http://example.org/ontology/>
200 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
201 | 
202 | SELECT DISTINCT  ?x
203 | WHERE
204 |   { ?x rdf:type <Place>
205 |     { SELECT  ?x
206 |       WHERE
207 |         { ?x <language> ?s0 .
208 |           ?s0 rdf:type <Language>
209 |         }
210 |       GROUP BY ?x
211 |       HAVING ( COUNT(?s0) >= 2 )
212 |     }
213 |   }
214 | 
(not (A))
216 |  and (r some (s some (not (B))))
BASE    <http://example.org/ontology/>
217 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
218 | 
219 | SELECT DISTINCT  ?x
220 | WHERE
221 |   { FILTER NOT EXISTS {?x rdf:type <A>}
222 |     ?x <r> ?s0 .
223 |     ?s0 <s> ?s1
224 |     FILTER NOT EXISTS {?s1 rdf:type <B>}
225 |   }
226 | 
A or B
BASE    <http://example.org/ontology/>
228 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
229 | 
230 | SELECT DISTINCT  ?x
231 | WHERE
232 |   {   { ?x rdf:type <A>}
233 |     UNION
234 |       { ?x rdf:type <B>}
235 |   }
236 | 
(not (A)) or (not (B))
BASE    <http://example.org/ontology/>
238 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
239 | 
240 | SELECT DISTINCT  ?x
241 | WHERE
242 |   {   { ?x ?p ?o
243 |         FILTER NOT EXISTS {?x rdf:type <A>}
244 |       }
245 |     UNION
246 |       { ?x ?p ?o
247 |         FILTER NOT EXISTS {?x rdf:type <B>}
248 |       }
249 |   }
250 | 
not (B)
BASE    <http://example.org/ontology/>
252 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
253 | 
254 | SELECT DISTINCT  ?x
255 | WHERE
256 |   { ?x ?p ?o
257 |     FILTER NOT EXISTS {?x rdf:type <B>}
258 |   }
259 | 
{a , b}
BASE    <http://example.org/ontology/>
261 | 
262 | SELECT DISTINCT  ?x
263 | WHERE
264 |   { VALUES ?x { <a> <b> }}
265 | 
r some B
BASE    <http://example.org/ontology/>
267 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
268 | 
269 | SELECT DISTINCT  ?x
270 | WHERE
271 |   { ?x <r> ?s0 .
272 |     ?s0 rdf:type <B>
273 |   }
274 | 
r some 
276 |     (A
277 |      and (not (B)))
BASE    <http://example.org/ontology/>
278 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
279 | 
280 | SELECT DISTINCT  ?x
281 | WHERE
282 |   { ?x <r> ?s0 .
283 |     ?s0 rdf:type <A>
284 |     FILTER NOT EXISTS {?s0 rdf:type <B>}
285 |   }
286 | 
r some ({a})
288 | (logically equivalent to
289 | r value a)
BASE    <http://example.org/ontology/>
290 | 
291 | SELECT DISTINCT  ?x
292 | WHERE
293 |   { ?x <r> <a>}
294 | 
r some ({a , b})
BASE    <http://example.org/ontology/>
296 | 
297 | SELECT DISTINCT  ?x
298 | WHERE
299 |   { ?x <r> ?s0
300 |     VALUES ?s0 { <a> <b> }
301 |   }
302 | 
language only Language
BASE    <http://example.org/ontology/>
304 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
305 | 
306 | SELECT DISTINCT  ?x
307 | WHERE
308 |   { ?x ?p ?o
309 |     FILTER NOT EXISTS {?x <language> ?s1
310 |       FILTER NOT EXISTS {?s1 rdf:type <Language>}
311 |     }
312 |   }
313 | 
r only B
BASE    <http://example.org/ontology/>
315 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
316 | 
317 | SELECT DISTINCT  ?x
318 | WHERE
319 |   { ?x ?p ?o
320 |     FILTER NOT EXISTS {?x <r> ?s1
321 |       FILTER NOT EXISTS {?s1 rdf:type <B>}
322 |     }
323 |   }
324 | 
r only Thing
326 | (logically equivalent to
327 | Thing)
BASE    <http://example.org/ontology/>
328 | 
329 | SELECT DISTINCT  ?x
330 | WHERE
331 |   { ?x ?p ?o}
332 | 
r only 
334 |     (A
335 |      and (s only Thing))
336 | (logically equivalent to
337 | r only A)
BASE    <http://example.org/ontology/>
338 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
339 | 
340 | SELECT DISTINCT  ?x
341 | WHERE
342 |   { ?x ?p ?o
343 |     FILTER NOT EXISTS {?x <r> ?s1
344 |       FILTER NOT EXISTS {?s1 rdf:type <A>}
345 |     }
346 |   }
347 | 
r only 
349 |     (A or (s only Thing))
350 | (logically equivalent to
351 | Thing)
BASE    <http://example.org/ontology/>
352 | 
353 | SELECT DISTINCT  ?x
354 | WHERE
355 |   { ?x ?p ?o}
356 | 
r only (s only Thing)
358 | (logically equivalent to
359 | Thing)
BASE    <http://example.org/ontology/>
360 | 
361 | SELECT DISTINCT  ?x
362 | WHERE
363 |   { ?x ?p ?o}
364 | 
r value a
BASE    <http://example.org/ontology/>
366 | 
367 | SELECT DISTINCT  ?x
368 | WHERE
369 |   { ?x <r> <a>}
370 | 
language min 2 Language
BASE    <http://example.org/ontology/>
372 | PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
373 | 
374 | SELECT DISTINCT  ?x
375 | WHERE
376 |   { ?x <language> ?s0 .
377 |     ?s0 rdf:type <Language>
378 |   }
379 | GROUP BY ?x
380 | HAVING ( COUNT(?s0) >= 2 )
381 | 
t some (integer or (boolean and {1 , 2}))
BASE    <http://example.org/ontology/>
383 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
384 | 
385 | SELECT DISTINCT  ?x
386 | WHERE
387 |   { ?x <t> ?s0
388 |     FILTER ( ( datatype(?s0) = xsd:integer ) || ( ( datatype(?s0) = xsd:boolean ) && ( ?s0 IN (1, 2) ) ) )
389 |   }
390 | 
t some  not ({1 , 2})
BASE    <http://example.org/ontology/>
392 | 
393 | SELECT DISTINCT  ?x
394 | WHERE
395 |   { ?x <t> ?s0
396 |     FILTER ( ?s0 NOT IN (1, 2) )
397 |   }
398 | 
t some {1 , 2}
BASE    <http://example.org/ontology/>
400 | 
401 | SELECT DISTINCT  ?x
402 | WHERE
403 |   { ?x <t> ?s0
404 |     FILTER ( ?s0 IN (1, 2) )
405 |   }
406 | 
t some (boolean and {1 , 2})
BASE    <http://example.org/ontology/>
408 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
409 | 
410 | SELECT DISTINCT  ?x
411 | WHERE
412 |   { ?x <t> ?s0
413 |     FILTER ( ( datatype(?s0) = xsd:boolean ) && ( ?s0 IN (1, 2) ) )
414 |   }
415 | 
t some PlainLiteral[length 10]
BASE    <http://example.org/ontology/>
417 | 
418 | SELECT DISTINCT  ?x
419 | WHERE
420 |   { ?x <t> ?s0
421 |     FILTER strlen(( str(?s0) = 10 ))
422 |   }
423 | 
t some integer[>= 3 , < 10]
BASE    <http://example.org/ontology/>
425 | 
426 | SELECT DISTINCT  ?x
427 | WHERE
428 |   { ?x <t> ?s0
429 |     FILTER ( ( ?s0 >= 3 ) && ( ?s0 < 10 ) )
430 |   }
431 | 
t only boolean
BASE    <http://example.org/ontology/>
433 | PREFIX  xsd:  <http://www.w3.org/2001/XMLSchema#>
434 | 
435 | SELECT DISTINCT  ?x
436 | WHERE
437 |   { ?x ?p ?o
438 |     FILTER NOT EXISTS {?x <t> ?s1
439 |       FILTER ( datatype(?s1) != xsd:boolean )
440 |     }
441 |   }
442 | 
t only {1}
BASE    <http://example.org/ontology/>
444 | 
445 | SELECT DISTINCT  ?x
446 | WHERE
447 |   { ?x ?p ?o
448 |     FILTER NOT EXISTS {?x <t> ?s1
449 |       FILTER ( ?s1 NOT IN (1) )
450 |     }
451 |   }
452 | 
454 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.aksw.owl2sparql 6 | owl2sparql-core 7 | 0.1-SNAPSHOT 8 | jar 9 | 10 | owl2sparql-core 11 | A simple OWL to SPARQL converter 12 | https://github.com/AKSW/OWL2SPARQL 13 | 2015 14 | 15 | 16 | AKSW 17 | http://aksw.org 18 | 19 | 20 | 21 | 22 | Lorenz Buehmann 23 | buehmann@informatik.uni-leipzig.de 24 | 25 | lead developer 26 | 27 | http://aksw.org 28 | 29 | 30 | 31 | 32 | 33 | The Apache Software License, Version 2.0 34 | http://www.apache.org/licenses/LICENSE-2.0.txt 35 | repo 36 | A business-friendly OSS license 37 | 38 | 39 | 40 | 41 | scm:git:git@github.com:AKSW/owl2sparql.git 42 | HEAD 43 | 44 | 45 | 46 | 47 | maven.aksw.internal 48 | AKSW Internal Release Repository 49 | http://maven.aksw.org/archiva/repository/internal 50 | 51 | 52 | maven.aksw.snapshots 53 | AKSW Snapshot Repository 54 | http://maven.aksw.org/archiva/repository/snapshots 55 | 56 | 57 | 58 | 59 | UTF-8 60 | 1.8 61 | 1.8 62 | 63 | 64 | 65 | 66 | net.sourceforge.owlapi 67 | owlapi-distribution 68 | 4.2.4 69 | 70 | 71 | junit 72 | junit 73 | 4.12 74 | test 75 | 76 | 77 | com.google.guava 78 | guava 79 | 19.0 80 | 81 | 82 | org.apache.jena 83 | jena-arq 84 | 2.13.0 85 | 86 | 87 | 88 | 89 | 90 | 91 | maven-compiler-plugin 92 | 3.3 93 | 94 | ${maven.compiler.source} 95 | ${maven.compiler.target} 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-javadoc-plugin 101 | 2.10.3 102 | 103 | 104 | attach-javadoc 105 | verify 106 | 107 | jar 108 | 109 | 110 | 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-source-plugin 115 | 2.4 116 | 117 | 118 | attach-sources 119 | verify 120 | 121 | jar-no-fork 122 | 123 | 124 | 125 | 126 | 127 | org.codehaus.mojo 128 | license-maven-plugin 129 | 1.8 130 | 131 | apache_v2 132 | false 133 | true 134 | true 135 | 136 | src/main/java 137 | src/test/java 138 | 139 | 140 | 141 | 142 | validate 143 | 144 | check-file-header 145 | 146 | 147 | 148 | 149 | 150 | org.apache.maven.plugins 151 | maven-release-plugin 152 | 2.5.2 153 | 154 | false 155 | true 156 | 157 | 158 | 159 | 160 | 161 | 162 | GitHub 163 | https://github.com/AKSW/OWL2SPARQL/issues 164 | 165 | 166 | -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/OWLAxiomToSPARQLConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql; 21 | 22 | 23 | import java.util.LinkedList; 24 | import java.util.List; 25 | 26 | import org.aksw.owl2sparql.util.VarGenerator; 27 | import org.semanticweb.owlapi.model.ClassExpressionType; 28 | import org.semanticweb.owlapi.model.DataRangeType; 29 | import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom; 30 | import org.semanticweb.owlapi.model.OWLAnnotationPropertyDomainAxiom; 31 | import org.semanticweb.owlapi.model.OWLAnnotationPropertyRangeAxiom; 32 | import org.semanticweb.owlapi.model.OWLAsymmetricObjectPropertyAxiom; 33 | import org.semanticweb.owlapi.model.OWLAxiom; 34 | import org.semanticweb.owlapi.model.OWLAxiomVisitor; 35 | import org.semanticweb.owlapi.model.OWLClass; 36 | import org.semanticweb.owlapi.model.OWLClassAssertionAxiom; 37 | import org.semanticweb.owlapi.model.OWLClassExpression; 38 | import org.semanticweb.owlapi.model.OWLDataProperty; 39 | import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom; 40 | import org.semanticweb.owlapi.model.OWLDataPropertyDomainAxiom; 41 | import org.semanticweb.owlapi.model.OWLDataPropertyExpression; 42 | import org.semanticweb.owlapi.model.OWLDataPropertyRangeAxiom; 43 | import org.semanticweb.owlapi.model.OWLDataRange; 44 | import org.semanticweb.owlapi.model.OWLDatatypeDefinitionAxiom; 45 | import org.semanticweb.owlapi.model.OWLDeclarationAxiom; 46 | import org.semanticweb.owlapi.model.OWLDifferentIndividualsAxiom; 47 | import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom; 48 | import org.semanticweb.owlapi.model.OWLDisjointDataPropertiesAxiom; 49 | import org.semanticweb.owlapi.model.OWLDisjointObjectPropertiesAxiom; 50 | import org.semanticweb.owlapi.model.OWLDisjointUnionAxiom; 51 | import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom; 52 | import org.semanticweb.owlapi.model.OWLEquivalentDataPropertiesAxiom; 53 | import org.semanticweb.owlapi.model.OWLEquivalentObjectPropertiesAxiom; 54 | import org.semanticweb.owlapi.model.OWLFunctionalDataPropertyAxiom; 55 | import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom; 56 | import org.semanticweb.owlapi.model.OWLHasKeyAxiom; 57 | import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom; 58 | import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom; 59 | import org.semanticweb.owlapi.model.OWLIrreflexiveObjectPropertyAxiom; 60 | import org.semanticweb.owlapi.model.OWLNegativeDataPropertyAssertionAxiom; 61 | import org.semanticweb.owlapi.model.OWLNegativeObjectPropertyAssertionAxiom; 62 | import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom; 63 | import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom; 64 | import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; 65 | import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom; 66 | import org.semanticweb.owlapi.model.OWLReflexiveObjectPropertyAxiom; 67 | import org.semanticweb.owlapi.model.OWLSameIndividualAxiom; 68 | import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom; 69 | import org.semanticweb.owlapi.model.OWLSubClassOfAxiom; 70 | import org.semanticweb.owlapi.model.OWLSubDataPropertyOfAxiom; 71 | import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom; 72 | import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom; 73 | import org.semanticweb.owlapi.model.OWLSymmetricObjectPropertyAxiom; 74 | import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom; 75 | import org.semanticweb.owlapi.model.SWRLRule; 76 | 77 | import com.hp.hpl.jena.query.ParameterizedSparqlString; 78 | import com.hp.hpl.jena.query.Query; 79 | import com.hp.hpl.jena.query.QueryFactory; 80 | import com.hp.hpl.jena.query.Syntax; 81 | import org.slf4j.LoggerFactory; 82 | 83 | /** 84 | * A converter from OWL 2 85 | * axioms to SPARQL queries. 86 | * 87 | * @author Lorenz Buehmann 88 | * 89 | */ 90 | public class OWLAxiomToSPARQLConverter implements OWLAxiomVisitor{ 91 | 92 | private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(OWLAxiomToSPARQLConverter.class); 93 | 94 | private String subjectVar = "?x"; 95 | private String objectVar = "?o"; 96 | 97 | private boolean useDistinct = true; 98 | 99 | private OWLClassExpressionToSPARQLConverter expressionConverter; 100 | 101 | private String sparql; 102 | 103 | public OWLAxiomToSPARQLConverter() {} 104 | 105 | public OWLAxiomToSPARQLConverter(String targetSubjectVariable, String targetObjectVariable) { 106 | this.subjectVar = targetSubjectVariable; 107 | this.objectVar = targetObjectVariable; 108 | } 109 | 110 | /** 111 | * Converts an OWL axiom into a SPARQL query. 112 | * 113 | * @param axiom the OWL axiom to convert 114 | * @return the SPARQL query 115 | */ 116 | public String convert(OWLAxiom axiom){ 117 | return convert(axiom, subjectVar, objectVar); 118 | } 119 | 120 | /** 121 | * Converts an OWL axiom into a SPARQL query with targetSubjectVariable 122 | * as single projection variable. 123 | * @param axiom the OWL axiom to convert 124 | * @param targetSubjectVariable the name of the projection variable in the SPARQL 125 | * query 126 | * 127 | * @return the SPARQL query 128 | */ 129 | public String convert(OWLAxiom axiom, String targetSubjectVariable){ 130 | return convert(axiom, targetSubjectVariable, objectVar); 131 | } 132 | 133 | /** 134 | * Converts an OWL axiom into a SPARQL query with targetSubjectVariable 135 | * as single projection variable. 136 | * @param axiom the OWL axiom to convert 137 | * @param targetSubjectVariable the name of the subject projection variable in the SPARQL 138 | * query 139 | * @param targetObjectVariable the name of the object projection variable in the SPARQL 140 | * query 141 | * @return the SPARQL query 142 | */ 143 | public String convert(OWLAxiom axiom, String targetSubjectVariable, String targetObjectVariable) { 144 | this.subjectVar = targetSubjectVariable; 145 | this.objectVar = targetObjectVariable; 146 | 147 | LOGGER.debug("Converting axiom {}", axiom); 148 | sparql = ""; 149 | 150 | String queryString = createSelectClause() + createWhereClause(axiom); 151 | 152 | return queryString; 153 | } 154 | 155 | /** 156 | * Converts an OWL axiom into a SPARQL query using the default variable as 157 | * projection variable. 158 | * 159 | * @param axiom the OWL axiom 160 | * @return the SPARQL query 161 | */ 162 | public Query asQuery(OWLAxiom axiom){ 163 | return asQuery(axiom, subjectVar, objectVar); 164 | } 165 | 166 | /** 167 | * Converts an OWL axiom into a SPARQL query with targetSubjectVariable 168 | * as single projection variable. 169 | * @param axiom the OWL axiom to convert 170 | * @param targetSubjectVariable the name of the projection variable in the SPARQL 171 | * query 172 | * 173 | * @return the SPARQL query 174 | */ 175 | public Query asQuery(OWLAxiom axiom, String targetSubjectVariable){ 176 | return asQuery(axiom, targetSubjectVariable, objectVar); 177 | } 178 | 179 | /** 180 | * Converts an OWL axiom into a SPARQL query with targetSubjectVariable 181 | * as single projection variable. 182 | * @param axiom the OWL axiom to convert 183 | * @param targetSubjectVariable the name of the subject projection variable in the SPARQL 184 | * query 185 | * @param targetObjectVariable the name of the object projection variable in the SPARQL 186 | * query 187 | * @return the SPARQL query 188 | */ 189 | public Query asQuery(OWLAxiom axiom, String targetSubjectVariable, String targetObjectVariable){ 190 | 191 | String queryString = convert(axiom, targetSubjectVariable, targetObjectVariable); 192 | 193 | return QueryFactory.create(queryString, Syntax.syntaxARQ); 194 | } 195 | 196 | /** 197 | * Whether to return SPARQL queries with DISTINCT keyword. 198 | * @param useDistinct true if use DISTINCT, otherwise false 199 | */ 200 | public void setUseDistinct(boolean useDistinct) { 201 | this.useDistinct = useDistinct; 202 | } 203 | 204 | private String createSelectClause() { 205 | return "SELECT " + (useDistinct ? " DISTINCT " : "") + subjectVar; 206 | } 207 | 208 | private String createWhereClause(OWLAxiom axiom){ 209 | return " WHERE " + createGroupGraphPattern(axiom); 210 | } 211 | 212 | private String createGroupGraphPattern(OWLAxiom axiom) { 213 | expressionConverter = new OWLClassExpressionToSPARQLConverter(); 214 | axiom.accept(this); 215 | return "{" + sparql + "}"; 216 | } 217 | 218 | private String notExists(String pattern){ 219 | return "FILTER NOT EXISTS{" + pattern + "}"; 220 | } 221 | 222 | private String notExists(String targetVar, List classExpressions, boolean useUnion){ 223 | String pattern = ""; 224 | if(useUnion){ 225 | String unionPattern = ""; 226 | if(classExpressions.size() > 1){ 227 | for (int i = 0; i < classExpressions.size() - 1; i++) { 228 | unionPattern += "{" + expressionConverter.asGroupGraphPattern(classExpressions.get(i), targetVar) + "}"; 229 | unionPattern += " UNION "; 230 | } 231 | unionPattern += "{" + expressionConverter.asGroupGraphPattern(classExpressions.get(classExpressions.size() - 1), targetVar) + "}"; 232 | } else { 233 | unionPattern = expressionConverter.asGroupGraphPattern(classExpressions.get(0), targetVar); 234 | } 235 | pattern = notExists(unionPattern); 236 | } else { 237 | for (OWLClassExpression ce : classExpressions) { 238 | pattern += notExists(expressionConverter.asGroupGraphPattern(ce, targetVar)); 239 | } 240 | } 241 | return pattern; 242 | } 243 | 244 | /////////////////////////////////////////////////////////////////////////// 245 | // // 246 | // Class axioms // 247 | // // 248 | /////////////////////////////////////////////////////////////////////////// 249 | 250 | @Override 251 | public void visit(OWLSubClassOfAxiom axiom) { 252 | // process subclass 253 | OWLClassExpression subClass = axiom.getSubClass(); 254 | if(!subClass.isOWLThing()){// we do not need to convert owl:Thing 255 | String subClassPattern = expressionConverter.asGroupGraphPattern(subClass, subjectVar); 256 | sparql += subClassPattern; 257 | } 258 | 259 | // process superclass 260 | OWLClassExpression superClass = axiom.getSuperClass(); 261 | boolean needsOuterTriplePattern = subClass.isOWLThing() && 262 | (superClass.getClassExpressionType() == ClassExpressionType.OBJECT_COMPLEMENT_OF || 263 | superClass.getClassExpressionType() == ClassExpressionType.DATA_ALL_VALUES_FROM || 264 | superClass.getClassExpressionType() == ClassExpressionType.OBJECT_ALL_VALUES_FROM); 265 | String superClassPattern = expressionConverter.asGroupGraphPattern(superClass, subjectVar, 266 | needsOuterTriplePattern); 267 | sparql += superClassPattern; 268 | } 269 | 270 | @Override 271 | public void visit(OWLEquivalentClassesAxiom axiom) { 272 | List classExpressions = axiom.getClassExpressionsAsList(); 273 | 274 | for (OWLClassExpression ce : classExpressions) { 275 | sparql += expressionConverter.asGroupGraphPattern(ce, subjectVar); 276 | } 277 | } 278 | 279 | @Override 280 | public void visit(OWLDisjointClassesAxiom axiom) { 281 | List disjointClasses = axiom.getClassExpressionsAsList(); 282 | 283 | for(int i = 0; i < disjointClasses.size(); i++){ 284 | sparql += "{"; 285 | OWLClassExpression ce = disjointClasses.remove(i); 286 | sparql += expressionConverter.asGroupGraphPattern(ce, subjectVar); 287 | for (OWLClassExpression ce2 : disjointClasses) { 288 | sparql += notExists(expressionConverter.asGroupGraphPattern(ce2, subjectVar)); 289 | } 290 | disjointClasses.add(i, ce); 291 | sparql += "}"; 292 | if(i < disjointClasses.size()-1){ 293 | sparql += " UNION "; 294 | } 295 | } 296 | } 297 | 298 | @Override 299 | public void visit(OWLDisjointUnionAxiom axiom) { 300 | OWLClass cls = axiom.getOWLClass(); 301 | sparql += expressionConverter.asGroupGraphPattern(cls, subjectVar); 302 | 303 | List classExpressions = new LinkedList<>(axiom.getClassExpressions()); 304 | 305 | for(int i = 0; i < classExpressions.size(); i++){ 306 | sparql += "{"; 307 | OWLClassExpression ce = classExpressions.remove(i); 308 | 309 | // add triple pattern for class to be 310 | sparql += expressionConverter.asGroupGraphPattern(ce, subjectVar); 311 | 312 | // add NOT EXISTS for classes not to be 313 | sparql += notExists(subjectVar, classExpressions, false); 314 | 315 | classExpressions.add(i, ce); 316 | sparql += "}"; 317 | if(i < classExpressions.size()-1){ 318 | sparql += " UNION "; 319 | } 320 | } 321 | } 322 | 323 | /////////////////////////////////////////////////////////////////////////// 324 | // // 325 | // Property axioms // 326 | // // 327 | /////////////////////////////////////////////////////////////////////////// 328 | 329 | @Override 330 | public void visit(OWLSubObjectPropertyOfAxiom axiom) { 331 | OWLObjectPropertyExpression subPropertyExpression = axiom.getSubProperty(); 332 | if(subPropertyExpression.isAnonymous()){ 333 | sparql += objectVar + "<" + subPropertyExpression.getInverseProperty().asOWLObjectProperty().toStringID() + "> " + subjectVar + " ."; 334 | } else { 335 | sparql += subjectVar + "<" + subPropertyExpression.asOWLObjectProperty().toStringID() + "> " + objectVar + " ."; 336 | } 337 | 338 | OWLObjectPropertyExpression superPropertyExpression = axiom.getSuperProperty(); 339 | if(superPropertyExpression.isAnonymous()){ 340 | sparql += objectVar + "<" + superPropertyExpression.getInverseProperty().asOWLObjectProperty().toStringID() + "> " + subjectVar + " ."; 341 | } else { 342 | sparql += subjectVar + "<" + superPropertyExpression.asOWLObjectProperty().toStringID() + "> " + objectVar + " ."; 343 | } 344 | } 345 | 346 | @Override 347 | public void visit(OWLEquivalentObjectPropertiesAxiom axiom) { 348 | for (OWLObjectPropertyExpression propertyExpression : axiom.getProperties()) { 349 | if(propertyExpression.isAnonymous()){ 350 | sparql += objectVar + "<" + propertyExpression.getInverseProperty().asOWLObjectProperty().toStringID() + "> " + subjectVar + " ."; 351 | } else { 352 | sparql += subjectVar + "<" + propertyExpression.asOWLObjectProperty().toStringID() + "> " + objectVar + " ."; 353 | } 354 | } 355 | } 356 | 357 | @Override 358 | public void visit(OWLDisjointObjectPropertiesAxiom axiom) { 359 | List propertyExpressions = new LinkedList<>(axiom.getProperties()); 360 | 361 | for(int i = 0; i < propertyExpressions.size(); i++){ 362 | sparql += "{"; 363 | OWLObjectPropertyExpression pe = propertyExpressions.remove(i); 364 | if(pe.isAnonymous()){ 365 | sparql += objectVar + "<" + pe.getInverseProperty().asOWLObjectProperty().toStringID() + "> " + subjectVar + " ."; 366 | } else { 367 | sparql += subjectVar + "<" + pe.asOWLObjectProperty().toStringID() + "> " + objectVar + " ."; 368 | } 369 | for (OWLObjectPropertyExpression pe2 : propertyExpressions) { 370 | String pattern; 371 | if(pe2.isAnonymous()){ 372 | pattern = objectVar + "<" + pe2.getInverseProperty().asOWLObjectProperty().toStringID() + "> " + subjectVar + " ."; 373 | } else { 374 | pattern = subjectVar + "<" + pe2.asOWLObjectProperty().toStringID() + "> " + objectVar + " ."; 375 | } 376 | sparql += notExists(pattern); 377 | } 378 | propertyExpressions.add(i, pe); 379 | sparql += "}"; 380 | if(i < propertyExpressions.size()-1){ 381 | sparql += " UNION "; 382 | } 383 | } 384 | } 385 | 386 | @Override 387 | public void visit(OWLSubDataPropertyOfAxiom axiom) { 388 | OWLDataPropertyExpression subPropertyExpression = axiom.getSubProperty(); 389 | sparql += subjectVar + "<" + subPropertyExpression.asOWLDataProperty().toStringID() + "> " + objectVar + " ."; 390 | 391 | OWLDataPropertyExpression superPropertyExpression = axiom.getSuperProperty(); 392 | sparql += subjectVar + "<" + superPropertyExpression.asOWLDataProperty().toStringID() + "> " + objectVar + " ."; 393 | } 394 | 395 | @Override 396 | public void visit(OWLEquivalentDataPropertiesAxiom axiom) { 397 | for (OWLDataPropertyExpression propertyExpression : axiom.getProperties()) { 398 | sparql += subjectVar + "<" + propertyExpression.asOWLDataProperty().toStringID() + "> " + objectVar + " ."; 399 | } 400 | } 401 | 402 | @Override 403 | public void visit(OWLDisjointDataPropertiesAxiom axiom) { 404 | List propertyExpressions = new LinkedList<>(axiom.getProperties()); 405 | 406 | for(int i = 0; i < propertyExpressions.size(); i++){ 407 | sparql += "{"; 408 | OWLDataPropertyExpression pe = propertyExpressions.remove(i); 409 | sparql += subjectVar + "<" + pe.asOWLDataProperty().toStringID() + "> " + objectVar + " ."; 410 | for (OWLDataPropertyExpression pe2 : propertyExpressions) { 411 | String pattern = subjectVar + "<" + pe2.asOWLDataProperty().toStringID() + "> " + objectVar + " ."; 412 | sparql += notExists(pattern); 413 | } 414 | propertyExpressions.add(i, pe); 415 | sparql += "}"; 416 | if(i < propertyExpressions.size()-1){ 417 | sparql += " UNION "; 418 | } 419 | } 420 | } 421 | 422 | @Override 423 | public void visit(OWLObjectPropertyDomainAxiom axiom) { 424 | axiom.asOWLSubClassOfAxiom().accept(this); 425 | } 426 | 427 | @Override 428 | public void visit(OWLObjectPropertyRangeAxiom axiom) { 429 | OWLSubClassOfAxiom subClassOfAxiom = axiom.asOWLSubClassOfAxiom(); 430 | subClassOfAxiom.accept(this); 431 | String tmp = subjectVar; 432 | subjectVar = objectVar; 433 | objectVar = tmp; 434 | } 435 | 436 | @Override 437 | public void visit(OWLDataPropertyDomainAxiom axiom) { 438 | axiom.asOWLSubClassOfAxiom().accept(this); 439 | } 440 | 441 | @Override 442 | public void visit(OWLDataPropertyRangeAxiom axiom) { 443 | OWLDataRange range = axiom.getRange(); 444 | if (range.getDataRangeType() == DataRangeType.DATATYPE) { 445 | OWLDataProperty property = axiom.getProperty().asOWLDataProperty(); 446 | sparql += subjectVar + " <" + property.toStringID() + "> ?o." + "FILTER (DATATYPE(?o) = <" 447 | + range.asOWLDatatype().toStringID() + ">)"; 448 | String tmp = subjectVar; 449 | subjectVar = objectVar; 450 | objectVar = tmp; 451 | } else { 452 | throw new IllegalArgumentException("Datarange " + range + " not supported yet."); 453 | } 454 | } 455 | 456 | @Override 457 | public void visit(OWLAsymmetricObjectPropertyAxiom axiom) { 458 | String propertyURI = axiom.getProperty().asOWLObjectProperty().toStringID(); 459 | ParameterizedSparqlString query = new ParameterizedSparqlString("?s ?p ?o . FILTER NOT EXISTS{?o ?p ?s}"); 460 | query.setIri("p", propertyURI); 461 | sparql += query.toString(); 462 | } 463 | 464 | @Override 465 | public void visit(OWLSymmetricObjectPropertyAxiom axiom) { 466 | String propertyURI = axiom.getProperty().asOWLObjectProperty().toStringID(); 467 | ParameterizedSparqlString query = new ParameterizedSparqlString("?s ?p ?o . ?o ?p ?s ."); 468 | query.setIri("p", propertyURI); 469 | sparql += query.toString(); 470 | } 471 | 472 | @Override 473 | public void visit(OWLReflexiveObjectPropertyAxiom axiom) { 474 | axiom.asOWLSubClassOfAxiom().accept(this); 475 | } 476 | 477 | @Override 478 | public void visit(OWLIrreflexiveObjectPropertyAxiom axiom) { 479 | axiom.asOWLSubClassOfAxiom().accept(this); 480 | } 481 | 482 | @Override 483 | public void visit(OWLFunctionalObjectPropertyAxiom axiom) { 484 | axiom.asOWLSubClassOfAxiom().accept(this); 485 | } 486 | 487 | @Override 488 | public void visit(OWLInverseFunctionalObjectPropertyAxiom axiom) { 489 | axiom.asOWLSubClassOfAxiom().accept(this); 490 | } 491 | 492 | @Override 493 | public void visit(OWLTransitiveObjectPropertyAxiom axiom) { 494 | ParameterizedSparqlString template = new ParameterizedSparqlString( 495 | subjectVar + " ?p ?o1 . ?o1 ?p ?o . " + subjectVar + " ?p " + objectVar); 496 | template.setIri("p", axiom.getProperty().asOWLObjectProperty().toStringID()); 497 | sparql += template.toString(); 498 | } 499 | 500 | @Override 501 | public void visit(OWLFunctionalDataPropertyAxiom axiom) { 502 | axiom.asOWLSubClassOfAxiom().accept(this); 503 | } 504 | 505 | @Override 506 | public void visit(OWLSubPropertyChainOfAxiom axiom) { 507 | VarGenerator varGenerator = new VarGenerator(); 508 | 509 | List propertyChain = axiom.getPropertyChain(); 510 | String subjectVar = this.subjectVar; 511 | for (int i = 0; i < propertyChain.size() - 1; i++) { 512 | OWLObjectPropertyExpression propertyExpression = propertyChain.get(i); 513 | 514 | // new object var will be created 515 | String objectVar = varGenerator.newVar(); 516 | 517 | sparql += subjectVar + render(propertyExpression) + objectVar + " ."; 518 | 519 | // subject var becomes old object var 520 | subjectVar = objectVar; 521 | } 522 | sparql += subjectVar + render(propertyChain.get(propertyChain.size()-1)) + this.objectVar + " ."; 523 | 524 | OWLObjectPropertyExpression superProperty = axiom.getSuperProperty(); 525 | sparql += this.subjectVar + render(superProperty) + objectVar; 526 | } 527 | 528 | @Override 529 | public void visit(OWLInverseObjectPropertiesAxiom axiom) { 530 | axiom.asSubObjectPropertyOfAxioms().forEach(ax -> ax.accept(this)); 531 | } 532 | 533 | @Override 534 | public void visit(SWRLRule rule) { 535 | LOGGER.warn("Ignoring axiom {} . Reason: SWRL rules not supported.", rule); 536 | } 537 | 538 | @Override 539 | public void visit(OWLHasKeyAxiom axiom) { 540 | LOGGER.warn("Ignoring axiom {} . Reason: HasKey axiom not supported.", axiom); 541 | } 542 | 543 | private String render(OWLObjectPropertyExpression propertyExpression){ 544 | if(propertyExpression.isAnonymous()){ 545 | return "^" + render(propertyExpression.getInverseProperty()); 546 | } else { 547 | return "<" + propertyExpression.asOWLObjectProperty().toStringID() + ">"; 548 | } 549 | } 550 | 551 | /////////////////////////////////////////////////////////////////////////// 552 | // // 553 | // ABox axioms // 554 | // // 555 | /////////////////////////////////////////////////////////////////////////// 556 | 557 | @Override 558 | public void visit(OWLNegativeDataPropertyAssertionAxiom axiom) { 559 | aBoxAxiomsNotSupportedWarning(axiom); 560 | } 561 | 562 | @Override 563 | public void visit(OWLDifferentIndividualsAxiom axiom) { 564 | aBoxAxiomsNotSupportedWarning(axiom); 565 | } 566 | 567 | @Override 568 | public void visit(OWLObjectPropertyAssertionAxiom axiom) { 569 | aBoxAxiomsNotSupportedWarning(axiom); 570 | } 571 | 572 | @Override 573 | public void visit(OWLClassAssertionAxiom axiom) { 574 | aBoxAxiomsNotSupportedWarning(axiom); 575 | } 576 | 577 | @Override 578 | public void visit(OWLDataPropertyAssertionAxiom axiom) { 579 | aBoxAxiomsNotSupportedWarning(axiom); 580 | } 581 | 582 | @Override 583 | public void visit(OWLNegativeObjectPropertyAssertionAxiom axiom) { 584 | aBoxAxiomsNotSupportedWarning(axiom); 585 | } 586 | 587 | @Override 588 | public void visit(OWLSameIndividualAxiom axiom) { 589 | aBoxAxiomsNotSupportedWarning(axiom); 590 | } 591 | 592 | @Override 593 | public void visit(OWLDatatypeDefinitionAxiom axiom) { 594 | aBoxAxiomsNotSupportedWarning(axiom); 595 | } 596 | 597 | /////////////////////////////////////////////////////////////////////////// 598 | // // 599 | // Annotation axioms // 600 | // // 601 | /////////////////////////////////////////////////////////////////////////// 602 | 603 | @Override 604 | public void visit(OWLAnnotationAssertionAxiom axiom) { 605 | annotationAxiomsNotSupportedWarning(axiom); 606 | } 607 | 608 | @Override 609 | public void visit(OWLSubAnnotationPropertyOfAxiom axiom) { 610 | annotationAxiomsNotSupportedWarning(axiom); 611 | } 612 | 613 | @Override 614 | public void visit(OWLAnnotationPropertyDomainAxiom axiom) { 615 | annotationAxiomsNotSupportedWarning(axiom); 616 | } 617 | 618 | @Override 619 | public void visit(OWLAnnotationPropertyRangeAxiom axiom) { 620 | annotationAxiomsNotSupportedWarning(axiom); 621 | } 622 | 623 | @Override 624 | public void visit(OWLDeclarationAxiom axiom) { 625 | annotationAxiomsNotSupportedWarning(axiom); 626 | } 627 | 628 | private void aBoxAxiomsNotSupportedWarning(OWLAxiom axiom) { 629 | LOGGER.warn("Ignoring axiom {} . Reason: ABox axioms are not supported.", axiom); 630 | } 631 | 632 | private void annotationAxiomsNotSupportedWarning(OWLAxiom axiom) { 633 | LOGGER.warn("Ignoring axiom {} . Reason: Annotation axioms are not supported.", axiom); 634 | } 635 | } 636 | -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/OWLClassExpressionToSPARQLConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql; 21 | 22 | import com.google.common.base.Joiner; 23 | import com.google.common.collect.HashMultimap; 24 | import com.google.common.collect.Multimap; 25 | import com.google.common.collect.Sets; 26 | import com.hp.hpl.jena.query.Query; 27 | import com.hp.hpl.jena.query.QueryFactory; 28 | import com.hp.hpl.jena.query.Syntax; 29 | import com.hp.hpl.jena.sparql.algebra.Algebra; 30 | import com.hp.hpl.jena.sparql.algebra.Op; 31 | import org.aksw.owl2sparql.style.AllQuantorTranslation; 32 | import org.aksw.owl2sparql.style.EqualityRendering; 33 | import org.aksw.owl2sparql.style.NominalTranslation; 34 | import org.aksw.owl2sparql.style.OWLThingRendering; 35 | import org.aksw.owl2sparql.util.OWLClassExpressionMinimizer; 36 | import org.aksw.owl2sparql.util.VariablesMapping; 37 | import org.semanticweb.owlapi.apibinding.OWLManager; 38 | import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer; 39 | import org.semanticweb.owlapi.io.ToStringRenderer; 40 | import org.semanticweb.owlapi.model.*; 41 | import org.semanticweb.owlapi.util.DefaultPrefixManager; 42 | import org.semanticweb.owlapi.vocab.OWLFacet; 43 | import org.slf4j.Logger; 44 | import org.slf4j.LoggerFactory; 45 | import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 46 | 47 | import java.util.*; 48 | import java.util.stream.Collectors; 49 | 50 | import static org.semanticweb.owlapi.model.ClassExpressionType.OBJECT_MAX_CARDINALITY; 51 | 52 | /** 53 | * A converter from 54 | * OWL 2 class 55 | * expressions to SPARQL queries. 56 | * 57 | * @author Lorenz Buehmann 58 | * 59 | */ 60 | public class OWLClassExpressionToSPARQLConverter implements OWLClassExpressionVisitor, OWLDataRangeVisitor{ 61 | 62 | private static final Logger logger = LoggerFactory.getLogger(OWLClassExpressionToSPARQLConverter.class); 63 | 64 | private static final String TRIPLE_PATTERN = "%s %s %s .\n"; 65 | 66 | private OWLDataFactory df = new OWLDataFactoryImpl(); 67 | 68 | private Multimap properties = HashMultimap.create(); 69 | 70 | private Map intersection; 71 | private Set variableEntities = new HashSet<>(); 72 | 73 | private VariablesMapping mapping = new VariablesMapping(); 74 | 75 | private OWLClassExpression expr; 76 | 77 | private Deque naryExpressions = new ArrayDeque<>(); 78 | 79 | private OWLClassExpressionMinimizer minimizer = new OWLClassExpressionMinimizer(df); 80 | 81 | private boolean ignoreGenericTypeStatements = true; 82 | 83 | private boolean needOuterTriplePattern = true; 84 | 85 | private boolean useDistinct = true; 86 | 87 | private boolean useReasoning = false; 88 | 89 | private EqualityRendering equalityRendering = EqualityRendering.TERM_EQUALITY; 90 | 91 | private AllQuantorTranslation allQuantorTranslation = AllQuantorTranslation.DOUBLE_NEGATION; 92 | 93 | private OWLThingRendering owlThingRendering = OWLThingRendering.GENERIC_TRIPLE_PATTERN; 94 | 95 | private NominalTranslation nominalTranslation = NominalTranslation.VALUES; 96 | 97 | private String countVar = "?cnt"; 98 | 99 | private String sparql = ""; 100 | private String appendix = ""; 101 | private Stack variables = new Stack<>(); 102 | 103 | private boolean negatedDataRange = false; 104 | 105 | private Deque existentialFillers = new ArrayDeque<>(); 106 | 107 | public OWLClassExpressionToSPARQLConverter() {} 108 | 109 | public OWLClassExpressionToSPARQLConverter(VariablesMapping mapping) { 110 | this.mapping = mapping; 111 | } 112 | 113 | /** 114 | * Converts an OWL class expression into a SPARQL query with 115 | * rootVariable as projection variable. It's possible to 116 | * return it as COUNT query if wanted. 117 | * 118 | * @param ce the OWL class expression to convert 119 | * @param rootVariable the name of the projection variable in the SPARQL 120 | * query 121 | * @param countQuery whether to return a SELECT (COUNT(?var) as ?cnt) query 122 | * @return the SPARQL query 123 | */ 124 | public String convert(OWLClassExpression ce, String rootVariable, boolean countQuery){ 125 | return createSelectClause(countQuery) + createWhereClause(ce) + createSolutionModifier(); 126 | } 127 | 128 | /** 129 | * Converts an OWL class expression into a SPARQL query with 130 | * rootVariable as projection variable. 131 | * 132 | * @param ce the OWL class expression to convert 133 | * @param rootVariable the name of the projection variable in the SPARQL 134 | * query 135 | * @return the SPARQL query 136 | */ 137 | public Query asQuery(OWLClassExpression ce, String rootVariable){ 138 | return asQuery(rootVariable, ce, Collections.emptySet()); 139 | } 140 | 141 | /** 142 | * Converts an OWL class expression into a SPARQL query with 143 | * rootVariable as projection variable. It's possible to 144 | * return it as COUNT query if wanted. 145 | * 146 | * @param ce the OWL class expression to convert 147 | * @param rootVariable the name of the projection variable in the SPARQL 148 | * query 149 | * @param countQuery whether to return a SELECT (COUNT(?var) as ?cnt) query 150 | * @return the SPARQL query 151 | */ 152 | public Query asQuery(String rootVariable, OWLClassExpression ce, boolean countQuery){ 153 | String queryString = convert(ce, rootVariable, countQuery); 154 | 155 | return QueryFactory.create(queryString, Syntax.syntaxARQ); 156 | } 157 | 158 | /** 159 | * Converts an OWL class expression into a SPARQL query with 160 | * rootVariable as projection variable. It's possible to 161 | * declare a set of OWL entities which will be replaced by variables 162 | * in the query, that are then additionally used as projection variables 163 | * and grouping variables. 164 | * 165 | * @param ce the OWL class expression to convert 166 | * @param rootVariable the name of the projection variable in the SPARQL 167 | * query 168 | * @param variableEntities a set of entities that are replaced by variables 169 | * @return the SPARQL query 170 | */ 171 | public Query asQuery(String rootVariable, OWLClassExpression ce, Set variableEntities){ 172 | return asQuery(rootVariable, ce, variableEntities, false); 173 | } 174 | 175 | /** 176 | * Converts an OWL class expression into a SPARQL query with 177 | * rootVariable as projection variable. It's possible to 178 | * declare a set of OWL entities which will be replaced by variables 179 | * in the query, that are then additionally used as projection variables 180 | * and grouping variables. Moreover, it's possible to 181 | * return a COUNT query if wanted. 182 | * 183 | * @param ce the OWL class expression to convert 184 | * @param rootVariable the name of the projection variable in the SPARQL 185 | * query 186 | * @param variableEntities a set of entities that are replaced by variables 187 | * @param countQuery whether to return a SELECT (COUNT(?var) as ?cnt) query 188 | * @return the SPARQL query 189 | */ 190 | public Query asQuery(String rootVariable, OWLClassExpression ce, Set variableEntities, boolean countQuery){ 191 | this.variableEntities = variableEntities; 192 | 193 | String queryString = "SELECT DISTINCT "; 194 | 195 | String triplePattern = asGroupGraphPattern(ce, rootVariable, true); 196 | 197 | if(variableEntities.isEmpty()){ 198 | queryString += rootVariable + " WHERE {"; 199 | } else { 200 | for (OWLEntity owlEntity : variableEntities) { 201 | String var = mapping.get(owlEntity); 202 | queryString += var + " "; 203 | } 204 | if(countQuery){ 205 | queryString += "(COUNT(DISTINCT " + rootVariable + ") AS ?cnt)"; 206 | } else { 207 | queryString += rootVariable; 208 | } 209 | queryString += " WHERE {"; 210 | } 211 | 212 | queryString += triplePattern; 213 | queryString += "}"; 214 | 215 | if (countQuery && !variableEntities.isEmpty()) { 216 | queryString += "GROUP BY "; 217 | for (OWLEntity owlEntity : variableEntities) { 218 | String var = mapping.get(owlEntity); 219 | queryString += var; 220 | } 221 | queryString += " ORDER BY DESC(?cnt)"; 222 | } 223 | queryString += appendix; 224 | logger.debug("Query: {}", queryString); 225 | return QueryFactory.create(queryString, Syntax.syntaxSPARQL_11); 226 | } 227 | 228 | /** 229 | * Converts an OWL class expression into a GroupGraphPattern, which can be described 230 | * as the outer-most graph pattern in a query, sometimes also called the query pattern. 231 | * @param ce the OWL class expression 232 | * @param rootVariable the name of the projection variable 233 | * @return a SPARQL graph pattern 234 | */ 235 | public String asGroupGraphPattern(OWLClassExpression ce, String rootVariable){ 236 | return asGroupGraphPattern(ce, rootVariable, false); 237 | } 238 | 239 | /** 240 | * Converts an OWL class expression into a GroupGraphPattern, which can be described 241 | * as the outer-most graph pattern in a query, sometimes also called the query pattern. 242 | * @param ce the OWL class expression 243 | * @param rootVariable the name of the projection variable 244 | * @param needOuterTriplePattern whether 245 | * @return a SPARQL graph pattern 246 | */ 247 | public String asGroupGraphPattern(OWLClassExpression ce, String rootVariable, boolean needOuterTriplePattern){ 248 | this.needOuterTriplePattern = needOuterTriplePattern; 249 | reset(); 250 | variables.push(rootVariable); 251 | 252 | // minimize the class expression 253 | this.expr = minimizer.minimizeClone(ce); 254 | if(!expr.equals(ce)) { 255 | logger.info("CE rewritten to " + expr); 256 | } 257 | 258 | if(expr.equals(df.getOWLThing())) { 259 | logger.warn("Expression is logically equivalent to owl:Thing, thus, the SPARQL query returns all triples."); 260 | } 261 | 262 | // convert 263 | expr.accept(this); 264 | 265 | return sparql; 266 | } 267 | 268 | /** 269 | * Converts an OWL data range into a GroupGraphPattern. 270 | * @param dr the OWL data range 271 | * @param rootVariable the name of the projection variable 272 | * @return a SPARQL graph pattern 273 | */ 274 | public String asGroupGraphPattern(OWLDataRange dr, String rootVariable) 275 | { 276 | reset(); 277 | variables.push(rootVariable); 278 | 279 | // convert 280 | dr.accept(this); 281 | 282 | return sparql; 283 | } 284 | 285 | /** 286 | * Whether to return SPARQL queries with DISTINCT keyword. 287 | * @param useDistinct true if use DISTINCT, otherwise false 288 | */ 289 | public void setUseDistinct(boolean useDistinct) { 290 | this.useDistinct = useDistinct; 291 | } 292 | 293 | /** 294 | * Since SPARQL 1.1 there is a mechanism called property 295 | * paths (see W3C rec.), 296 | * which allows to add some kind of light-weight inferencing to a SPARQL query. 297 | * 298 | * Currently, we do the following if enabled 299 | * 300 | *
    301 | *
  • ?s rdf:type :A . -> ?s rdf:type/(rdfs:subClassOf|owl:equivalentClass)* :A .
  • 302 | *
303 | * 304 | * Note, this feature only works on query engines that support SPARQL 1.1 . 305 | * 306 | * @param useReasoning use inferencing 307 | */ 308 | public void setUseReasoning(boolean useReasoning) { 309 | this.useReasoning = useReasoning; 310 | } 311 | 312 | /** 313 | * How to express equality in SPARQL. 314 | * 315 | * @param equalityRendering the equalityRendering to set 316 | */ 317 | public void setEqualityRendering(EqualityRendering equalityRendering) { 318 | this.equalityRendering = equalityRendering; 319 | } 320 | 321 | /** 322 | * How to translate owl:allValuesFrom into SPARQL. 323 | * 324 | * @param allQuantorTranslation the allQuantorTranslation to set 325 | */ 326 | public void setAllQuantorTranslation(AllQuantorTranslation allQuantorTranslation) { 327 | this.allQuantorTranslation = allQuantorTranslation; 328 | } 329 | 330 | /** 331 | * How to express owl:Thing in SPARQL. 332 | * @param owlThingRendering the owlThingRendering to set 333 | */ 334 | public void setOwlThingRendering(OWLThingRendering owlThingRendering) { 335 | this.owlThingRendering = owlThingRendering; 336 | } 337 | 338 | public VariablesMapping getVariablesMapping() { 339 | return mapping; 340 | } 341 | 342 | private String createSelectClause(boolean countQuery) { 343 | return "SELECT " + (countQuery ? "(COUNT(" : "") + (useDistinct ? " DISTINCT " : "") + variables.firstElement() + (countQuery ? " AS " + countVar + ")" : ""); 344 | } 345 | 346 | private String createWhereClause(OWLClassExpression ce){ 347 | return " WHERE " + createGroupGraphPattern(ce); 348 | } 349 | 350 | private String createGroupGraphPattern(OWLClassExpression ce) { 351 | ce.accept(this); 352 | return "{" + sparql + "}"; 353 | } 354 | 355 | // private OWLClassExpression rewrite(OWLClassExpression ce) { 356 | // 357 | // } 358 | 359 | private String createSolutionModifier() { 360 | return appendix; 361 | } 362 | 363 | private void reset(){ 364 | variables.clear(); 365 | properties.clear(); 366 | sparql = ""; 367 | appendix = ""; 368 | intersection = new HashMap<>(); 369 | mapping.reset(); 370 | } 371 | 372 | private int modalDepth(){ 373 | return variables.size(); 374 | } 375 | 376 | /** 377 | * Checks whether the intersection contains at least one operand that 378 | * is not a negation. 379 | * @param intersection the intersection 380 | * @return whether the intersection contains at least one operand that 381 | * is not a negation. 382 | */ 383 | private boolean containsNonNegationOperand(OWLObjectIntersectionOf intersection){ 384 | for (OWLClassExpression op : intersection.getOperands()) { 385 | if(op.getClassExpressionType() != ClassExpressionType.OBJECT_COMPLEMENT_OF){ 386 | return true; 387 | } 388 | } 389 | return false; 390 | } 391 | 392 | private boolean inIntersection(){ 393 | return intersection.containsKey(modalDepth()) ? intersection.get(modalDepth()) : false; 394 | } 395 | 396 | private void enterIntersection(){ 397 | naryExpressions.push(1); 398 | intersection.put(modalDepth(), true); 399 | } 400 | 401 | private void leaveIntersection(){ 402 | naryExpressions.pop(); 403 | intersection.remove(modalDepth()); 404 | } 405 | 406 | private String asTriplePattern(String subject, String predicate, String object){ 407 | return String.format(TRIPLE_PATTERN, subject, predicate, object); 408 | } 409 | 410 | private String asTriplePattern(String subject, OWLEntity predicate, OWLEntity object){ 411 | return asTriplePattern(subject, render(predicate), render(object)); 412 | } 413 | 414 | private String asTriplePattern(String subject, OWLEntity predicate, String object){ 415 | return asTriplePattern(subject, render(predicate), object); 416 | } 417 | 418 | private String asTriplePattern(String subject, OWLEntity predicate, OWLLiteral object){ 419 | return asTriplePattern(subject, render(predicate), render(object)); 420 | } 421 | 422 | private String genericTriplePattern(){ 423 | // BasicPattern bgp = new BasicPattern(); 424 | // bgp.add(Triple.create(NodeFactory.createVariable("s"), NodeFactory.createVariable("s"), NodeFactory.createVariable("s"))); 425 | // System.out.println(FormatterElement.asString(new ElementTriplesBlock(bgp))); 426 | return variables.peek() + " ?p ?o ."; 427 | } 428 | 429 | private String typeTriplePattern(String var, String type){ 430 | return var + (useReasoning ? " /* " : " a ") + type + " .\n"; 431 | } 432 | 433 | private String equalExpressions(String expr1, String expr2, boolean negated){ 434 | return (equalityRendering == EqualityRendering.TERM_EQUALITY) ? 435 | (negated ? "!" : "") + "sameTerm(" + expr1 + ", " + expr2 + ")" : 436 | expr1 + (negated ? " != " : " = ") + expr2; 437 | } 438 | 439 | private String filter(String expr){ 440 | return "FILTER(" + expr + ")"; 441 | } 442 | 443 | private String render(OWLEntity entity){ 444 | String s; 445 | if(variableEntities.contains(entity)){ 446 | s = mapping.getVariable(entity); 447 | } else { 448 | s = "<" + entity.toStringID() + ">"; 449 | } 450 | if(entity.isOWLObjectProperty()){ 451 | properties.put(modalDepth(), entity); 452 | } 453 | return s; 454 | } 455 | 456 | private String render(OWLLiteral literal){ 457 | return "\"" + literal.getLiteral() + "\"^^<" + literal.getDatatype().toStringID() + ">"; 458 | } 459 | 460 | @Override 461 | public void visit(OWLClass ce) { 462 | if(ce.equals(expr) || (ignoreGenericTypeStatements && !ce.isOWLThing())){ 463 | if(!ce.isOWLThing() || owlThingRendering == OWLThingRendering.EXPLICIT){ 464 | sparql += typeTriplePattern(variables.peek(), render(ce)); 465 | } else { 466 | sparql += asTriplePattern(variables.peek(), "?p", "?o"); 467 | } 468 | } 469 | } 470 | 471 | @Override 472 | public void visit(OWLObjectIntersectionOf ce) { 473 | // if all operands are negated, we have to add a generic triple 474 | if(!containsNonNegationOperand(ce) && needOuterTriplePattern){ 475 | sparql += genericTriplePattern(); 476 | } 477 | 478 | enterIntersection(); 479 | List operands = ce.getOperandsAsList(); 480 | for (OWLClassExpression operand : operands) { 481 | operand.accept(this); 482 | } 483 | Collection props = properties.get(modalDepth()); 484 | if(props.size() > 1){ 485 | Collection vars = new TreeSet<>(); 486 | for (OWLEntity p : props) { 487 | if(mapping.containsKey(p)){ 488 | vars.add(mapping.get(p)); 489 | } 490 | } 491 | if(vars.size() == 2){ 492 | List varList = new ArrayList<>(vars); 493 | sparql += filter(equalExpressions(varList.get(0), varList.get(1), true)); 494 | } 495 | } 496 | leaveIntersection(); 497 | } 498 | 499 | @Override 500 | public void visit(OWLObjectUnionOf ce) { 501 | naryExpressions.push(0); 502 | List operands = ce.getOperandsAsList(); 503 | for (int i = 0; i < operands.size()-1; i++) { 504 | sparql += "{"; 505 | operands.get(i).accept(this); 506 | sparql += "}"; 507 | sparql += " UNION "; 508 | } 509 | sparql += "{"; 510 | operands.get(operands.size()-1).accept(this); 511 | sparql += "}"; 512 | naryExpressions.pop(); 513 | } 514 | 515 | private boolean inUnion() { 516 | return !naryExpressions.isEmpty() && naryExpressions.peek().equals(0); 517 | } 518 | 519 | @Override 520 | public void visit(OWLObjectComplementOf ce) { 521 | if((!inIntersection() && 522 | // modalDepth() == 1 && 523 | needOuterTriplePattern && (existentialFillers.isEmpty() || !existentialFillers.peek().equals(ce))) || inUnion()){ 524 | sparql += genericTriplePattern(); 525 | } 526 | 527 | sparql += "FILTER NOT EXISTS {"; 528 | ce.getOperand().accept(this); 529 | sparql += "}"; 530 | } 531 | 532 | @Override 533 | public void visit(OWLObjectSomeValuesFrom ce) { 534 | String objectVariable = mapping.newIndividualVariable(); 535 | OWLObjectPropertyExpression propertyExpression = ce.getProperty(); 536 | if(propertyExpression.isAnonymous()){ 537 | //property expression is inverse of a property 538 | sparql += asTriplePattern(objectVariable, propertyExpression.getNamedProperty(), variables.peek()); 539 | } else { 540 | sparql += asTriplePattern(variables.peek(), propertyExpression.getNamedProperty(), objectVariable); 541 | } 542 | OWLClassExpression filler = ce.getFiller(); 543 | existentialFillers.push(filler); 544 | variables.push(objectVariable); 545 | filler.accept(this); 546 | variables.pop(); 547 | existentialFillers.pop(); 548 | // if(filler.isAnonymous()){ 549 | // variables.push(objectVariable); 550 | // filler.accept(this); 551 | // variables.pop(); 552 | // } else { 553 | // sparql += triple(objectVariable, "a", filler.asOWLClass()); 554 | // } 555 | 556 | } 557 | 558 | private boolean isTrivialConcept(OWLClassExpression ce) { 559 | return ce.isOWLThing() 560 | || (ce.getClassExpressionType() == ClassExpressionType.OBJECT_ALL_VALUES_FROM && isTrivialConcept(((OWLObjectAllValuesFrom) ce) 561 | .getFiller())); 562 | } 563 | 564 | @Override 565 | public void visit(OWLObjectAllValuesFrom ce) { 566 | OWLClassExpression filler = ce.getFiller(); 567 | 568 | String subject = variables.peek(); 569 | String objectVariable = mapping.newIndividualVariable(); 570 | 571 | if(isTrivialConcept(filler)) { 572 | // \forall r.\top is trivial, as everything belongs to that concept 573 | // thus, we can omit it if it's used in a conjunction or as complex filler 574 | if(!inIntersection()) { 575 | sparql += asTriplePattern(subject, mapping.newPropertyVariable(), objectVariable); 576 | } 577 | } else { 578 | // we can either use double negation on \forall r.A such that we have a logically 579 | // equivalent expression \neg \exists r.\neg A 580 | // or we use subselects get the individuals whose r successors are only of type A 581 | if(allQuantorTranslation == AllQuantorTranslation.DOUBLE_NEGATION){ 582 | OWLObjectComplementOf doubleNegatedExpression = df.getOWLObjectComplementOf( 583 | df.getOWLObjectSomeValuesFrom( 584 | ce.getProperty(), 585 | df.getOWLObjectComplementOf(ce.getFiller()))); 586 | doubleNegatedExpression.accept(this); 587 | } else { 588 | if(!inIntersection()) { 589 | sparql += asTriplePattern(subject, mapping.newPropertyVariable(), objectVariable); 590 | } 591 | 592 | OWLObjectPropertyExpression propertyExpression = ce.getProperty(); 593 | OWLObjectProperty predicate = propertyExpression.getNamedProperty(); 594 | if(propertyExpression.isAnonymous()){ 595 | //property expression is inverse of a property 596 | sparql += asTriplePattern(objectVariable, predicate, variables.peek()); 597 | } else { 598 | sparql += asTriplePattern(variables.peek(), predicate, objectVariable); 599 | } 600 | 601 | String var = mapping.newIndividualVariable(); 602 | sparql += "{SELECT " + subject + " (COUNT(" + var + ") AS ?cnt1) WHERE {"; 603 | sparql += asTriplePattern(subject, predicate, var); 604 | variables.push(var); 605 | filler.accept(this); 606 | variables.pop(); 607 | sparql += "} GROUP BY " + subject + "}"; 608 | 609 | var = mapping.newIndividualVariable(); 610 | sparql += "{SELECT " + subject + " (COUNT(" + var + ") AS ?cnt2) WHERE {"; 611 | sparql += asTriplePattern(subject, predicate, var); 612 | sparql += "} GROUP BY " + subject + "}"; 613 | 614 | sparql += filter("?cnt1=?cnt2"); 615 | } 616 | } 617 | } 618 | 619 | @Override 620 | public void visit(OWLObjectHasValue ce) { 621 | OWLObjectPropertyExpression propertyExpression = ce.getProperty(); 622 | OWLNamedIndividual value = ce.getFiller().asOWLNamedIndividual(); 623 | if(propertyExpression.isAnonymous()){ 624 | //property expression is inverse of a property 625 | sparql += asTriplePattern(value.toStringID(), propertyExpression.getNamedProperty(), variables.peek()); 626 | } else { 627 | sparql += asTriplePattern(variables.peek(), propertyExpression.getNamedProperty(), value); 628 | } 629 | } 630 | 631 | @Override 632 | public void visit(OWLObjectMinCardinality ce) { 633 | processObjectCardinalityRestriction(ce, ">="); 634 | } 635 | 636 | @Override 637 | public void visit(OWLObjectExactCardinality ce) { 638 | processObjectCardinalityRestriction(ce, "="); 639 | } 640 | 641 | @Override 642 | public void visit(OWLObjectMaxCardinality ce) { 643 | processObjectCardinalityRestriction(ce, "<="); 644 | } 645 | 646 | private void processObjectCardinalityRestriction(OWLObjectCardinalityRestriction ce, String operator) { 647 | String subjectVariable = variables.peek(); 648 | String objectVariable = mapping.newIndividualVariable(); 649 | 650 | int cardinality = ce.getCardinality(); 651 | 652 | boolean maxOneCardinalityAsFilterNotExists = true; 653 | boolean useMaxCardOptimization = ce.getClassExpressionType() == OBJECT_MAX_CARDINALITY && cardinality == 1 && maxOneCardinalityAsFilterNotExists; 654 | 655 | if(useMaxCardOptimization){ 656 | // process the restriction once with the filler variable ?o1 657 | processPropertyRestriction(ce, subjectVariable, objectVariable); 658 | 659 | sparql += "FILTER NOT EXISTS {"; 660 | 661 | // we need a second filler variable ?o2 662 | String objectVariable2 = mapping.newIndividualVariable(); 663 | 664 | // process the restriction again with the new filler variable 665 | processPropertyRestriction(ce, subjectVariable, objectVariable2); 666 | 667 | // add FILTER(?o1 != ?o2) 668 | sparql += filter(equalExpressions(objectVariable, objectVariable2, true)); 669 | sparql += "}"; 670 | } else { 671 | if(!useMaxCardOptimization && (inIntersection() || modalDepth() > 1)){ 672 | sparql += "{SELECT " + subjectVariable + " WHERE {"; 673 | } 674 | 675 | processPropertyRestriction(ce, subjectVariable, objectVariable); 676 | 677 | String grouping = " GROUP BY " + subjectVariable + " HAVING(COUNT(" + objectVariable + ")" + operator + cardinality + ")"; 678 | if(inIntersection() || modalDepth() > 1){ 679 | sparql += "}" + grouping + "}"; 680 | } else { 681 | appendix += grouping; 682 | } 683 | } 684 | } 685 | 686 | private void processPropertyRestrictionFiller(String objectVariable, OWLClassExpression filler) { 687 | variables.push(objectVariable); 688 | filler.accept(this); 689 | variables.pop(); 690 | } 691 | 692 | private > void processPropertyRestriction( 693 | R ce, String subjectVariable, String objectVariable) { 694 | OWLObjectPropertyExpression pe = ce.getProperty(); 695 | 696 | if (pe.isAnonymous()) {// property expression is inverse of a property 697 | sparql += asTriplePattern(objectVariable, pe.getNamedProperty(), subjectVariable); 698 | } else { 699 | sparql += asTriplePattern(subjectVariable, pe.getNamedProperty(), objectVariable); 700 | } 701 | 702 | // process the filler 703 | processPropertyRestrictionFiller(objectVariable, ce.getFiller()); 704 | } 705 | 706 | @Override 707 | public void visit(OWLObjectHasSelf ce) { 708 | String subject = variables.peek(); 709 | OWLObjectPropertyExpression property = ce.getProperty(); 710 | sparql += asTriplePattern(subject, property.getNamedProperty(), subject); 711 | } 712 | 713 | @Override 714 | public void visit(OWLObjectOneOf ce) { 715 | String subject = variables.peek(); 716 | String valuesString = Joiner 717 | .on(nominalTranslation == NominalTranslation.FILTER_IN ? "," : " ") 718 | .join(ce.getIndividuals().stream() 719 | .map(ind -> "<" + ind.toStringID() + ">") 720 | .collect(Collectors.toList())); 721 | if(nominalTranslation == NominalTranslation.FILTER_IN) { 722 | if(modalDepth() == 1){ 723 | sparql += genericTriplePattern(); 724 | } 725 | sparql += "FILTER(" + subject + " IN (" + valuesString + "))"; 726 | } else if(nominalTranslation == NominalTranslation.VALUES){ 727 | sparql += "VALUES " + subject + " {" + valuesString + "}"; 728 | } else { 729 | throw new RuntimeException(nominalTranslation + " not implemented yet"); 730 | } 731 | } 732 | 733 | @Override 734 | public void visit(OWLDataSomeValuesFrom ce) { 735 | String objectVariable = mapping.newIndividualVariable(); 736 | OWLDataPropertyExpression propertyExpression = ce.getProperty(); 737 | sparql += asTriplePattern(variables.peek(), propertyExpression.asOWLDataProperty(), objectVariable); 738 | OWLDataRange filler = ce.getFiller(); 739 | variables.push(objectVariable); 740 | processDataRange(filler); 741 | variables.pop(); 742 | } 743 | 744 | @Override 745 | public void visit(OWLDataAllValuesFrom ce) { 746 | OWLDataRange filler = ce.getFiller(); 747 | 748 | String subject = variables.peek(); 749 | String objectVariable = mapping.newIndividualVariable(); 750 | 751 | // we can either use double negation on \forall r.A such that we have a logically 752 | // equivalent expression \neg \exists r.\neg A 753 | // or we use subselects get the individuals whose r successors are only of type A 754 | if(allQuantorTranslation == AllQuantorTranslation.DOUBLE_NEGATION){ 755 | OWLObjectComplementOf doubleNegatedExpression = df.getOWLObjectComplementOf( 756 | df.getOWLDataSomeValuesFrom( 757 | ce.getProperty(), 758 | df.getOWLDataComplementOf(ce.getFiller()))); 759 | doubleNegatedExpression.accept(this); 760 | } else { 761 | if(!inIntersection()) { 762 | sparql += asTriplePattern(subject, mapping.newPropertyVariable(), objectVariable); 763 | } 764 | 765 | OWLDataPropertyExpression propertyExpression = ce.getProperty(); 766 | OWLDataProperty predicate = propertyExpression.asOWLDataProperty(); 767 | if(propertyExpression.isAnonymous()){ 768 | //property expression is inverse of a property 769 | sparql += asTriplePattern(objectVariable, predicate, variables.peek()); 770 | } else { 771 | sparql += asTriplePattern(variables.peek(), predicate, objectVariable); 772 | } 773 | 774 | String var = mapping.newIndividualVariable(); 775 | sparql += "{SELECT " + subject + " (COUNT(" + var + ") AS ?cnt1) WHERE {"; 776 | sparql += asTriplePattern(subject, predicate, var); 777 | variables.push(var); 778 | filler.accept(this); 779 | variables.pop(); 780 | sparql += "} GROUP BY " + subject + "}"; 781 | 782 | var = mapping.newIndividualVariable(); 783 | sparql += "{SELECT " + subject + " (COUNT(" + var + ") AS ?cnt2) WHERE {"; 784 | sparql += asTriplePattern(subject, predicate, var); 785 | sparql += "} GROUP BY " + subject + "}"; 786 | 787 | sparql += filter("?cnt1=?cnt2"); 788 | } 789 | } 790 | 791 | @Override 792 | public void visit(OWLDataHasValue ce) { 793 | OWLDataPropertyExpression propertyExpression = ce.getProperty(); 794 | OWLLiteral value = ce.getFiller(); 795 | sparql += asTriplePattern(variables.peek(), propertyExpression.asOWLDataProperty(), value); 796 | } 797 | 798 | @Override 799 | public void visit(OWLDataMinCardinality ce) { 800 | processDataCardinality(ce, ">="); 801 | } 802 | 803 | @Override 804 | public void visit(OWLDataExactCardinality ce) { 805 | processDataCardinality(ce, "="); 806 | } 807 | 808 | @Override 809 | public void visit(OWLDataMaxCardinality ce) { 810 | processDataCardinality(ce, "<="); 811 | } 812 | 813 | private void processDataCardinality(OWLDataCardinalityRestriction ce, String operator) { 814 | String subjectVariable = variables.peek(); 815 | String objectVariable = mapping.newIndividualVariable(); 816 | OWLDataPropertyExpression propertyExpression = ce.getProperty(); 817 | int cardinality = ce.getCardinality(); 818 | sparql += "{SELECT " + subjectVariable + " WHERE {"; 819 | sparql += asTriplePattern(subjectVariable, propertyExpression.asOWLDataProperty(), objectVariable); 820 | OWLDataRange filler = ce.getFiller(); 821 | variables.push(objectVariable); 822 | processDataRange(filler); 823 | variables.pop(); 824 | 825 | sparql += "} GROUP BY " + subjectVariable + " HAVING(COUNT(" + objectVariable + ")" + operator + cardinality + ")}"; 826 | } 827 | 828 | private void processDataRange(OWLDataRange dataRange) { 829 | sparql += "FILTER("; 830 | dataRange.accept(this); 831 | sparql += ")"; 832 | } 833 | 834 | @Override 835 | public void visit(OWLDatatype node) { 836 | if (ignoreGenericTypeStatements && !node.isRDFPlainLiteral() && !node.isTopDatatype()) { 837 | sparql += 838 | String.format("DATATYPE(%s) %s %s", 839 | variables.peek(), 840 | (negatedDataRange ? "!=" : "="), 841 | node.getIRI().toQuotedString()); 842 | } 843 | } 844 | 845 | @Override 846 | public void visit(OWLDataOneOf node) { 847 | String subject = variables.peek(); 848 | if(modalDepth() == 1){ 849 | sparql += genericTriplePattern(); 850 | } 851 | sparql += subject + (negatedDataRange ? " NOT " : "") + " IN ("; 852 | String values = ""; 853 | for (OWLLiteral value : node.getValues()) { 854 | if(!values.isEmpty()){ 855 | values += ","; 856 | } 857 | values += render(value); 858 | } 859 | sparql += values; 860 | sparql += ")"; 861 | } 862 | 863 | @Override 864 | public void visit(OWLDataComplementOf node) { 865 | negatedDataRange = true; 866 | node.getDataRange().accept(this); 867 | negatedDataRange = false; 868 | } 869 | 870 | @Override 871 | public void visit(OWLDataIntersectionOf node) { 872 | Iterator iterator = node.getOperands().iterator(); 873 | while(iterator.hasNext()) { 874 | iterator.next().accept(this); 875 | if(iterator.hasNext()) { 876 | sparql += " && "; 877 | } 878 | } 879 | } 880 | 881 | @Override 882 | public void visit(OWLDataUnionOf node) { 883 | Iterator iterator = node.getOperands().iterator(); 884 | while(iterator.hasNext()) { 885 | iterator.next().accept(this); 886 | if(iterator.hasNext()) { 887 | sparql += " || "; 888 | } 889 | } 890 | } 891 | 892 | @Override 893 | public void visit(OWLDatatypeRestriction node) { 894 | String subject = variables.peek(); 895 | 896 | for (Iterator iterator = node.getFacetRestrictions().iterator(); iterator.hasNext();) { 897 | OWLFacetRestriction fr = iterator.next(); 898 | 899 | OWLFacet facet = fr.getFacet(); 900 | OWLLiteral value = fr.getFacetValue(); 901 | String valueString = value.getLiteral(); 902 | 903 | switch(facet) { 904 | case LENGTH: sparql += String.format("STRLEN(STR(%s) = %d)", subject, value.parseInteger()); 905 | break; 906 | case MIN_LENGTH: sparql += String.format("STRLEN(STR(%s) >= %d)", subject, value.parseInteger()); 907 | break; 908 | case MAX_LENGTH: sparql += String.format("STRLEN(STR(%s) <= %d)", subject, value.parseInteger()); 909 | break; 910 | case PATTERN: sparql += String.format("REGEX(STR(%s), %d)", subject, value.parseInteger()); 911 | break; 912 | case LANG_RANGE: 913 | break; 914 | case MAX_EXCLUSIVE: sparql += subject + "<" + valueString; 915 | break; 916 | case MAX_INCLUSIVE: sparql += subject + "<=" + valueString; 917 | break; 918 | case MIN_EXCLUSIVE: sparql += subject + ">" + valueString; 919 | break; 920 | case MIN_INCLUSIVE: sparql += subject + ">=" + valueString; 921 | break; 922 | case FRACTION_DIGITS: 923 | break; 924 | case TOTAL_DIGITS: 925 | break; 926 | default: 927 | break; 928 | 929 | } 930 | 931 | if(iterator.hasNext()) { 932 | sparql += " && "; 933 | } 934 | } 935 | 936 | sparql += " && datatype(" + subject + ")=<" + node.getDatatype().toStringID() + ">"; 937 | } 938 | 939 | public static void main(String[] args) throws Exception { 940 | ToStringRenderer.getInstance().setRenderer(new DLSyntaxObjectRenderer()); 941 | OWLClassExpressionToSPARQLConverter converter = new OWLClassExpressionToSPARQLConverter(); 942 | 943 | OWLOntologyManager man = OWLManager.createOWLOntologyManager(); 944 | OWLDataFactory df = man.getOWLDataFactory(); 945 | PrefixManager pm = new DefaultPrefixManager(); 946 | pm.setDefaultPrefix("http://dbpedia.org/ontology/"); 947 | 948 | OWLClass clsA = df.getOWLClass("A", pm); 949 | OWLClass clsB = df.getOWLClass("B", pm); 950 | OWLClass clsC = df.getOWLClass("C", pm); 951 | 952 | OWLObjectProperty propR = df.getOWLObjectProperty("r", pm); 953 | OWLObjectProperty propS = df.getOWLObjectProperty("s", pm); 954 | 955 | OWLDataProperty dpT = df.getOWLDataProperty("t", pm); 956 | OWLDataRange booleanRange = df.getBooleanOWLDatatype(); 957 | OWLLiteral lit = df.getOWLLiteral(1); 958 | 959 | OWLIndividual indA = df.getOWLNamedIndividual("a", pm); 960 | OWLIndividual indB = df.getOWLNamedIndividual("b", pm); 961 | 962 | String rootVar = "?x"; 963 | 964 | OWLClassExpression expr = clsA; 965 | String query = converter.asQuery(expr, rootVar).toString(); 966 | System.out.println(expr + "\n" + query); 967 | 968 | expr = df.getOWLObjectSomeValuesFrom(propR, clsB); 969 | query = converter.asQuery(expr, rootVar).toString(); 970 | System.out.println(expr + "\n" + query); 971 | 972 | expr = df.getOWLObjectIntersectionOf( 973 | df.getOWLObjectSomeValuesFrom(propR, clsB), 974 | clsB); 975 | query = converter.asQuery(expr, rootVar).toString(); 976 | System.out.println(expr + "\n" + query); 977 | 978 | expr = df.getOWLObjectUnionOf( 979 | clsA, 980 | clsB); 981 | query = converter.asQuery(expr, rootVar).toString(); 982 | System.out.println(expr + "\n" + query); 983 | 984 | expr = df.getOWLObjectHasValue(propR, indA); 985 | query = converter.asQuery(expr, rootVar).toString(); 986 | System.out.println(expr + "\n" + query); 987 | 988 | expr = df.getOWLObjectAllValuesFrom(propR, df.getOWLThing()); 989 | query = converter.asQuery(expr, rootVar).toString(); 990 | System.out.println(expr + "\n" + query); 991 | 992 | expr = df.getOWLObjectAllValuesFrom(propR, df.getOWLObjectAllValuesFrom(propS, df.getOWLThing())); 993 | query = converter.asQuery(expr, rootVar).toString(); 994 | System.out.println(expr + "\n" + query); 995 | 996 | expr = df.getOWLObjectAllValuesFrom( 997 | propR, 998 | df.getOWLObjectIntersectionOf( 999 | clsA, 1000 | df.getOWLObjectAllValuesFrom(propS, df.getOWLThing()))); 1001 | query = converter.asQuery(expr, rootVar).toString(); 1002 | System.out.println(expr + "\n" + query); 1003 | 1004 | expr = df.getOWLObjectAllValuesFrom( 1005 | propR, 1006 | df.getOWLObjectUnionOf( 1007 | clsA, 1008 | df.getOWLObjectAllValuesFrom(propS, df.getOWLThing()))); 1009 | query = converter.asQuery(expr, rootVar).toString(); 1010 | System.out.println(expr + "\n" + query); 1011 | 1012 | expr = df.getOWLObjectAllValuesFrom(propR, clsB); 1013 | query = converter.asQuery(expr, rootVar).toString(); 1014 | System.out.println(expr + "\n" + query); 1015 | 1016 | expr = df.getOWLObjectAllValuesFrom(df.getOWLObjectProperty("language", pm), df.getOWLClass("Language", pm)); 1017 | query = converter.asQuery(expr, rootVar).toString(); 1018 | System.out.println(expr + "\n" + query); 1019 | 1020 | expr = df.getOWLObjectMinCardinality(2, df.getOWLObjectProperty("language", pm), df.getOWLClass("Language", pm)); 1021 | query = converter.asQuery(expr, rootVar).toString(); 1022 | System.out.println(expr + "\n" + query); 1023 | 1024 | expr = df.getOWLObjectIntersectionOf( 1025 | df.getOWLClass("Place", pm), 1026 | df.getOWLObjectMinCardinality( 1027 | 2, 1028 | df.getOWLObjectProperty("language", pm), 1029 | df.getOWLClass("Language", pm))); 1030 | query = converter.asQuery(expr, rootVar).toString(); 1031 | System.out.println(expr + "\n" + query); 1032 | 1033 | expr = df.getOWLObjectOneOf(indA, indB); 1034 | query = converter.asQuery(expr, rootVar).toString(); 1035 | System.out.println(expr + "\n" + query); 1036 | 1037 | expr = df.getOWLObjectSomeValuesFrom(propR, df.getOWLObjectOneOf(indA, indB)); 1038 | query = converter.asQuery(expr, rootVar).toString(); 1039 | System.out.println(expr + "\n" + query); 1040 | 1041 | expr = df.getOWLObjectIntersectionOf( 1042 | clsA, 1043 | df.getOWLObjectHasSelf(propR)); 1044 | query = converter.asQuery(expr, rootVar).toString(); 1045 | System.out.println(expr + "\n" + query); 1046 | 1047 | expr = df.getOWLObjectIntersectionOf( 1048 | clsA, 1049 | df.getOWLDataSomeValuesFrom(dpT, booleanRange)); 1050 | query = converter.asQuery(expr, rootVar).toString(); 1051 | System.out.println(expr + "\n" + query); 1052 | 1053 | expr = df.getOWLObjectIntersectionOf( 1054 | clsA, 1055 | df.getOWLDataHasValue(dpT, lit)); 1056 | query = converter.asQuery(expr, rootVar).toString(); 1057 | System.out.println(expr + "\n" + query); 1058 | 1059 | expr = df.getOWLObjectIntersectionOf( 1060 | clsA, 1061 | df.getOWLDataMinCardinality(2, dpT, booleanRange)); 1062 | query = converter.asQuery(expr, rootVar).toString(); 1063 | System.out.println(expr + "\n" + query); 1064 | 1065 | expr = df.getOWLObjectComplementOf(clsB); 1066 | query = converter.asQuery(expr, rootVar).toString(); 1067 | System.out.println(expr + "\n" + query); 1068 | 1069 | expr = df.getOWLObjectIntersectionOf( 1070 | clsA, 1071 | df.getOWLObjectComplementOf(clsB)); 1072 | query = converter.asQuery(expr, rootVar).toString(); 1073 | System.out.println(expr + "\n" + query); 1074 | 1075 | expr = df.getOWLObjectSomeValuesFrom(propR, 1076 | df.getOWLObjectIntersectionOf( 1077 | clsA, 1078 | df.getOWLObjectComplementOf(clsB))); 1079 | query = converter.asQuery(expr, rootVar).toString(); 1080 | System.out.println(expr + "\n" + query); 1081 | 1082 | expr = df.getOWLDataAllValuesFrom(dpT, booleanRange); 1083 | query = converter.asQuery(expr, rootVar).toString(); 1084 | System.out.println(expr + "\n" + query); 1085 | 1086 | expr = df.getOWLDataAllValuesFrom(dpT,df.getOWLDataOneOf(lit)); 1087 | query = converter.asQuery(expr, rootVar).toString(); 1088 | System.out.println(expr + "\n" + query); 1089 | 1090 | //variable entity 1091 | expr = df.getOWLObjectIntersectionOf( 1092 | df.getOWLObjectSomeValuesFrom(propR, clsB), 1093 | clsB, df.getOWLObjectSomeValuesFrom(propS, clsA)); 1094 | query = converter.asQuery(rootVar, expr, Sets.newHashSet(propR, propS)).toString(); 1095 | System.out.println(expr + "\n" + query); 1096 | 1097 | expr = df.getOWLObjectIntersectionOf( 1098 | df.getOWLObjectSomeValuesFrom( 1099 | propR, 1100 | df.getOWLObjectIntersectionOf( 1101 | df.getOWLObjectSomeValuesFrom(propS, clsA), 1102 | clsC)), 1103 | clsB); 1104 | query = converter.asQuery(rootVar, expr, Sets.newHashSet(propR, propS)).toString(); 1105 | System.out.println(expr + "\n" + query); 1106 | 1107 | 1108 | expr = df.getOWLObjectIntersectionOf( 1109 | df.getOWLObjectComplementOf(clsA), 1110 | df.getOWLObjectSomeValuesFrom( 1111 | propR, 1112 | df.getOWLObjectSomeValuesFrom( 1113 | propS, 1114 | df.getOWLObjectComplementOf(clsB) 1115 | ) 1116 | ) 1117 | ); 1118 | query = converter.asQuery(expr, rootVar).toString(); 1119 | System.out.println(expr + "\n" + query); 1120 | 1121 | expr = df.getOWLObjectUnionOf( 1122 | df.getOWLObjectComplementOf(clsA), 1123 | df.getOWLObjectComplementOf(clsB) 1124 | ); 1125 | query = converter.asQuery(expr, rootVar).toString(); 1126 | System.out.println(expr + "\n" + query); 1127 | 1128 | expr = df.getOWLObjectIntersectionOf( 1129 | clsA, 1130 | df.getOWLObjectUnionOf( 1131 | clsB, 1132 | df.getOWLObjectComplementOf( 1133 | df.getOWLObjectSomeValuesFrom( 1134 | propR, 1135 | df.getOWLThing() 1136 | ) 1137 | ) 1138 | ) 1139 | ); 1140 | query = converter.asQuery(expr, rootVar).toString(); 1141 | System.out.println(expr + "\n" + query); 1142 | 1143 | Op op = Algebra.compile(converter.asQuery(expr, rootVar)); 1144 | System.out.println(op); 1145 | 1146 | expr = df.getOWLObjectIntersectionOf( 1147 | clsA, 1148 | df.getOWLObjectComplementOf( 1149 | df.getOWLObjectSomeValuesFrom( 1150 | propR, 1151 | clsB 1152 | ) 1153 | ) 1154 | ); 1155 | query = converter.asQuery(expr, rootVar).toString(); 1156 | System.out.println(expr + "\n" + query); 1157 | 1158 | expr = df.getOWLObjectIntersectionOf( 1159 | clsA, 1160 | df.getOWLDataSomeValuesFrom(dpT, df.getOWLDataComplementOf(booleanRange)) 1161 | ); 1162 | query = converter.asQuery(expr, rootVar).toString(); 1163 | System.out.println(expr + "\n" + query); 1164 | 1165 | // data one of 1166 | expr = df.getOWLDataSomeValuesFrom(dpT,df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2))); 1167 | query = converter.asQuery(expr, rootVar).toString(); 1168 | System.out.println(expr + "\n" + query); 1169 | 1170 | // data not one of 1171 | expr = df.getOWLDataSomeValuesFrom( 1172 | dpT, 1173 | df.getOWLDataComplementOf( 1174 | df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2)))); 1175 | query = converter.asQuery(expr, rootVar).toString(); 1176 | System.out.println(expr + "\n" + query); 1177 | 1178 | // data intersection 1179 | expr = df.getOWLDataSomeValuesFrom( 1180 | dpT, 1181 | df.getOWLDataIntersectionOf( 1182 | df.getBooleanOWLDatatype(), 1183 | df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2)))); 1184 | query = converter.asQuery(expr, rootVar).toString(); 1185 | System.out.println(expr + "\n" + query); 1186 | 1187 | // data union 1188 | expr = df.getOWLDataSomeValuesFrom( 1189 | dpT, 1190 | df.getOWLDataUnionOf( 1191 | df.getIntegerOWLDatatype(), 1192 | df.getOWLDataIntersectionOf( 1193 | df.getBooleanOWLDatatype(), 1194 | df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2))))); 1195 | query = converter.asQuery(expr, rootVar).toString(); 1196 | System.out.println(expr + "\n" + query); 1197 | 1198 | // data restriction 1199 | expr = df.getOWLDataSomeValuesFrom( 1200 | dpT, 1201 | df.getOWLDatatypeRestriction( 1202 | df.getIntegerOWLDatatype(), 1203 | df.getOWLFacetRestriction( 1204 | OWLFacet.MAX_EXCLUSIVE, df.getOWLLiteral(10)), 1205 | df.getOWLFacetRestriction( 1206 | OWLFacet.MIN_INCLUSIVE, df.getOWLLiteral(3)))); 1207 | query = converter.asQuery(expr, rootVar).toString(); 1208 | System.out.println(expr + "\n" + query); 1209 | 1210 | // data restriction 1211 | expr = df.getOWLDataSomeValuesFrom( 1212 | dpT, 1213 | df.getOWLDatatypeRestriction( 1214 | df.getRDFPlainLiteral(), 1215 | df.getOWLFacetRestriction( 1216 | OWLFacet.LENGTH, df.getOWLLiteral(10)))); 1217 | query = converter.asQuery(expr, rootVar).toString(); 1218 | System.out.println(expr + "\n" + query); 1219 | 1220 | expr = df.getOWLObjectMaxCardinality(1, propR, clsA); 1221 | query = converter.asQuery(expr, rootVar).toString(); 1222 | System.out.println(expr + "\n" + query); 1223 | 1224 | expr = df.getOWLObjectMaxCardinality(0, propR, clsA); 1225 | query = converter.asQuery(expr, rootVar).toString(); 1226 | System.out.println(expr + "\n" + query); 1227 | 1228 | expr = df.getOWLObjectComplementOf(clsA); 1229 | query = converter.asQuery(expr, rootVar).toString(); 1230 | System.out.println(expr + "\n" + query); 1231 | 1232 | expr = df.getOWLObjectAllValuesFrom(propR, clsA); 1233 | query = converter.asQuery(expr, rootVar).toString(); 1234 | System.out.println(expr + "\n" + query); 1235 | 1236 | expr = df.getOWLObjectExactCardinality(2, propR, clsA); 1237 | query = converter.asQuery(expr, rootVar).toString(); 1238 | System.out.println(expr + "\n" + query); 1239 | } 1240 | } -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/OWLObjectPropertyExpressionConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | /** 21 | * 22 | */ 23 | package org.aksw.owl2sparql; 24 | 25 | import org.semanticweb.owlapi.model.*; 26 | 27 | import javax.annotation.Nonnull; 28 | 29 | /** 30 | * @author Lorenz Buehmann 31 | * 32 | */ 33 | public class OWLObjectPropertyExpressionConverter implements OWLPropertyExpressionVisitorEx{ 34 | 35 | String propertyVar = "?p"; 36 | 37 | /* (non-Javadoc) 38 | * @see org.semanticweb.owlapi.model.OWLPropertyExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectProperty) 39 | */ 40 | @Override 41 | public String visit(OWLObjectProperty property) { 42 | return property.toStringID(); 43 | } 44 | 45 | /* (non-Javadoc) 46 | * @see org.semanticweb.owlapi.model.OWLPropertyExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectInverseOf) 47 | */ 48 | @Override 49 | public String visit(OWLObjectInverseOf property) { 50 | return propertyVar + "" + ""; 51 | } 52 | 53 | /* (non-Javadoc) 54 | * @see org.semanticweb.owlapi.model.OWLPropertyExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataProperty) 55 | */ 56 | @Override 57 | public String visit(OWLDataProperty property) { 58 | return property.toStringID(); 59 | } 60 | 61 | @Nonnull 62 | @Override 63 | public String visit(@Nonnull OWLAnnotationProperty property) { 64 | return property.toStringID(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/style/AllQuantorTranslation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.style; 21 | 22 | /** 23 | * How to express an universal restriction, i.e. owl:allValuesFrom in SPARQL. 24 | * 25 | * @author Lorenz Buehmann 26 | * 27 | */ 28 | public enum AllQuantorTranslation { 29 | /** 30 | * Use double negation, e.g. 31 | *
32 | *
33 | 	 * FILTER NOT EXISTS {
34 | 	 * 	?s :p ?o .
35 | 	 * 	FILTER NOT EXISTS { ?o a :Class }
36 | 	 * }
37 | 	 * 
38 | * And addition, this mode tries to cover the completed semantics of \forall by also addressing the case in which 39 | * there is no :p successor at all. This leads to the graph pattern 40 | *
41 | 	 * {
42 | 	 * ?s ?p ?o .
43 | 	 * FILTER NOT EXISTS {
44 | 	 *	?s :p ?o1 .
45 | 	 * } UNION {
46 | 	 * ?s :p ?o .
47 | 	 * FILTER NOT EXISTS {
48 | 	 *	?s :p ?o .
49 | 	 * 	FILTER NOT EXISTS { ?o a :Class }
50 | 	 * }
51 | 	 * }
52 | 	 * 
53 | *
54 | */ 55 | DOUBLE_NEGATION_STRICT, 56 | /** 57 | * Use double negation, e.g. 58 | *
59 | *
60 | 	 * FILTER NOT EXISTS { 
61 | 	 * 	?s :p ?o . 
62 | 	 * 	FILTER NOT EXISTS { ?o a :Class }
63 | 	 * }
64 | 	 * 
65 | *
66 | */ 67 | DOUBLE_NEGATION, 68 | /** 69 | * Use two sub-selects and compare its values, e.g. 70 | *
71 | *
72 | 	 * ?s ?p ?o .
73 | 	 * {SELECT (COUNT(*) AS ?cnt1) WHERE { ?s :p ?o } }
74 | 	 * {SELECT (COUNT(*) AS ?cnt1) WHERE { ?s :p ?o . ?o a :Class } }
75 | 	 * FILTER (?cnt1 = ?cnt2)
76 | 	 * 
77 | *
78 | */ 79 | SUBSELECT_COUNT_EQUALS 80 | } -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/style/EqualityRendering.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.style; 21 | 22 | /** 23 | * How to render equality in SPARQL. 24 | *
    25 | *
  • {@link #VALUE_EQUALTIY}
  • 26 | *
  • {@link #TERM_EQUALITY}
  • 27 | *
28 | * @author Lorenz Buehmann 29 | * 30 | */ 31 | public enum EqualityRendering { 32 | 33 | /** 34 | * Value equality uses the = operator, e.g. 35 | * FILTER(?x = 1) . 36 | */ 37 | VALUE_EQUALTIY, 38 | /** 39 | * Term equality uses the SAMETERM function, e.g. 40 | * FILTER(SAMETERM(?x, 1)) . 41 | *

42 | * Term equality only returns true if the RDF terms are identical. So if 43 | * the RDF term in the database was encoded as “001”^^xsd:integer 44 | * term equality would give false whereas value equality would return true 45 | * because the value of the terms is equivalent. 46 | */ 47 | TERM_EQUALITY 48 | } -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/style/NominalTranslation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 - 2016 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.style; 21 | 22 | /** 23 | * @author Lorenz Buehmann 24 | */ 25 | public enum NominalTranslation { 26 | 27 | FILTER_IN, 28 | VALUES 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/style/OWLThingRendering.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.style; 21 | 22 | /** 23 | * The way how owl:Thing in OWL class expressions is mapped to 24 | * SPARQL. 25 | *

    26 | *
  • {@link #EXPLICIT}
  • 27 | *
  • {@link #GENERIC_TRIPLE_PATTERN}
  • 28 | *
29 | * @author Lorenz Buehmann 30 | * 31 | */ 32 | public enum OWLThingRendering { 33 | /** 34 | * Use a triple pattern ?s a owl:Thing . 35 | */ 36 | EXPLICIT, 37 | /** 38 | * Use a generic triple pattern ?s ?p ?o . 39 | */ 40 | GENERIC_TRIPLE_PATTERN 41 | } -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/util/OWLClassExpressionMinimizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.util; 21 | 22 | import java.util.HashSet; 23 | import java.util.List; 24 | import java.util.Set; 25 | 26 | import org.semanticweb.owlapi.model.OWLClass; 27 | import org.semanticweb.owlapi.model.OWLClassExpression; 28 | import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx; 29 | import org.semanticweb.owlapi.model.OWLDataAllValuesFrom; 30 | import org.semanticweb.owlapi.model.OWLDataExactCardinality; 31 | import org.semanticweb.owlapi.model.OWLDataFactory; 32 | import org.semanticweb.owlapi.model.OWLDataHasValue; 33 | import org.semanticweb.owlapi.model.OWLDataMaxCardinality; 34 | import org.semanticweb.owlapi.model.OWLDataMinCardinality; 35 | import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom; 36 | import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom; 37 | import org.semanticweb.owlapi.model.OWLObjectComplementOf; 38 | import org.semanticweb.owlapi.model.OWLObjectExactCardinality; 39 | import org.semanticweb.owlapi.model.OWLObjectHasSelf; 40 | import org.semanticweb.owlapi.model.OWLObjectHasValue; 41 | import org.semanticweb.owlapi.model.OWLObjectIntersectionOf; 42 | import org.semanticweb.owlapi.model.OWLObjectMaxCardinality; 43 | import org.semanticweb.owlapi.model.OWLObjectMinCardinality; 44 | import org.semanticweb.owlapi.model.OWLObjectOneOf; 45 | import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom; 46 | import org.semanticweb.owlapi.model.OWLObjectUnionOf; 47 | import org.semanticweb.owlapi.util.OWLObjectDuplicator; 48 | 49 | /** 50 | * @author Lorenz Buehmann 51 | * 52 | */ 53 | public class OWLClassExpressionMinimizer implements OWLClassExpressionVisitorEx{ 54 | 55 | private OWLDataFactory df; 56 | private OWLObjectDuplicator objectDuplicator; 57 | 58 | private boolean beautify = true; 59 | 60 | public OWLClassExpressionMinimizer(OWLDataFactory dataFactory) { 61 | this.df = dataFactory; 62 | 63 | objectDuplicator = new OWLObjectDuplicator(dataFactory); 64 | } 65 | 66 | public OWLClassExpression minimize(OWLClassExpression ce){ 67 | return ce.accept(this); 68 | } 69 | 70 | public OWLClassExpression minimizeClone(OWLClassExpression ce){ 71 | OWLClassExpression clone = objectDuplicator.duplicateObject(ce); 72 | return clone.accept(this); 73 | } 74 | 75 | /* (non-Javadoc) 76 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLClass) 77 | */ 78 | @Override 79 | public OWLClassExpression visit(OWLClass ce) { 80 | return ce; 81 | } 82 | 83 | /* (non-Javadoc) 84 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectIntersectionOf) 85 | */ 86 | @Override 87 | public OWLClassExpression visit(OWLObjectIntersectionOf ce) { 88 | List operands = ce.getOperandsAsList(); 89 | //replace operands by the short form 90 | for (int i = 0; i < operands.size(); i++) { 91 | operands.set(i, operands.get(i).accept(this)); 92 | } 93 | 94 | Set newOperands = new HashSet<>(operands); 95 | 96 | if(newOperands.size() == 1){ 97 | return newOperands.iterator().next().accept(this); 98 | } 99 | 100 | for (int i = 0; i < operands.size(); i++) { 101 | OWLClassExpression op1 = operands.get(i); 102 | for (int j = i + 1; j < operands.size(); j++) { 103 | OWLClassExpression op2 = operands.get(j); 104 | 105 | //remove operand if it is a super class 106 | if(isSubClassOf(op1, op2)){ 107 | newOperands.remove(op2); 108 | } else if(isSubClassOf(op2, op1)){ 109 | newOperands.remove(op1); 110 | } 111 | } 112 | } 113 | 114 | if(newOperands.size() == 1){ 115 | return newOperands.iterator().next().accept(this); 116 | } 117 | 118 | return df.getOWLObjectIntersectionOf(newOperands); 119 | } 120 | 121 | /** 122 | * Checks whether {@code subclass} is a subclass of {@code superclass}. 123 | * @param subClass the sub class 124 | * @param superClass the super class 125 | * @return whether {@code subclass} is a subclass of {@code superclass} 126 | */ 127 | private boolean isSubClassOf(OWLClassExpression subClass, OWLClassExpression superClass) { 128 | return subClass.isOWLNothing() || superClass.isOWLThing(); 129 | } 130 | 131 | /* (non-Javadoc) 132 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectUnionOf) 133 | */ 134 | @Override 135 | public OWLClassExpression visit(OWLObjectUnionOf ce) { 136 | List operands = ce.getOperandsAsList(); 137 | //replace operands by the short form 138 | for (int i = 0; i < operands.size(); i++) { 139 | operands.set(i, operands.get(i).accept(this)); 140 | } 141 | Set newOperands = new HashSet<>(operands); 142 | 143 | if(newOperands.size() == 1){ 144 | return newOperands.iterator().next().accept(this); 145 | } 146 | 147 | for (int i = 0; i < operands.size(); i++) { 148 | OWLClassExpression op1 = operands.get(i); 149 | for (int j = i + 1; j < operands.size(); j++) { 150 | OWLClassExpression op2 = operands.get(j); 151 | 152 | //remove operand if it is a subclass 153 | if(isSubClassOf(op2, op1)){ 154 | newOperands.remove(op2); 155 | } else if(isSubClassOf(op1, op2)){ 156 | newOperands.remove(op1); 157 | } else if(isSubClassOf(op1, df.getOWLObjectComplementOf(op2)) || isSubClassOf(op2, df.getOWLObjectComplementOf(op1))) { 158 | // check for C or not C 159 | return df.getOWLThing(); 160 | } 161 | } 162 | } 163 | 164 | if(newOperands.size() == 1){ 165 | return newOperands.iterator().next().accept(this); 166 | } 167 | 168 | 169 | 170 | 171 | return df.getOWLObjectUnionOf(newOperands); 172 | } 173 | 174 | /* (non-Javadoc) 175 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectComplementOf) 176 | */ 177 | @Override 178 | public OWLClassExpression visit(OWLObjectComplementOf ce) { 179 | OWLClassExpression operand = ce.getOperand(); 180 | OWLClassExpression shortendedOperand = operand.accept(this); 181 | if(shortendedOperand.isOWLThing()){// \neg \top \equiv \bot 182 | return df.getOWLNothing(); 183 | } else if(shortendedOperand.isOWLNothing()){// \neg \bot \equiv \top 184 | return df.getOWLThing(); 185 | } else if(operand != shortendedOperand){ 186 | return df.getOWLObjectComplementOf(shortendedOperand); 187 | } 188 | return ce; 189 | } 190 | 191 | /* (non-Javadoc) 192 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom) 193 | */ 194 | @Override 195 | public OWLClassExpression visit(OWLObjectSomeValuesFrom ce) { 196 | OWLClassExpression filler = ce.getFiller(); 197 | OWLClassExpression shortenedFiller = filler.accept(this); 198 | if(shortenedFiller.isOWLNothing()){// \exists r.\bottom \equiv \bottom 199 | return df.getOWLNothing(); 200 | } else if(!filler.equals(shortenedFiller)){ 201 | return df.getOWLObjectSomeValuesFrom(ce.getProperty(), shortenedFiller); 202 | } 203 | 204 | // convert r some {a} to r value a 205 | if(shortenedFiller instanceof OWLObjectOneOf && ((OWLObjectOneOf) shortenedFiller).getIndividuals().size() == 1) { 206 | return df.getOWLObjectHasValue(ce.getProperty(), ((OWLObjectOneOf) shortenedFiller).getIndividuals().iterator().next()); 207 | } 208 | return ce; 209 | } 210 | 211 | /* (non-Javadoc) 212 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectAllValuesFrom) 213 | */ 214 | @Override 215 | public OWLClassExpression visit(OWLObjectAllValuesFrom ce) { 216 | OWLClassExpression filler = ce.getFiller(); 217 | OWLClassExpression shortenedFiller = filler.accept(this); 218 | if(shortenedFiller.isOWLThing()){// \forall r.\top \equiv \top 219 | return df.getOWLThing(); 220 | } else if(beautify && shortenedFiller.isOWLNothing()) {// \forall r.\bot to \neg \exists r.\top 221 | return df.getOWLObjectComplementOf(df.getOWLObjectSomeValuesFrom(ce.getProperty(), df.getOWLThing())); 222 | } else if(!filler.equals(shortenedFiller)){ 223 | return df.getOWLObjectAllValuesFrom(ce.getProperty(), shortenedFiller); 224 | } 225 | return ce; 226 | } 227 | 228 | /* (non-Javadoc) 229 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectHasValue) 230 | */ 231 | @Override 232 | public OWLClassExpression visit(OWLObjectHasValue ce) { 233 | return ce; 234 | } 235 | 236 | /* (non-Javadoc) 237 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectMinCardinality) 238 | */ 239 | @Override 240 | public OWLClassExpression visit(OWLObjectMinCardinality ce) { 241 | // >= 0 r.C \equiv \top 242 | int cardinality = ce.getCardinality(); 243 | if (cardinality == 0) { 244 | return df.getOWLThing(); 245 | } 246 | OWLClassExpression filler = ce.getFiller(); 247 | OWLClassExpression shortenedFiller = filler.accept(this); 248 | if(shortenedFiller.isOWLNothing()){// >= n r.\bot \equiv \bot if n != 0 249 | return df.getOWLNothing(); 250 | } else if(!filler.equals(shortenedFiller)){ 251 | return df.getOWLObjectMinCardinality(ce.getCardinality(), ce.getProperty(), shortenedFiller); 252 | } 253 | return ce; 254 | } 255 | 256 | /* (non-Javadoc) 257 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectExactCardinality) 258 | */ 259 | @Override 260 | public OWLClassExpression visit(OWLObjectExactCardinality ce) { 261 | OWLClassExpression filler = ce.getFiller(); 262 | OWLClassExpression shortenedFiller = filler.accept(this); 263 | if(!filler.equals(shortenedFiller)){ 264 | return df.getOWLObjectExactCardinality(ce.getCardinality(), ce.getProperty(), shortenedFiller); 265 | } 266 | return ce; 267 | } 268 | 269 | /* (non-Javadoc) 270 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectMaxCardinality) 271 | */ 272 | @Override 273 | public OWLClassExpression visit(OWLObjectMaxCardinality ce) { 274 | OWLClassExpression filler = ce.getFiller(); 275 | OWLClassExpression shortenedFiller = filler.accept(this); 276 | if(shortenedFiller.isOWLNothing()){// <= n r.\bot \equiv \top 277 | return df.getOWLThing(); 278 | } else if(beautify && ce.getCardinality() == 0) {// we rewrite <= 0 r C to \neg \exists r C - easier to read for humans 279 | return df.getOWLObjectComplementOf(df.getOWLObjectSomeValuesFrom(ce.getProperty(), shortenedFiller)); 280 | } else if(!filler.equals(shortenedFiller)){ 281 | return df.getOWLObjectMaxCardinality(ce.getCardinality(), ce.getProperty(), shortenedFiller); 282 | } 283 | return ce; 284 | } 285 | 286 | /* (non-Javadoc) 287 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectHasSelf) 288 | */ 289 | @Override 290 | public OWLClassExpression visit(OWLObjectHasSelf ce) { 291 | return ce; 292 | } 293 | 294 | /* (non-Javadoc) 295 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLObjectOneOf) 296 | */ 297 | @Override 298 | public OWLClassExpression visit(OWLObjectOneOf ce) { 299 | return ce; 300 | } 301 | 302 | /* (non-Javadoc) 303 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLDataSomeValuesFrom) 304 | */ 305 | @Override 306 | public OWLClassExpression visit(OWLDataSomeValuesFrom ce) { 307 | return ce; 308 | } 309 | 310 | /* (non-Javadoc) 311 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLDataAllValuesFrom) 312 | */ 313 | @Override 314 | public OWLClassExpression visit(OWLDataAllValuesFrom ce) { 315 | return ce; 316 | } 317 | 318 | /* (non-Javadoc) 319 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLDataHasValue) 320 | */ 321 | @Override 322 | public OWLClassExpression visit(OWLDataHasValue ce) { 323 | return ce; 324 | } 325 | 326 | /* (non-Javadoc) 327 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLDataMinCardinality) 328 | */ 329 | @Override 330 | public OWLClassExpression visit(OWLDataMinCardinality ce) { 331 | return ce; 332 | } 333 | 334 | /* (non-Javadoc) 335 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLDataExactCardinality) 336 | */ 337 | @Override 338 | public OWLClassExpression visit(OWLDataExactCardinality ce) { 339 | return ce; 340 | } 341 | 342 | /* (non-Javadoc) 343 | * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx#visit(org.semanticweb.owlapi.model.OWLDataMaxCardinality) 344 | */ 345 | @Override 346 | public OWLClassExpression visit(OWLDataMaxCardinality ce) { 347 | return ce; 348 | } 349 | } 350 | -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/util/PermutationsOfN.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.util; 21 | 22 | import java.util.Collection; 23 | import java.util.List; 24 | 25 | import com.google.common.collect.Collections2; 26 | import com.google.common.collect.ImmutableList; 27 | import com.google.common.collect.Lists; 28 | 29 | public class PermutationsOfN { 30 | 31 | public static List> getSubsetsOfSizeN( List set, int k ) { 32 | if ( k > set.size() ) { 33 | k = set.size(); 34 | } 35 | List> result = Lists.newArrayList(); 36 | List subset = Lists.newArrayListWithCapacity( k ); 37 | for ( int i = 0; i < k; i++ ) { 38 | subset.add( null ); 39 | } 40 | return processLargerSubsets( result, set, subset, 0, 0 ); 41 | } 42 | 43 | private static List> processLargerSubsets( List> result, List set, List subset, int subsetSize, int nextIndex ) { 44 | if ( subsetSize == subset.size() ) { 45 | result.add( ImmutableList.copyOf( subset ) ); 46 | } else { 47 | for ( int j = nextIndex; j < set.size(); j++ ) { 48 | subset.set( subsetSize, set.get( j ) ); 49 | processLargerSubsets( result, set, subset, subsetSize + 1, j + 1 ); 50 | } 51 | } 52 | return result; 53 | } 54 | 55 | public static Collection> getPermutationsOfSizeN( List list, int size ) { 56 | Collection> all = Lists.newArrayList(); 57 | if ( list.size() < size ) { 58 | size = list.size(); 59 | } 60 | if ( list.size() == size ) { 61 | all.addAll( Collections2.permutations( list ) ); 62 | } else { 63 | for ( List p : getSubsetsOfSizeN( list, size ) ) { 64 | all.addAll( Collections2.permutations( p ) ); 65 | } 66 | } 67 | return all; 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/util/VarGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | /** 21 | * 22 | */ 23 | package org.aksw.owl2sparql.util; 24 | 25 | /** 26 | * @author Lorenz Buehmann 27 | * 28 | */ 29 | public class VarGenerator { 30 | 31 | private static final String header = "?"; 32 | private final String base; 33 | private int cnt = 0; 34 | 35 | public VarGenerator(String base) { 36 | this.base = base; 37 | } 38 | 39 | public VarGenerator() { 40 | this("s"); 41 | } 42 | 43 | public String newVar(){ 44 | return header + base + cnt++; 45 | } 46 | 47 | public void reset(){ 48 | cnt = 0; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/aksw/owl2sparql/util/VariablesMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.util; 21 | 22 | import java.util.HashMap; 23 | 24 | import org.semanticweb.owlapi.model.OWLEntity; 25 | 26 | public class VariablesMapping extends HashMap{ 27 | 28 | private VarGenerator classVarGenerator = new VarGenerator("cls"); 29 | private VarGenerator propertyVarGenerator = new VarGenerator("p"); 30 | private VarGenerator individualVarGenerator = new VarGenerator("s"); 31 | 32 | /** 33 | * Returns the already used variable for the given entity or creates a new one. 34 | * @param entity the OWL entity 35 | * @return the already used variable for the given entity or creates a new one 36 | */ 37 | public String getVariable(OWLEntity entity){ 38 | String var = get(entity); 39 | 40 | // create fresh variable 41 | if(var == null){ 42 | if(entity.isOWLClass()){ 43 | var = classVarGenerator.newVar(); 44 | } else if(entity.isOWLObjectProperty() || entity.isOWLDataProperty()){ 45 | var = propertyVarGenerator.newVar(); 46 | } else if(entity.isOWLNamedIndividual()){ 47 | var = individualVarGenerator.newVar(); 48 | } 49 | put(entity, var); 50 | } 51 | return var; 52 | } 53 | 54 | /** 55 | * @return a fresh variable used in subject/object position. 56 | */ 57 | public String newIndividualVariable(){ 58 | return individualVarGenerator.newVar(); 59 | } 60 | 61 | /** 62 | * @return a fresh variable used in predicate position. 63 | */ 64 | public String newPropertyVariable(){ 65 | return propertyVarGenerator.newVar(); 66 | } 67 | 68 | /** 69 | * Reset all settings. 70 | */ 71 | public void reset(){ 72 | clear(); 73 | classVarGenerator.reset(); 74 | propertyVarGenerator.reset(); 75 | individualVarGenerator.reset(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # suppress inspection "UnusedProperty" for whole file 2 | # All loggers will default to the INFO level unless specified in a specific logger 3 | # For more information, see the Log4J API manual at: http://bit.ly/KmvtWL . 4 | log4j.rootLogger=INFO, stdout 5 | 6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.stdout.layout.ConversionPattern= %-4r [%t] %-5p %c %x - %m%n 9 | 10 | # basic log level 11 | log4j.logger.org.aksw.owl2sparql=INFO 12 | 13 | # hide OWL API warning "entityExpansionLimit not supported by parser" 14 | log4j.logger.org.semanticweb.owlapi.util.SAXParsers=ERROR 15 | # hide OWL API warning "dumping remaining triples" 16 | log4j.logger.org.semanticweb.owlapi.rdf.rdfxml.parser.OWLRDFConsumer=ERROR 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/test/java/org/aksw/owl2sparql/OWLAxiomToSPARQLConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql; 21 | 22 | import com.google.common.collect.Lists; 23 | import com.google.common.collect.Sets; 24 | import com.hp.hpl.jena.query.Query; 25 | import com.hp.hpl.jena.query.QueryFactory; 26 | import org.junit.BeforeClass; 27 | import org.junit.Test; 28 | import org.semanticweb.owlapi.apibinding.OWLManager; 29 | import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer; 30 | import org.semanticweb.owlapi.io.ToStringRenderer; 31 | import org.semanticweb.owlapi.model.*; 32 | import org.semanticweb.owlapi.util.DefaultPrefixManager; 33 | 34 | import static org.junit.Assert.assertTrue; 35 | 36 | /** 37 | * @author Lorenz Buehmann 38 | * 39 | */ 40 | public class OWLAxiomToSPARQLConverterTest { 41 | 42 | private OWLAxiomToSPARQLConverter converter = new OWLAxiomToSPARQLConverter("?s","?o"); 43 | 44 | private OWLOntologyManager man = OWLManager.createOWLOntologyManager(); 45 | private OWLDataFactory df = man.getOWLDataFactory(); 46 | private PrefixManager pm = new DefaultPrefixManager(); 47 | 48 | private OWLClass clsA = df.getOWLClass("A", pm); 49 | private OWLClass clsB = df.getOWLClass("B", pm); 50 | private OWLClass clsC = df.getOWLClass("C", pm); 51 | private OWLClass clsD = df.getOWLClass("D", pm); 52 | 53 | private OWLObjectProperty propR = df.getOWLObjectProperty("r", pm); 54 | private OWLObjectProperty propS = df.getOWLObjectProperty("s", pm); 55 | private OWLObjectProperty propT = df.getOWLObjectProperty("t", pm); 56 | 57 | private OWLDataProperty dpT = df.getOWLDataProperty("dpT", pm); 58 | private OWLDataRange booleanRange = df.getBooleanOWLDatatype(); 59 | private OWLLiteral lit = df.getOWLLiteral(1); 60 | 61 | private OWLIndividual indA = df.getOWLNamedIndividual("a", pm); 62 | private OWLIndividual indB = df.getOWLNamedIndividual("b", pm); 63 | 64 | private OWLClassExpression ce1 = df.getOWLObjectOneOf(indA, indB); 65 | private OWLClassExpression ce2 = df.getOWLDataHasValue(dpT, lit); 66 | 67 | public OWLAxiomToSPARQLConverterTest() { 68 | pm.setDefaultPrefix("http://foo.bar/"); 69 | } 70 | 71 | 72 | /** 73 | * @throws java.lang.Exception 74 | */ 75 | @BeforeClass 76 | public static void setUpBeforeClass() throws Exception { 77 | ToStringRenderer.getInstance().setRenderer(new DLSyntaxObjectRenderer()); 78 | } 79 | 80 | @Test 81 | public void testSubClassOfAxiom() { 82 | OWLClassExpression subClass = clsA; 83 | OWLClassExpression superClass = clsB; 84 | OWLAxiom axiom = df.getOWLSubClassOfAxiom(subClass, superClass); 85 | 86 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 87 | "WHERE\n" + 88 | " { ?s .\n" + 89 | " ?s \n" + 90 | " }"); 91 | Query query = converter.asQuery(axiom); 92 | 93 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 94 | 95 | subClass = ce1; 96 | superClass = ce2; 97 | axiom = df.getOWLSubClassOfAxiom(subClass, superClass); 98 | 99 | targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 100 | "WHERE\n" + 101 | " { VALUES ?s { }\n" + 102 | " ?s 1\n" + 103 | " }"); 104 | query = converter.asQuery(axiom); 105 | 106 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 107 | 108 | } 109 | 110 | @Test 111 | public void testEquivalentClassesAxiom() { 112 | OWLAxiom axiom = df.getOWLEquivalentClassesAxiom(clsA, clsB, clsC); 113 | 114 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 115 | "WHERE\n" + 116 | " { ?s .\n" + 117 | " ?s .\n" + 118 | " ?s \n" + 119 | " }"); 120 | Query query = converter.asQuery(axiom); 121 | 122 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 123 | } 124 | 125 | @Test 126 | public void testDisjointClassesAxiom() { 127 | OWLAxiom axiom = df.getOWLDisjointClassesAxiom(clsA, clsB, clsC); 128 | 129 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 130 | "WHERE\n" + 131 | " { { ?s \n" + 132 | " FILTER NOT EXISTS {?s }\n" + 133 | " FILTER NOT EXISTS {?s }\n" + 134 | " }\n" + 135 | " UNION\n" + 136 | " { ?s \n" + 137 | " FILTER NOT EXISTS {?s }\n" + 138 | " FILTER NOT EXISTS {?s }\n" + 139 | " }\n" + 140 | " UNION\n" + 141 | " { ?s \n" + 142 | " FILTER NOT EXISTS {?s }\n" + 143 | " FILTER NOT EXISTS {?s }\n" + 144 | " }\n" + 145 | " }"); 146 | Query query = converter.asQuery(axiom); 147 | 148 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 149 | } 150 | 151 | @Test 152 | public void testDisjointUnionAxiom() { 153 | OWLAxiom axiom = df.getOWLDisjointUnionAxiom(clsA, Sets.newHashSet(clsB, clsC, clsD)); 154 | 155 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 156 | " WHERE\n" + 157 | " { ?s \n" + 158 | " { ?s \n" + 159 | " FILTER NOT EXISTS {?s }\n" + 160 | " FILTER NOT EXISTS {?s }\n" + 161 | " }\n" + 162 | " UNION\n" + 163 | " { ?s \n" + 164 | " FILTER NOT EXISTS {?s }\n" + 165 | " FILTER NOT EXISTS {?s }\n" + 166 | " }\n" + 167 | " UNION\n" + 168 | " { ?s \n" + 169 | " FILTER NOT EXISTS {?s }\n" + 170 | " FILTER NOT EXISTS {?s }\n" + 171 | " }\n" + 172 | " }"); 173 | Query query = converter.asQuery(axiom); 174 | 175 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 176 | } 177 | 178 | @Test 179 | public void testSubPropertyAxiom() { 180 | OWLAxiom axiom = df.getOWLSubObjectPropertyOfAxiom(propR, propS); 181 | 182 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 183 | " WHERE\n" + 184 | " { ?s ?o .\n" + 185 | " ?s ?o\n" + 186 | " }"); 187 | Query query = converter.asQuery(axiom); 188 | 189 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 190 | } 191 | 192 | @Test 193 | public void testEquivalentPropertiesAxiom() { 194 | OWLAxiom axiom = df.getOWLEquivalentObjectPropertiesAxiom(propR, propS, propT); 195 | 196 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 197 | " WHERE\n" + 198 | " { ?s ?o .\n" + 199 | " ?s ?o .\n" + 200 | " ?s ?o\n" + 201 | " }"); 202 | Query query = converter.asQuery(axiom); 203 | 204 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 205 | } 206 | 207 | @Test 208 | public void testDisjointPropertiesAxiom() { 209 | OWLAxiom axiom = df.getOWLDisjointObjectPropertiesAxiom(propR, propS, propT); 210 | 211 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 212 | "WHERE\n" + 213 | " { { ?s ?o\n" + 214 | " FILTER NOT EXISTS {?s ?o }\n" + 215 | " FILTER NOT EXISTS {?s ?o }\n" + 216 | " }\n" + 217 | " UNION\n" + 218 | " { ?s ?o\n" + 219 | " FILTER NOT EXISTS {?s ?o }\n" + 220 | " FILTER NOT EXISTS {?s ?o }\n" + 221 | " }\n" + 222 | " UNION\n" + 223 | " { ?s ?o\n" + 224 | " FILTER NOT EXISTS {?s ?o }\n" + 225 | " FILTER NOT EXISTS {?s ?o }\n" + 226 | " }\n" + 227 | " }"); 228 | Query query = converter.asQuery(axiom); 229 | 230 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 231 | } 232 | 233 | @Test 234 | public void testPropertyDomainAxiom() { 235 | OWLAxiom axiom = df.getOWLObjectPropertyDomainAxiom(propR, clsA); 236 | 237 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 238 | " WHERE\n" + 239 | " { ?s ?s0 .\n" + 240 | " ?s \n" + 241 | " }"); 242 | Query query = converter.asQuery(axiom); 243 | 244 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 245 | } 246 | 247 | @Test 248 | public void testObjectPropertyRangeAxiom() { 249 | OWLAxiom axiom = df.getOWLObjectPropertyRangeAxiom(propR, clsA); 250 | 251 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 252 | " WHERE\n" + 253 | " { ?s ?p ?o\n" + 254 | " FILTER NOT EXISTS {?s ?s1\n" + 255 | " FILTER NOT EXISTS {?s1 }\n" + 256 | " }\n" + 257 | " }"); 258 | Query query = converter.asQuery(axiom); 259 | 260 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 261 | } 262 | 263 | @Test 264 | public void testDataPropertyRangeAxiom() { 265 | OWLAxiom axiom = df.getOWLDataPropertyRangeAxiom(dpT, booleanRange); 266 | 267 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 268 | " WHERE\n" + 269 | " { ?s ?o\n" + 270 | " FILTER ( datatype(?o) = )\n" + 271 | " }"); 272 | Query query = converter.asQuery(axiom); 273 | 274 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 275 | } 276 | 277 | @Test 278 | public void testAsymmetricObjectPropertyAxiom() { 279 | OWLAxiom axiom = df.getOWLAsymmetricObjectPropertyAxiom(propR); 280 | 281 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 282 | " WHERE\n" + 283 | " { ?s ?o\n" + 284 | " FILTER NOT EXISTS {?o ?s }\n" + 285 | " }"); 286 | Query query = converter.asQuery(axiom); 287 | 288 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 289 | } 290 | 291 | @Test 292 | public void testSymmetricObjectPropertyAxiom() { 293 | OWLAxiom axiom = df.getOWLSymmetricObjectPropertyAxiom(propR); 294 | 295 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 296 | " WHERE\n" + 297 | " { ?s ?o .\n" + 298 | " ?o ?s \n" + 299 | " }"); 300 | Query query = converter.asQuery(axiom); 301 | 302 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 303 | } 304 | 305 | @Test 306 | public void testReflexiveObjectPropertyAxiom() { 307 | OWLAxiom axiom = df.getOWLReflexiveObjectPropertyAxiom(propR); 308 | 309 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 310 | " WHERE\n" + 311 | " { ?s ?s\n" + 312 | " }"); 313 | Query query = converter.asQuery(axiom); 314 | 315 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 316 | } 317 | 318 | @Test 319 | public void testIrreflexiveObjectPropertyAxiom() { 320 | OWLAxiom axiom = df.getOWLIrreflexiveObjectPropertyAxiom(propR); 321 | 322 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 323 | " WHERE\n" + 324 | " { ?s ?p ?o\n" + 325 | " FILTER NOT EXISTS {?s ?s }\n" + 326 | " }"); 327 | Query query = converter.asQuery(axiom); 328 | 329 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 330 | } 331 | 332 | @Test 333 | public void testFunctionalObjectPropertyAxiom() { 334 | OWLAxiom axiom = df.getOWLFunctionalObjectPropertyAxiom(propR); 335 | 336 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 337 | " WHERE\n" + 338 | " { ?s ?s0\n" + 339 | " FILTER NOT EXISTS {?s ?s1\n" + 340 | " FILTER ( ! sameTerm(?s0, ?s1) )\n" + 341 | " }\n" + 342 | " }"); 343 | Query query = converter.asQuery(axiom); 344 | 345 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 346 | } 347 | 348 | @Test 349 | public void testInverseFunctionalObjectPropertyAxiom() { 350 | OWLAxiom axiom = df.getOWLInverseFunctionalObjectPropertyAxiom(propR); 351 | 352 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 353 | " WHERE\n" + 354 | " { ?s0 ?s\n" + 355 | " FILTER NOT EXISTS {?s1 ?s\n" + 356 | " FILTER ( ! sameTerm(?s0, ?s1) )\n" + 357 | " }\n" + 358 | " }"); 359 | Query query = converter.asQuery(axiom); 360 | 361 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 362 | } 363 | 364 | @Test 365 | public void testTransitiveObjectPropertyAxiom() { 366 | OWLAxiom axiom = df.getOWLTransitiveObjectPropertyAxiom(propR); 367 | 368 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 369 | " WHERE\n" + 370 | " { ?s ?o1 .\n" + 371 | " ?o1 ?o .\n" + 372 | " ?s ?o\n" + 373 | " }"); 374 | Query query = converter.asQuery(axiom); 375 | 376 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 377 | } 378 | 379 | @Test 380 | public void testSubPropertyChainAxiom() { 381 | OWLAxiom axiom = df.getOWLSubPropertyChainOfAxiom(Lists.newArrayList(propR, propS, propT), propT); 382 | 383 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s \n" + 384 | " WHERE\n" + 385 | " { ?s ?s0 .\n" + 386 | " ?s0 ?s1 .\n" + 387 | " ?s1 ?o .\n" + 388 | " ?s ?o\n" + 389 | " }"); 390 | Query query = converter.asQuery(axiom); 391 | 392 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 393 | } 394 | 395 | @Test 396 | public void testInversePropertiesAxiom() { 397 | OWLAxiom axiom = df.getOWLInverseObjectPropertiesAxiom(propR, propS); 398 | 399 | Query targetQuery = QueryFactory.create("SELECT DISTINCT ?s\n" + 400 | "WHERE\n" + 401 | " { ?s ?o .\n" + 402 | " ?o ?s .\n" + 403 | " ?s ?o .\n" + 404 | " ?o ?s\n" + 405 | " }"); 406 | Query query = converter.asQuery(axiom); 407 | 408 | assertTrue("Conversion of axiom " + axiom + " failed.\n" + query + " does not match " + targetQuery, query.equals(targetQuery)); 409 | } 410 | 411 | } 412 | -------------------------------------------------------------------------------- /src/test/java/org/aksw/owl2sparql/example/HTMLTableBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 - 2016 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.example; 21 | 22 | /** 23 | * Uses: 24 | * HTMLTableBuilder htmlBuilder = new HTMLTableBuilder(null, true, 2, 3); 25 | * htmlBuilder.addTableHeader("1H", "2H", "3H"); 26 | * htmlBuilder.addRowValues("1", "2", "3"); 27 | * htmlBuilder.addRowValues("4", "5", "6"); 28 | * htmlBuilder.addRowValues("9", "8", "7"); 29 | * String table = htmlBuilder.build(); 30 | * System.out.println(table.toString()); 31 | */ 32 | 33 | public class HTMLTableBuilder { 34 | 35 | private static String HTML_HEAD = 36 | "\n" + 37 | "\n" + 38 | "\n" + 39 | "\n" + 81 | "\n" + 82 | "\n" + 83 | "\n" + 84 | "\n"; 85 | 86 | public static String HTML_START = ""; 87 | public static String HTML_END = "\n"; 88 | public static String TABLE_START_BORDER = "\n"; 89 | public static String TABLE_START = "\n
"; 90 | public static String TABLE_END = "\n
"; 91 | public static String HEADER_START = ""; 92 | public static String HEADER_END = "\n"; 93 | public static String ROW_START = "\n"; 94 | public static String ROW_END = ""; 95 | public static String COLUMN_START = ""; 96 | public static String COLUMN_END = ""; 97 | private final StringBuilder table = new StringBuilder(); 98 | private int columns; 99 | 100 | 101 | /** 102 | * @param header 103 | * @param border 104 | * @param rows 105 | * @param columns 106 | */ 107 | public HTMLTableBuilder(String header, boolean border, int rows, int columns) { 108 | this.columns = columns; 109 | if (header != null) { 110 | table.append(""); 111 | table.append(header); 112 | table.append(""); 113 | } 114 | table.append(HTML_START); 115 | table.append(HTML_HEAD); 116 | table.append(border ? TABLE_START_BORDER : TABLE_START); 117 | table.append(TABLE_END); 118 | table.append(HTML_END); 119 | } 120 | 121 | /** 122 | * @param args 123 | */ 124 | public static void main(String[] args) { 125 | HTMLTableBuilder htmlBuilder = new HTMLTableBuilder(null, true, 2, 3); 126 | htmlBuilder.addTableHeader("1H", "2H", "3H"); 127 | htmlBuilder.addRowValues("1", "2", "3"); 128 | htmlBuilder.addRowValues("4", "5", "6"); 129 | htmlBuilder.addRowValues("9", "8", "7"); 130 | String table = htmlBuilder.build(); 131 | System.out.println(table.toString()); 132 | } 133 | 134 | /** 135 | * @param values 136 | */ 137 | public void addTableHeader(String... values) { 138 | if (values.length != columns) { 139 | System.out.println("Error column length"); 140 | } else { 141 | int lastIndex = table.lastIndexOf(TABLE_END); 142 | if (lastIndex > 0) { 143 | StringBuilder sb = new StringBuilder(); 144 | sb.append(ROW_START); 145 | for (String value : values) { 146 | sb.append(HEADER_START); 147 | sb.append(value); 148 | sb.append(HEADER_END); 149 | } 150 | sb.append(ROW_END); 151 | table.insert(lastIndex, sb.toString()); 152 | } 153 | } 154 | } 155 | 156 | /** 157 | * @param values 158 | */ 159 | public void addRowValues(String... values) { 160 | if (values.length != columns) { 161 | System.out.println("Error column length"); 162 | } else { 163 | int lastIndex = table.lastIndexOf(ROW_END); 164 | if (lastIndex > 0) { 165 | int index = lastIndex + ROW_END.length(); 166 | StringBuilder sb = new StringBuilder(); 167 | sb.append(ROW_START); 168 | for (String value : values) { 169 | sb.append(COLUMN_START); 170 | sb.append(value); 171 | sb.append(COLUMN_END); 172 | } 173 | sb.append(ROW_END); 174 | table.insert(index, sb.toString()); 175 | } 176 | } 177 | } 178 | 179 | /** 180 | * @return 181 | */ 182 | public String build() { 183 | return table.toString(); 184 | } 185 | 186 | 187 | } -------------------------------------------------------------------------------- /src/test/java/org/aksw/owl2sparql/example/OWLClassExpressionConversionExamples.java: -------------------------------------------------------------------------------- 1 | /* 2 | * #%L 3 | * owl2sparql-core 4 | * %% 5 | * Copyright (C) 2015 - 2016 AKSW 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * #L% 19 | */ 20 | package org.aksw.owl2sparql.example; 21 | 22 | import com.google.common.base.Charsets; 23 | import com.google.common.collect.Lists; 24 | import com.hp.hpl.jena.query.Query; 25 | import com.hp.hpl.jena.shared.PrefixMapping; 26 | import com.hp.hpl.jena.shared.impl.PrefixMappingImpl; 27 | import org.aksw.owl2sparql.OWLClassExpressionToSPARQLConverter; 28 | import org.aksw.owl2sparql.style.AllQuantorTranslation; 29 | import org.aksw.owl2sparql.util.OWLClassExpressionMinimizer; 30 | import org.semanticweb.owlapi.apibinding.OWLManager; 31 | import org.semanticweb.owlapi.io.ToStringRenderer; 32 | import org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntax; 33 | import org.semanticweb.owlapi.manchestersyntax.renderer.ManchesterOWLSyntaxOWLObjectRendererImpl; 34 | import org.semanticweb.owlapi.model.*; 35 | import org.semanticweb.owlapi.util.DefaultPrefixManager; 36 | import org.semanticweb.owlapi.vocab.OWLFacet; 37 | 38 | import java.io.File; 39 | import java.util.Arrays; 40 | import java.util.List; 41 | import java.util.TreeSet; 42 | 43 | /** 44 | * @author Lorenz Buehmann 45 | */ 46 | public class OWLClassExpressionConversionExamples { 47 | 48 | public static void main(String[] args) throws Exception { 49 | ToStringRenderer.getInstance().setRenderer(new ManchesterOWLSyntaxOWLObjectRendererImpl()); 50 | 51 | OWLClassExpressionToSPARQLConverter converter = new OWLClassExpressionToSPARQLConverter(); 52 | converter.setAllQuantorTranslation(AllQuantorTranslation.DOUBLE_NEGATION); 53 | 54 | String NS = "http://example.org/ontology/"; 55 | OWLOntologyManager man = OWLManager.createOWLOntologyManager(); 56 | OWLDataFactory df = man.getOWLDataFactory(); 57 | PrefixManager pm = new DefaultPrefixManager(); 58 | pm.setDefaultPrefix(NS); 59 | OWLClassExpressionMinimizer minimizer = new OWLClassExpressionMinimizer(df); 60 | 61 | OWLClass clsA = df.getOWLClass("A", pm); 62 | OWLClass clsB = df.getOWLClass("B", pm); 63 | OWLClass clsC = df.getOWLClass("C", pm); 64 | 65 | OWLObjectProperty propR = df.getOWLObjectProperty("r", pm); 66 | OWLObjectProperty propS = df.getOWLObjectProperty("s", pm); 67 | 68 | OWLDataProperty dpT = df.getOWLDataProperty("t", pm); 69 | OWLDataRange booleanRange = df.getBooleanOWLDatatype(); 70 | OWLLiteral lit = df.getOWLLiteral(1); 71 | 72 | OWLIndividual indA = df.getOWLNamedIndividual("a", pm); 73 | OWLIndividual indB = df.getOWLNamedIndividual("b", pm); 74 | 75 | String rootVar = "?x"; 76 | 77 | List classExpressions = Lists.newArrayList( 78 | clsA, 79 | df.getOWLObjectSomeValuesFrom(propR, clsB), 80 | df.getOWLObjectIntersectionOf( 81 | df.getOWLObjectSomeValuesFrom(propR, clsB), 82 | clsB), 83 | df.getOWLObjectUnionOf( 84 | clsA, 85 | clsB), 86 | df.getOWLObjectHasValue(propR, 87 | indA), 88 | df.getOWLObjectAllValuesFrom(propR, 89 | df.getOWLThing()), 90 | df.getOWLObjectAllValuesFrom(propR, 91 | df.getOWLObjectAllValuesFrom(propS, df.getOWLThing())), 92 | df.getOWLObjectAllValuesFrom( 93 | propR, 94 | df.getOWLObjectIntersectionOf( 95 | clsA, 96 | df.getOWLObjectAllValuesFrom(propS, df.getOWLThing()))), 97 | df.getOWLObjectAllValuesFrom( 98 | propR, 99 | df.getOWLObjectUnionOf( 100 | clsA, 101 | df.getOWLObjectAllValuesFrom(propS, df.getOWLThing()))), 102 | df.getOWLObjectAllValuesFrom(propR, clsB), 103 | df.getOWLObjectAllValuesFrom(df.getOWLObjectProperty("language", pm), df.getOWLClass("Language", pm)), 104 | df.getOWLObjectMinCardinality(2, df.getOWLObjectProperty("language", pm), df.getOWLClass("Language", pm)), 105 | df.getOWLObjectIntersectionOf( 106 | df.getOWLClass("Place", pm), 107 | df.getOWLObjectMinCardinality( 108 | 2, 109 | df.getOWLObjectProperty("language", pm), 110 | df.getOWLClass("Language", pm))), 111 | df.getOWLObjectOneOf(indA, indB), 112 | df.getOWLObjectSomeValuesFrom( 113 | propR, 114 | df.getOWLObjectOneOf(indA)), 115 | df.getOWLObjectSomeValuesFrom(propR, df.getOWLObjectOneOf(indA, indB)), 116 | df.getOWLObjectIntersectionOf( 117 | clsA, 118 | df.getOWLObjectHasSelf(propR)), 119 | df.getOWLObjectIntersectionOf( 120 | clsA, 121 | df.getOWLDataSomeValuesFrom(dpT, booleanRange)), 122 | df.getOWLObjectIntersectionOf( 123 | clsA, 124 | df.getOWLDataHasValue(dpT, lit)), 125 | df.getOWLObjectIntersectionOf( 126 | clsA, 127 | df.getOWLDataMinCardinality(2, dpT, booleanRange)), 128 | df.getOWLObjectIntersectionOf( 129 | clsA, 130 | df.getOWLObjectComplementOf(clsB)), 131 | df.getOWLObjectSomeValuesFrom(propR, 132 | df.getOWLObjectIntersectionOf( 133 | clsA, 134 | df.getOWLObjectComplementOf(clsB))), 135 | df.getOWLDataAllValuesFrom(dpT, booleanRange), 136 | df.getOWLDataAllValuesFrom(dpT,df.getOWLDataOneOf(lit)), 137 | df.getOWLObjectIntersectionOf( 138 | df.getOWLObjectSomeValuesFrom( 139 | propR, 140 | clsB), 141 | clsB, 142 | df.getOWLObjectSomeValuesFrom(propS, clsA)), 143 | df.getOWLObjectComplementOf(clsB), 144 | df.getOWLObjectIntersectionOf( 145 | df.getOWLObjectSomeValuesFrom( 146 | propR, 147 | df.getOWLObjectIntersectionOf( 148 | df.getOWLObjectSomeValuesFrom(propS, clsA), 149 | clsC)), 150 | clsB), 151 | df.getOWLObjectIntersectionOf( 152 | df.getOWLObjectComplementOf(clsA), 153 | df.getOWLObjectSomeValuesFrom( 154 | propR, 155 | df.getOWLObjectSomeValuesFrom( 156 | propS, 157 | df.getOWLObjectComplementOf(clsB) 158 | ) 159 | ) 160 | ), 161 | df.getOWLObjectUnionOf( 162 | df.getOWLObjectComplementOf(clsA), 163 | df.getOWLObjectComplementOf(clsB) 164 | ), 165 | df.getOWLObjectIntersectionOf( 166 | clsA, 167 | df.getOWLObjectUnionOf( 168 | clsB, 169 | df.getOWLObjectComplementOf( 170 | df.getOWLObjectSomeValuesFrom( 171 | propR, 172 | df.getOWLThing() 173 | ) 174 | ) 175 | ) 176 | ), 177 | df.getOWLObjectIntersectionOf( 178 | clsA, 179 | df.getOWLObjectComplementOf( 180 | df.getOWLObjectSomeValuesFrom( 181 | propR, 182 | clsB 183 | ) 184 | ) 185 | ), 186 | df.getOWLObjectIntersectionOf( 187 | clsA, 188 | df.getOWLDataSomeValuesFrom(dpT, df.getOWLDataComplementOf(booleanRange)) 189 | ), 190 | df.getOWLDataSomeValuesFrom(dpT,df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2))), 191 | df.getOWLDataSomeValuesFrom( 192 | dpT, 193 | df.getOWLDataComplementOf( 194 | df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2)))), 195 | df.getOWLDataSomeValuesFrom( 196 | dpT, 197 | df.getOWLDataIntersectionOf( 198 | df.getBooleanOWLDatatype(), 199 | df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2)))), 200 | df.getOWLDataSomeValuesFrom( 201 | dpT, 202 | df.getOWLDataUnionOf( 203 | df.getIntegerOWLDatatype(), 204 | df.getOWLDataIntersectionOf( 205 | df.getBooleanOWLDatatype(), 206 | df.getOWLDataOneOf(df.getOWLLiteral(1), df.getOWLLiteral(2))))), 207 | df.getOWLDataSomeValuesFrom( 208 | dpT, 209 | df.getOWLDatatypeRestriction( 210 | df.getIntegerOWLDatatype(), 211 | df.getOWLFacetRestriction( 212 | OWLFacet.MAX_EXCLUSIVE, df.getOWLLiteral(10)), 213 | df.getOWLFacetRestriction( 214 | OWLFacet.MIN_INCLUSIVE, df.getOWLLiteral(3)))), 215 | df.getOWLDataSomeValuesFrom( 216 | dpT, 217 | df.getOWLDatatypeRestriction( 218 | df.getRDFPlainLiteral(), 219 | df.getOWLFacetRestriction( 220 | OWLFacet.LENGTH, df.getOWLLiteral(10)))) 221 | 222 | ); 223 | 224 | 225 | HTMLTableBuilder html = new HTMLTableBuilder("OWL To SPARQL Converter", true, classExpressions.size(), 2); 226 | html.addTableHeader("Class Expression", "SPARQL Query"); 227 | String[] keywords = {"WHERE", "SELECT", "DISTINCT", "FILTER", "NOT", "EXISTS", "UNION", "OPTIONAL", "GROUP BY", "HAVING", "COUNT", " IN", "PREFIX", "BASE"}; 228 | 229 | for (OWLClassExpression ce : new TreeSet<>(classExpressions)) { 230 | Query query = converter.asQuery(ce, rootVar); 231 | PrefixMapping pm2 = new PrefixMappingImpl(); 232 | if(query.toString().contains("rdf-schema#")) { 233 | pm2.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); 234 | } 235 | if(query.toString().contains("rdf-syntax-ns#")) { 236 | pm2.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); 237 | } 238 | if(query.toString().contains("XMLSchema#")) { 239 | pm2.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#"); 240 | } 241 | query.setPrefixMapping(pm2); 242 | query.setBaseURI(NS); 243 | System.out.println(ce + "\n" + query); 244 | 245 | String ceString = ce.toString(); 246 | String queryString = query.toString(); 247 | 248 | // add comment if CE was rewritten 249 | OWLClassExpression minCE = minimizer.minimize(ce); 250 | if(!ce.equals(minCE)) { 251 | ceString += "\n(logically equivalent to\n" + minCE.toString() + ")"; 252 | } 253 | // format OWL class expression 254 | for(ManchesterOWLSyntax keyword : ManchesterOWLSyntax.values()) { 255 | if(keyword.isClassExpressionConnectiveKeyword() || keyword.isClassExpressionQuantiferKeyword()) 256 | ceString = ceString.replace(keyword.keyword(), "" + keyword + ""); 257 | } 258 | 259 | // format SPARQL query 260 | queryString = queryString.replace("<", "<").replace(">", ">"); 261 | for (String keyword : keywords) { 262 | queryString = queryString.replace(keyword , "" + keyword + ""); 263 | } 264 | // add to HTML table 265 | html.addRowValues("
" + ceString + "
", "
" + queryString + "
"); 266 | } 267 | com.google.common.io.Files.write(html.build(), new File("examples/owl2sparql-examples.html"), Charsets.UTF_8); 268 | // Files.write(Paths.get("/tmp/owl2sparql.html"), Arrays.asList(html.build().split("\n")), Charset.forName("UTF-8")); 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # suppress inspection "UnusedProperty" for whole file 2 | # All loggers will default to the INFO level unless specified in a specific logger 3 | # For more information, see the Log4J API manual at: http://bit.ly/KmvtWL . 4 | log4j.rootLogger=INFO, stdout 5 | 6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.stdout.layout.ConversionPattern= %-4r [%t] %-5p %c %x - %m%n 9 | 10 | # basic log level 11 | log4j.logger.org.aksw.owl2sparql=DEBUG 12 | 13 | # hide OWL API warning "entityExpansionLimit not supported by parser" 14 | log4j.logger.org.semanticweb.owlapi.util.SAXParsers=ERROR 15 | # hide OWL API warning "dumping remaining triples" 16 | log4j.logger.org.semanticweb.owlapi.rdf.rdfxml.parser.OWLRDFConsumer=ERROR 17 | 18 | 19 | 20 | --------------------------------------------------------------------------------