001/**
002 * Copyright (C) 2007 - 2016, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.dllearner.utilities.owl;
020
021import com.google.common.collect.ComparisonChain;
022import org.semanticweb.owlapi.io.*;
023import org.semanticweb.owlapi.model.*;
024import org.semanticweb.owlapi.rdf.model.AbstractTranslator;
025import org.semanticweb.owlapi.util.AlwaysOutputId;
026import org.semanticweb.owlapi.util.AxiomAppearance;
027import org.semanticweb.owlapi.util.IndividualAppearance;
028import org.semanticweb.owlapi.util.OWLAnonymousIndividualsWithMultipleOccurrences;
029
030import javax.annotation.Nonnull;
031import java.util.Collection;
032import java.util.Collections;
033import java.util.List;
034import java.util.Map;
035import java.util.concurrent.atomic.AtomicInteger;
036
037import static org.semanticweb.owlapi.util.OWLAPIPreconditions.checkNotNull;
038
039/**
040 * A converter of OWL axioms or OWL ontology changes into SPARQL 1.1 Update commands.
041 *
042 * @author Lorenz Buehmann
043 */
044public class OWL2SPARULConverter
045                extends
046                AbstractTranslator<RDFNode, RDFResource, RDFResourceIRI, RDFLiteral> {
047        private StringBuilder sb;
048
049        public OWL2SPARULConverter(OWLOntologyManager manager,
050                                                           OWLOntology ontology, boolean useStrongTyping, IndividualAppearance individualAppearance,
051                                                           AxiomAppearance axiomAppearance, AtomicInteger nextNode, Map<Object, Integer> blankNodeMap) {
052                super(manager, ontology, useStrongTyping, individualAppearance, axiomAppearance, nextNode, blankNodeMap);
053        }
054
055        public OWL2SPARULConverter(OWLOntology ontology, boolean useStrongTyping) {
056                this(ontology.getOWLOntologyManager(), ontology, useStrongTyping,
057                         new OWLAnonymousIndividualsWithMultipleOccurrences(), new AlwaysOutputId(), new AtomicInteger(), Collections.emptyMap());
058        }
059
060        /**
061         * Converts an OWL axioms to a SPARQL 1.1 Update command.
062         *
063         * @param axiom the OWL axiom
064         * @param add    whether the axiom has to be added('ADD') or removed('DELETE')
065         * @return the SPARQL 1.1 Update command
066         */
067        public String convert(OWLAxiom axiom, boolean add) {
068                return convert(Collections.singleton(axiom), add);
069        }
070
071        /**
072         * Converts a set of OWL axioms to a SPARQL 1.1 Update command.
073         *
074         * @param axioms the OWL axioms
075         * @param add    whether those axioms have to be added('ADD') or removed('DELETE')
076         * @return the SPARQL 1.1 Update command
077         */
078        public String convert(Collection<OWLAxiom> axioms, boolean add) {
079                sb = new StringBuilder();
080                for (OWLAxiom ax : axioms) {
081                        sb.append(add ? "INSERT DATA" : "DELETE DATA");
082                        sb.append("{");
083                        ax.accept(this);
084                        sb.append("}");
085                        sb.append("\n");
086                }
087                return sb.toString();
088        }
089
090        /**
091         * Converts an OWL ontology change to a SPARQL 1.1 Update command.
092         *
093         * @param change the OWL ontology change
094         * @return the SPARQL 1.1 Update command
095         */
096        public String convert(OWLOntologyChange change) {
097                return convert(Collections.singletonList(change));
098        }
099
100        /**
101         * Converts a list of OWL ontology changes to a SPARQL 1.1 Update command.
102         *
103         * @param changes the ontology changes
104         * @return the SPARQL 1.1 Update command
105         */
106        public String convert(List<OWLOntologyChange> changes) {
107                sb = new StringBuilder();
108
109                // sort by type of change
110                Collections.sort(changes, (o1, o2) -> ComparisonChain.start()
111                                .compareTrueFirst(o1.isAddAxiom(), o2.isAddAxiom())
112                                .compare(o1.getAxiom(), o2.getAxiom())
113                                .result());
114
115                // convert to SPARQL 1.1 Update
116                for (OWLOntologyChange change : changes) {
117                        sb.append(change instanceof RemoveAxiom ? "DELETE DATA"
118                                        : "INSERT DATA");
119                        sb.append("{");
120                        change.getAxiom().accept(this);
121                        sb.append("}");
122                        sb.append("\n");
123                }
124                return sb.toString();
125        }
126
127        @Override
128        protected void addTriple(@Nonnull RDFResource subject, @Nonnull RDFResourceIRI pred,
129                                                         @Nonnull RDFNode object) {
130                sb.append(subject).append(" ").append(pred).append(" ").append(object);
131
132        }
133
134        @Nonnull
135        @Override
136        protected RDFResourceBlankNode getAnonymousNode(@Nonnull Object key) {
137                return new RDFResourceBlankNode(System.identityHashCode(key), false,false, false);
138        }
139
140        @Nonnull
141        @Override
142        protected RDFResource getAnonymousNodeForExpressions(@Nonnull Object key, boolean isAxiom) {
143                checkNotNull(key, "key cannot be null");
144                return new RDFResourceBlankNode(false, false, isAxiom);
145        }
146
147        @Nonnull
148        @Override
149        protected RDFResourceIRI getPredicateNode(@Nonnull IRI iri) {
150                return new RDFResourceIRI(iri);
151        }
152
153        @Nonnull
154        @Override
155        protected RDFResource getResourceNode(@Nonnull IRI iri) {
156                return new RDFResourceIRI(iri);
157        }
158
159        @Nonnull
160        @Override
161        protected RDFLiteral getLiteralNode(@Nonnull OWLLiteral literal) {
162                return new RDFLiteral(literal);
163        }
164}