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 org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntax;
022import org.semanticweb.owlapi.manchestersyntax.renderer.AbstractRenderer;
023import org.semanticweb.owlapi.model.*;
024import org.semanticweb.owlapi.util.CollectionFactory;
025import org.semanticweb.owlapi.util.ShortFormProvider;
026import org.semanticweb.owlapi.vocab.SWRLBuiltInsVocabulary;
027import org.semanticweb.owlapi.vocab.XSDVocabulary;
028
029import javax.annotation.Nonnull;
030import java.io.Writer;
031import java.util.Collection;
032import java.util.Iterator;
033import java.util.List;
034import java.util.Set;
035
036import static org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntax.*;
037import static org.semanticweb.owlapi.util.CollectionFactory.sortOptionally;
038
039/**
040 * @author Matthew Horridge, The University Of Manchester, Bio-Health
041 *         Informatics Group, Date: 25-Apr-2007
042 */
043public class ManchesterOWLSyntaxObjectRendererExt extends AbstractRenderer
044        implements OWLObjectVisitor {
045
046    /**
047     * @param writer
048     *        writer
049     * @param entityShortFormProvider
050     *        entityShortFormProvider
051     */
052    public ManchesterOWLSyntaxObjectRendererExt(Writer writer,
053            ShortFormProvider entityShortFormProvider) {
054        super(writer, entityShortFormProvider);
055    }
056
057    @Override
058    public void setUseTabbing(boolean useTabbing) {
059        super.setUseTabbing(useTabbing);
060    }
061
062    @Override
063    public boolean isUseTabbing() {
064        return super.isUseTabbing();
065    }
066
067    @Override
068    public void setUseWrapping(boolean useWrapping) {
069        super.setUseWrapping(useWrapping);
070    }
071
072    @Override
073    public boolean isUseWrapping() {
074        return super.isUseWrapping();
075    }
076
077    @Nonnull
078    protected static <T extends OWLObject> List<T> sort(
079            @Nonnull Collection<T> objects) {
080        return CollectionFactory.sortOptionally(objects);
081    }
082
083    protected void write(@Nonnull Set<? extends OWLObject> objects,
084                         @Nonnull ManchesterOWLSyntax delimeter, boolean newline) {
085        int tab = getIndent();
086        pushTab(tab);
087        for (Iterator<? extends OWLObject> it = sort(objects).iterator(); it
088                .hasNext();) {
089            it.next().accept(this);
090            if (it.hasNext()) {
091                if (newline && isUseWrapping()) {
092                    writeNewLine();
093                }
094                write(delimeter);
095            }
096        }
097        popTab();
098    }
099
100    protected void writeCommaSeparatedList(
101            @Nonnull Set<? extends OWLObject> objects) {
102        for (Iterator<? extends OWLObject> it = sort(objects).iterator(); it.hasNext();) {
103            it.next().accept(this);
104            if (it.hasNext()) {
105                write(", ");
106            }
107        }
108    }
109
110    protected void write(@Nonnull Set<? extends OWLClassExpression> objects,
111                         boolean newline) {
112        boolean first = true;
113        for (OWLClassExpression desc : sort(objects)) {
114            if (!first) {
115                if (newline && isUseWrapping()) {
116                    writeNewLine();
117                }
118                write(" ", AND, " ");
119            }
120            first = false;
121            if (desc instanceof OWLAnonymousClassExpression) {
122                write("(");
123            }
124            desc.accept(this);
125            if (desc instanceof OWLAnonymousClassExpression) {
126                write(")");
127            }
128        }
129    }
130
131    private void writeRestriction(
132            @Nonnull OWLQuantifiedDataRestriction restriction,
133            @Nonnull ManchesterOWLSyntax keyword) {
134        restriction.getProperty().accept(this);
135        write(keyword);
136        restriction.getFiller().accept(this);
137    }
138
139    private void writeRestriction(
140            @Nonnull OWLQuantifiedObjectRestriction restriction,
141            @Nonnull ManchesterOWLSyntax keyword) {
142        restriction.getProperty().accept(this);
143        write(keyword);
144        boolean conjunctionOrDisjunction = false;
145        if (restriction.getFiller() instanceof OWLAnonymousClassExpression) {
146            if (restriction.getFiller() instanceof OWLObjectIntersectionOf
147                    || restriction.getFiller() instanceof OWLObjectUnionOf) {
148                conjunctionOrDisjunction = true;
149                incrementTab(4);
150                if (isUseWrapping()) {
151                    writeNewLine();
152                }
153            }
154            write("(");
155        }
156        restriction.getFiller().accept(this);
157        if (restriction.getFiller() instanceof OWLAnonymousClassExpression) {
158            write(")");
159            if (conjunctionOrDisjunction) {
160                popTab();
161            }
162        }
163    }
164
165    private <V extends OWLObject> void writeRestriction(
166            @Nonnull OWLHasValueRestriction<V> restriction,
167            @Nonnull OWLPropertyExpression p) {
168        p.accept(this);
169        write(VALUE);
170        restriction.getFiller().accept(this);
171    }
172
173    private <F extends OWLPropertyRange> void writeRestriction(
174            @Nonnull OWLCardinalityRestriction<F> restriction,
175            @Nonnull ManchesterOWLSyntax keyword,
176            @Nonnull OWLPropertyExpression p) {
177        p.accept(this);
178        write(keyword);
179        write(Integer.toString(restriction.getCardinality()));
180        writeSpace();
181        if (restriction.getFiller() instanceof OWLAnonymousClassExpression) {
182            write("(");
183        }
184        restriction.getFiller().accept(this);
185        if (restriction.getFiller() instanceof OWLAnonymousClassExpression) {
186            write(")");
187        }
188    }
189
190    // Class expressions
191    @Override
192    public void visit(OWLClass ce) {
193        write(getShortFormProvider().getShortForm(ce));
194    }
195
196    @Override
197    public void visit(@Nonnull OWLObjectIntersectionOf ce) {
198        write(ce.getOperands(), true);
199    }
200
201    @Override
202    public void visit(@Nonnull OWLObjectUnionOf ce) {
203        boolean first = true;
204        for (OWLClassExpression op : sortOptionally(ce.getOperands())) {
205            if (!first) {
206                write(" ", OR, " ");
207            }
208            first = false;
209            if (op.isAnonymous()) {
210                write("(");
211            }
212            op.accept(this);
213            if (op.isAnonymous()) {
214                write(")");
215            }
216        }
217    }
218
219    @Override
220    public void visit(@Nonnull OWLObjectComplementOf ce) {
221        write("", NOT, ce.isAnonymous() ? " " : "");
222        if (ce.isAnonymous()) {
223            write("(");
224        }
225        ce.getOperand().accept(this);
226        if (ce.isAnonymous()) {
227            write(")");
228        }
229    }
230
231    @Override
232    public void visit(OWLObjectSomeValuesFrom ce) {
233        writeRestriction(ce, SOME);
234    }
235
236    @Override
237    public void visit(OWLObjectAllValuesFrom ce) {
238        writeRestriction(ce, ONLY);
239    }
240
241    @Override
242    public void visit(@Nonnull OWLObjectHasValue ce) {
243        writeRestriction(ce, ce.getProperty());
244    }
245
246    @Override
247    public void visit(@Nonnull OWLObjectMinCardinality ce) {
248        writeRestriction(ce, MIN, ce.getProperty());
249    }
250
251    @Override
252    public void visit(@Nonnull OWLObjectExactCardinality ce) {
253        writeRestriction(ce, EXACTLY, ce.getProperty());
254    }
255
256    @Override
257    public void visit(@Nonnull OWLObjectMaxCardinality ce) {
258        writeRestriction(ce, MAX, ce.getProperty());
259    }
260
261    @Override
262    public void visit(@Nonnull OWLObjectHasSelf ce) {
263        ce.getProperty().accept(this);
264        write(SOME);
265        write(SELF);
266    }
267
268    @Override
269    public void visit(@Nonnull OWLObjectOneOf ce) {
270        write("{");
271        write(ce.getIndividuals(), ONE_OF_DELIMETER, false);
272        write("}");
273    }
274
275    @Override
276    public void visit(OWLDataSomeValuesFrom ce) {
277        writeRestriction(ce, SOME);
278    }
279
280    @Override
281    public void visit(OWLDataAllValuesFrom ce) {
282        writeRestriction(ce, ONLY);
283    }
284
285    @Override
286    public void visit(@Nonnull OWLDataHasValue ce) {
287        writeRestriction(ce, ce.getProperty());
288    }
289
290    @Override
291    public void visit(@Nonnull OWLDataMinCardinality ce) {
292        writeRestriction(ce, MIN, ce.getProperty());
293    }
294
295    @Override
296    public void visit(@Nonnull OWLDataExactCardinality ce) {
297        writeRestriction(ce, EXACTLY, ce.getProperty());
298    }
299
300    @Override
301    public void visit(@Nonnull OWLDataMaxCardinality ce) {
302        writeRestriction(ce, MAX, ce.getProperty());
303    }
304
305    // Entities stuff
306    @Override
307    public void visit(OWLObjectProperty property) {
308        write(getShortFormProvider().getShortForm(property));
309    }
310
311    @Override
312    public void visit(OWLDataProperty property) {
313        write(getShortFormProvider().getShortForm(property));
314    }
315
316    @Override
317    public void visit(OWLNamedIndividual individual) {
318        write(getShortFormProvider().getShortForm(individual));
319    }
320
321    @Override
322    public void visit(OWLAnnotationProperty property) {
323        write(getShortFormProvider().getShortForm(property));
324    }
325
326    @Override
327    public void visit(OWLDatatype node) {
328        write(getShortFormProvider().getShortForm(node));
329    }
330
331    @Override
332    public void visit(@Nonnull OWLAnonymousIndividual individual) {
333        write(individual.toStringID());
334    }
335
336    @Override
337    public void visit(@Nonnull IRI iri) {
338        write(iri.toQuotedString());
339    }
340
341    @Override
342    public void visit(@Nonnull OWLAnnotation node) {
343        writeAnnotations(node.getAnnotations());
344        node.getProperty().accept(this);
345        writeSpace();
346        node.getValue().accept(this);
347    }
348
349    // Data stuff
350    @Override
351    public void visit(@Nonnull OWLDataComplementOf node) {
352        write(NOT);
353        if (node.getDataRange().isDatatype()) {
354            node.getDataRange().accept(this);
355        } else {
356            write("(");
357            node.getDataRange().accept(this);
358            write(")");
359        }
360    }
361
362    @Override
363    public void visit(@Nonnull OWLDataOneOf node) {
364        write("{");
365        write(node.getValues(), ONE_OF_DELIMETER, false);
366        write("}");
367    }
368
369    @Override
370    public void visit(@Nonnull OWLDataIntersectionOf node) {
371        write("(");
372        write(node.getOperands(), AND, false);
373        write(")");
374    }
375
376    @Override
377    public void visit(@Nonnull OWLDataUnionOf node) {
378        write("(");
379        write(node.getOperands(), OR, false);
380        write(")");
381    }
382
383    @Override
384    public void visit(@Nonnull OWLDatatypeRestriction node) {
385        node.getDatatype().accept(this);
386        write("[");
387        write(node.getFacetRestrictions(), FACET_RESTRICTION_SEPARATOR, false);
388        write("]");
389    }
390
391    @Override
392    public void visit(@Nonnull OWLLiteral node) {
393        // xsd:decimal is the default datatype for literal forms like "33.3"
394        // with no specified datatype
395        if (XSDVocabulary.DECIMAL.getIRI().equals(node.getDatatype().getIRI())) {
396            write(node.getLiteral());
397        } else if (node.getDatatype().isFloat()) {
398            write(node.getLiteral());
399            write("f");
400        } else if (node.getDatatype().isInteger()) {
401            write(node.getLiteral());
402        } else if (node.getDatatype().isBoolean()) {
403            write(node.getLiteral());
404        } else {
405            pushTab(getIndent());
406            writeLiteral(node.getLiteral());
407            if (node.hasLang()) {
408                write("@");
409                write(node.getLang());
410            } else if (!node.isRDFPlainLiteral()) {
411                write("^^");
412                node.getDatatype().accept(this);
413            }
414            popTab();
415        }
416    }
417
418    private void writeLiteral(@Nonnull String literal) {
419        write("\"");
420        for (int i = 0; i < literal.length(); i++) {
421            char ch = literal.charAt(i);
422            if (ch == '"') {
423                write('\\');
424            } else if (ch == '\\') {
425                write('\\');
426            }
427            write(ch);
428        }
429        write("\"");
430    }
431
432    @Override
433    public void visit(@Nonnull OWLFacetRestriction node) {
434        write(node.getFacet().getSymbolicForm());
435        writeSpace();
436        node.getFacetValue().accept(this);
437    }
438
439    // Property expression stuff
440    @Override
441    public void visit(@Nonnull OWLObjectInverseOf property) {
442        write(INVERSE);
443        write("(");
444        property.getInverse().accept(this);
445        write(")");
446    }
447
448    // Annotation stuff
449    // Stand alone axiom representation
450    // We render each axiom as a one line frame
451    private boolean wrapSave;
452    private boolean tabSave;
453
454    private void setAxiomWriting() {
455        wrapSave = isUseWrapping();
456        tabSave = isUseTabbing();
457        setUseWrapping(false);
458        setUseTabbing(false);
459    }
460
461    private void restore() {
462        setUseTabbing(tabSave);
463        setUseWrapping(wrapSave);
464    }
465
466    @Override
467    public void visit(@Nonnull OWLSubClassOfAxiom axiom) {
468        setAxiomWriting();
469        axiom.getSubClass().accept(this);
470        write(SUBCLASS_OF);
471        axiom.getSuperClass().accept(this);
472        restore();
473    }
474
475    @Override
476    public void visit(@Nonnull OWLNegativeObjectPropertyAssertionAxiom axiom) {
477        setAxiomWriting();
478        write(NOT);
479        write("(");
480        axiom.getSubject().accept(this);
481        write(" ");
482        axiom.getProperty().accept(this);
483        write(" ");
484        axiom.getObject().accept(this);
485        write(")");
486        restore();
487    }
488
489    @Override
490    public void visit(@Nonnull OWLAsymmetricObjectPropertyAxiom axiom) {
491        setAxiomWriting();
492        writeSectionKeyword(ASYMMETRIC);
493        axiom.getProperty().accept(this);
494        restore();
495    }
496
497    @Override
498    public void visit(@Nonnull OWLReflexiveObjectPropertyAxiom axiom) {
499        setAxiomWriting();
500        writeSectionKeyword(REFLEXIVE);
501        axiom.getProperty().accept(this);
502        restore();
503    }
504
505    private void writeBinaryOrNaryList(
506            @Nonnull ManchesterOWLSyntax binaryKeyword,
507            @Nonnull Set<? extends OWLObject> objects,
508            @Nonnull ManchesterOWLSyntax naryKeyword) {
509        if (objects.size() == 2) {
510            Iterator<? extends OWLObject> it = sort(objects).iterator();
511            it.next().accept(this);
512            write(binaryKeyword);
513            it.next().accept(this);
514        } else {
515            writeSectionKeyword(naryKeyword);
516            writeCommaSeparatedList(objects);
517        }
518    }
519
520    @Override
521    public void visit(@Nonnull OWLDisjointClassesAxiom axiom) {
522        setAxiomWriting();
523        writeBinaryOrNaryList(DISJOINT_WITH, axiom.getClassExpressions(),
524                DISJOINT_CLASSES);
525        restore();
526    }
527
528    @Override
529    public void visit(@Nonnull OWLDataPropertyDomainAxiom axiom) {
530        setAxiomWriting();
531        axiom.getProperty().accept(this);
532        write(DOMAIN);
533        axiom.getDomain().accept(this);
534        restore();
535    }
536
537    @Override
538    public void visit(@Nonnull OWLObjectPropertyDomainAxiom axiom) {
539        setAxiomWriting();
540        axiom.getProperty().accept(this);
541        write(DOMAIN);
542        axiom.getDomain().accept(this);
543        restore();
544    }
545
546    @Override
547    public void visit(@Nonnull OWLEquivalentObjectPropertiesAxiom axiom) {
548        setAxiomWriting();
549        writeBinaryOrNaryList(EQUIVALENT_TO, axiom.getProperties(),
550                EQUIVALENT_PROPERTIES);
551        restore();
552    }
553
554    @Override
555    public void visit(@Nonnull OWLNegativeDataPropertyAssertionAxiom axiom) {
556        setAxiomWriting();
557        write(NOT);
558        write("(");
559        axiom.getSubject().accept(this);
560        write(" ");
561        axiom.getProperty().accept(this);
562        write(" ");
563        axiom.getObject().accept(this);
564        write(")");
565        restore();
566    }
567
568    @Override
569    public void visit(@Nonnull OWLDifferentIndividualsAxiom axiom) {
570        setAxiomWriting();
571        writeBinaryOrNaryList(DIFFERENT_FROM, axiom.getIndividuals(),
572                DIFFERENT_INDIVIDUALS);
573        restore();
574    }
575
576    @Override
577    public void visit(@Nonnull OWLDisjointDataPropertiesAxiom axiom) {
578        setAxiomWriting();
579        writeBinaryOrNaryList(DISJOINT_WITH, axiom.getProperties(),
580                DISJOINT_PROPERTIES);
581        restore();
582    }
583
584    @Override
585    public void visit(@Nonnull OWLDisjointObjectPropertiesAxiom axiom) {
586        setAxiomWriting();
587        writeBinaryOrNaryList(DISJOINT_WITH, axiom.getProperties(),
588                DISJOINT_PROPERTIES);
589        restore();
590    }
591
592    @Override
593    public void visit(@Nonnull OWLObjectPropertyRangeAxiom axiom) {
594        setAxiomWriting();
595        axiom.getProperty().accept(this);
596        write(RANGE);
597        axiom.getRange().accept(this);
598        restore();
599    }
600
601    @Override
602    public void visit(@Nonnull OWLObjectPropertyAssertionAxiom axiom) {
603        setAxiomWriting();
604        axiom.getSubject().accept(this);
605        write(" ");
606        axiom.getProperty().accept(this);
607        write(" ");
608        axiom.getObject().accept(this);
609        restore();
610    }
611
612    @Override
613    public void visit(@Nonnull OWLFunctionalObjectPropertyAxiom axiom) {
614        setAxiomWriting();
615        writeSectionKeyword(FUNCTIONAL);
616        axiom.getProperty().accept(this);
617        restore();
618    }
619
620    @Override
621    public void visit(@Nonnull OWLSubObjectPropertyOfAxiom axiom) {
622        setAxiomWriting();
623        axiom.getSubProperty().accept(this);
624        write(SUB_PROPERTY_OF);
625        axiom.getSuperProperty().accept(this);
626        restore();
627    }
628
629    @Override
630    public void visit(@Nonnull OWLDisjointUnionAxiom axiom) {
631        setAxiomWriting();
632        axiom.getOWLClass().accept(this);
633        write(DISJOINT_UNION_OF);
634        writeCommaSeparatedList(axiom.getClassExpressions());
635        restore();
636    }
637
638    private void writeFrameType(OWLObject object) {
639        setAxiomWriting();
640        if (object instanceof OWLOntology) {
641            writeFrameKeyword(ONTOLOGY);
642            OWLOntology ont = (OWLOntology) object;
643            if (!ont.isAnonymous()) {
644                write("<");
645                write(ont.getOntologyID().getOntologyIRI().get().toString());
646                write(">");
647            }
648        } else {
649            if (object instanceof OWLClassExpression) {
650                writeFrameKeyword(CLASS);
651            } else if (object instanceof OWLObjectPropertyExpression) {
652                writeFrameKeyword(OBJECT_PROPERTY);
653            } else if (object instanceof OWLDataPropertyExpression) {
654                writeFrameKeyword(DATA_PROPERTY);
655            } else if (object instanceof OWLIndividual) {
656                writeFrameKeyword(INDIVIDUAL);
657            } else if (object instanceof OWLAnnotationProperty) {
658                writeFrameKeyword(ANNOTATION_PROPERTY);
659            }
660        }
661        object.accept(this);
662    }
663
664    @Override
665    public void visit(@Nonnull OWLDeclarationAxiom axiom) {
666        setAxiomWriting();
667        writeFrameType(axiom.getEntity());
668        restore();
669    }
670
671    @Override
672    public void visit(@Nonnull OWLAnnotationAssertionAxiom axiom) {
673        setAxiomWriting();
674        axiom.getSubject().accept(this);
675        write(" ");
676        axiom.getAnnotation().accept(this);
677        restore();
678    }
679
680    @Override
681    public void visit(@Nonnull OWLAnnotationPropertyDomainAxiom axiom) {
682        setAxiomWriting();
683        axiom.getProperty().accept(this);
684        write(DOMAIN);
685        axiom.getDomain().accept(this);
686    }
687
688    @Override
689    public void visit(@Nonnull OWLAnnotationPropertyRangeAxiom axiom) {
690        setAxiomWriting();
691        axiom.getProperty().accept(this);
692        write(RANGE);
693        axiom.getRange().accept(this);
694    }
695
696    @Override
697    public void visit(@Nonnull OWLSubAnnotationPropertyOfAxiom axiom) {
698        setAxiomWriting();
699        axiom.getSubProperty().accept(this);
700        write(SUB_PROPERTY_OF);
701        axiom.getSuperProperty().accept(this);
702    }
703
704    @Override
705    public void visit(@Nonnull OWLSymmetricObjectPropertyAxiom axiom) {
706        setAxiomWriting();
707        writeSectionKeyword(SYMMETRIC);
708        axiom.getProperty().accept(this);
709        restore();
710    }
711
712    @Override
713    public void visit(@Nonnull OWLDataPropertyRangeAxiom axiom) {
714        setAxiomWriting();
715        axiom.getProperty().accept(this);
716        writeSectionKeyword(RANGE);
717        axiom.getRange().accept(this);
718        restore();
719    }
720
721    @Override
722    public void visit(@Nonnull OWLFunctionalDataPropertyAxiom axiom) {
723        setAxiomWriting();
724        writeSectionKeyword(FUNCTIONAL);
725        axiom.getProperty().accept(this);
726        restore();
727    }
728
729    @Override
730    public void visit(@Nonnull OWLEquivalentDataPropertiesAxiom axiom) {
731        setAxiomWriting();
732        writeFrameKeyword(EQUIVALENT_PROPERTIES);
733        writeCommaSeparatedList(axiom.getProperties());
734        restore();
735    }
736
737    @Override
738    public void visit(@Nonnull OWLClassAssertionAxiom axiom) {
739        setAxiomWriting();
740        axiom.getIndividual().accept(this);
741        write(TYPE);
742        axiom.getClassExpression().accept(this);
743        restore();
744    }
745
746    @Override
747    public void visit(@Nonnull OWLEquivalentClassesAxiom axiom) {
748        setAxiomWriting();
749        writeBinaryOrNaryList(EQUIVALENT_TO, axiom.getClassExpressions(),
750                EQUIVALENT_CLASSES);
751        restore();
752    }
753
754    @Override
755    public void visit(@Nonnull OWLDataPropertyAssertionAxiom axiom) {
756        setAxiomWriting();
757        axiom.getSubject().accept(this);
758        write(" ");
759        axiom.getProperty().accept(this);
760        write(" ");
761        axiom.getObject().accept(this);
762        restore();
763    }
764
765    @Override
766    public void visit(@Nonnull OWLTransitiveObjectPropertyAxiom axiom) {
767        setAxiomWriting();
768        writeSectionKeyword(TRANSITIVE);
769        axiom.getProperty().accept(this);
770        restore();
771    }
772
773    @Override
774    public void visit(@Nonnull OWLIrreflexiveObjectPropertyAxiom axiom) {
775        setAxiomWriting();
776        writeSectionKeyword(IRREFLEXIVE);
777        axiom.getProperty().accept(this);
778        restore();
779    }
780
781    @Override
782    public void visit(@Nonnull OWLSubDataPropertyOfAxiom axiom) {
783        setAxiomWriting();
784        axiom.getSubProperty().accept(this);
785        writeSectionKeyword(SUB_PROPERTY_OF);
786        axiom.getSuperProperty().accept(this);
787        restore();
788    }
789
790    @Override
791    public void visit(@Nonnull OWLInverseFunctionalObjectPropertyAxiom axiom) {
792        setAxiomWriting();
793        writeSectionKeyword(INVERSE_FUNCTIONAL);
794        axiom.getProperty().accept(this);
795        restore();
796    }
797
798    @Override
799    public void visit(@Nonnull OWLSameIndividualAxiom axiom) {
800        setAxiomWriting();
801        writeBinaryOrNaryList(SAME_AS, axiom.getIndividuals(), SAME_INDIVIDUAL);
802        restore();
803    }
804
805    @Override
806    public void visit(@Nonnull OWLSubPropertyChainOfAxiom axiom) {
807        setAxiomWriting();
808        for (Iterator<OWLObjectPropertyExpression> it = axiom
809                .getPropertyChain().iterator(); it.hasNext();) {
810            it.next().accept(this);
811            if (it.hasNext()) {
812                write(" o ");
813            }
814        }
815        write(SUB_PROPERTY_OF);
816        axiom.getSuperProperty().accept(this);
817        restore();
818    }
819
820    @Override
821    public void visit(@Nonnull OWLInverseObjectPropertiesAxiom axiom) {
822        setAxiomWriting();
823        axiom.getFirstProperty().accept(this);
824        write(INVERSE_OF);
825        axiom.getSecondProperty().accept(this);
826        restore();
827    }
828
829    @Override
830    public void visit(@Nonnull SWRLRule rule) {
831        setAxiomWriting();
832        for (Iterator<SWRLAtom> it = rule.getBody().iterator(); it.hasNext();) {
833            it.next().accept(this);
834            if (it.hasNext()) {
835                write(", ");
836            }
837        }
838        write(" -> ");
839        for (Iterator<SWRLAtom> it = rule.getHead().iterator(); it.hasNext();) {
840            it.next().accept(this);
841            if (it.hasNext()) {
842                write(", ");
843            }
844        }
845        restore();
846    }
847
848    @Override
849    public void visit(@Nonnull OWLHasKeyAxiom axiom) {
850        setAxiomWriting();
851        axiom.getClassExpression().accept(this);
852        write(HAS_KEY);
853        write(axiom.getObjectPropertyExpressions(), COMMA, false);
854        write(axiom.getDataPropertyExpressions(), COMMA, false);
855    }
856
857    // SWRL
858    @Override
859    public void visit(@Nonnull SWRLClassAtom node) {
860        if (node.getPredicate().isAnonymous()) {
861            write("(");
862        }
863        node.getPredicate().accept(this);
864        if (node.getPredicate().isAnonymous()) {
865            write(")");
866        }
867        write("(");
868        node.getArgument().accept(this);
869        write(")");
870    }
871
872    @Override
873    public void visit(@Nonnull SWRLDataRangeAtom node) {
874        node.getPredicate().accept(this);
875        write("(");
876        node.getArgument().accept(this);
877        write(")");
878    }
879
880    @Override
881    public void visit(@Nonnull SWRLObjectPropertyAtom node) {
882        node.getPredicate().accept(this);
883        write("(");
884        node.getFirstArgument().accept(this);
885        write(", ");
886        node.getSecondArgument().accept(this);
887        write(")");
888    }
889
890    @Override
891    public void visit(@Nonnull SWRLDataPropertyAtom node) {
892        node.getPredicate().accept(this);
893        write("(");
894        node.getFirstArgument().accept(this);
895        write(", ");
896        node.getSecondArgument().accept(this);
897        write(")");
898    }
899
900    @Override
901    public void visit(@Nonnull SWRLBuiltInAtom node) {
902        SWRLBuiltInsVocabulary voc = SWRLBuiltInsVocabulary.getBuiltIn(node
903                .getPredicate());
904        if (voc != null) {
905            write(voc.getPrefixedName());
906        } else {
907            write(node.getPredicate().toQuotedString());
908        }
909        write("(");
910        for (Iterator<SWRLDArgument> it = sort(node.getArguments()).iterator(); it
911                .hasNext();) {
912            it.next().accept(this);
913            if (it.hasNext()) {
914                write(", ");
915            }
916        }
917        write(")");
918    }
919
920    @Override
921    public void visit(@Nonnull SWRLVariable node) {
922        write("?");
923        // do not save the namespace if it's the conventional one
924        if ("urn:swrl#".equals(node.getIRI().getNamespace())) {
925            write(node.getIRI().prefixedBy(""));
926        } else {
927            write(node.getIRI().toQuotedString());
928        }
929    }
930
931    @Override
932    public void visit(@Nonnull SWRLIndividualArgument node) {
933        node.getIndividual().accept(this);
934    }
935
936    @Override
937    public void visit(@Nonnull SWRLLiteralArgument node) {
938        node.getLiteral().accept(this);
939    }
940
941    @Override
942    public void visit(@Nonnull SWRLSameIndividualAtom node) {
943        write(SAME_AS);
944        write("(");
945        node.getFirstArgument().accept(this);
946        write(", ");
947        node.getSecondArgument().accept(this);
948        write(")");
949    }
950
951    @Override
952    public void visit(@Nonnull SWRLDifferentIndividualsAtom node) {
953        write(DIFFERENT_FROM);
954        write("(");
955        node.getFirstArgument().accept(this);
956        write(", ");
957        node.getSecondArgument().accept(this);
958        write(")");
959    }
960
961    @Override
962    public void visit(OWLDatatypeDefinitionAxiom axiom) {}
963
964    protected void writeAnnotations(@Nonnull Set<OWLAnnotation> annos) {
965        if (annos.isEmpty()) {
966            return;
967        }
968        writeNewLine();
969        write(ANNOTATIONS.toString());
970        write(": ");
971        pushTab(getIndent());
972        for (Iterator<OWLAnnotation> annoIt = sort(annos).iterator(); annoIt
973                .hasNext();) {
974            OWLAnnotation anno = annoIt.next();
975            anno.accept(this);
976            if (annoIt.hasNext()) {
977                write(", ");
978                writeNewLine();
979            }
980        }
981        writeNewLine();
982        writeNewLine();
983        popTab();
984    }
985
986    // Ontology
987    @Override
988    public void visit(OWLOntology ontology) {}
989}