/* * This file is part of the OWL API. * * The contents of this file are subject to the LGPL License, Version 3.0. * * Copyright (C) 2011, The University of Queensland * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. If * not, see http://www.gnu.org/licenses/. * * * Alternatively, the contents of this file may be used under the terms of the Apache License, * Version 2.0 in which case, the provisions of the Apache License Version 2.0 are applicable * instead of those above. * * Copyright 2011, The University of Queensland * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.semanticweb.owlapi.rio; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; import org.eclipse.rdf4j.OpenRDFUtil; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.rio.RDFHandler; import org.eclipse.rdf4j.rio.RDFHandlerException; import org.semanticweb.owlapi.io.RDFResource; import org.semanticweb.owlapi.io.RDFTriple; import org.semanticweb.owlapi.model.OWLAnnotationProperty; import org.semanticweb.owlapi.model.OWLClass; import org.semanticweb.owlapi.model.OWLDataProperty; import org.semanticweb.owlapi.model.OWLDatatype; import org.semanticweb.owlapi.model.OWLNamedIndividual; import org.semanticweb.owlapi.model.OWLObjectProperty; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLRuntimeException; import org.semanticweb.owlapi.model.PrefixManager; import org.semanticweb.owlapi.rdf.RDFRendererBase; import org.semanticweb.owlapi.rio.utils.RioUtils; import org.semanticweb.owlapi.util.VersionInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Peter Ansell p_ansell@yahoo.com * @since 4.0.0 */ public class RioRenderer extends RDFRendererBase { private static final Logger LOGGER = LoggerFactory.getLogger(RioRenderer.class); private final RDFHandler writer; private final PrefixManager pm; private final Set<RDFTriple> renderedStatements = new LinkedHashSet<>(); private final Resource[] contexts; /** * @param ontology ontology * @param writer writer * @param contexts contexts */ public RioRenderer(final OWLOntology ontology, final RDFHandler writer, final Resource... contexts) { super(ontology, ontology.getOWLOntologyManager().getOntologyConfigurator()); OpenRDFUtil.verifyContextNotNull(contexts); this.contexts = contexts; this.writer = writer; // XXX maybe use the ontology prefix manager pm = ontology.getPrefixManager(); if (!ontology.isAnonymous()) { String ontologyIRIString = ontology.getOntologyID().getOntologyIRI().get().toString(); String defaultPrefix = ontologyIRIString; if (!ontologyIRIString.endsWith("/")) { defaultPrefix = ontologyIRIString + '#'; } pm.withDefaultPrefix(defaultPrefix); } } @Override protected void beginDocument() { pending.clear(); renderedStatements.clear(); try { writer.startRDF(); } catch (RDFHandlerException e) { throw new OWLRuntimeException(e); } // Namespaces writeNamespaces(); } @Override protected void endDocument() { writeComment(VersionInfo.getVersionInfo().getGeneratedByMessage()); try { writer.endRDF(); } catch (RDFHandlerException e) { throw new OWLRuntimeException(e); } if (LOGGER.isTraceEnabled()) { LOGGER.trace("pendingNodes={}", Integer.valueOf(pending.size())); LOGGER.trace("renderedStatements={}", Integer.valueOf(renderedStatements.size())); } pending.clear(); renderedStatements.clear(); } @Override protected void endObject() { writeComment(""); } @Override protected void writeAnnotationPropertyComment(OWLAnnotationProperty prop) { writeComment(prop.getIRI().toString()); } @Override protected void writeClassComment(final OWLClass cls) { writeComment(cls.getIRI().toString()); } @Override protected void writeDataPropertyComment(OWLDataProperty prop) { writeComment(prop.getIRI().toString()); } @Override protected void writeDatatypeComment(OWLDatatype datatype) { writeComment(datatype.getIRI().toString()); } @Override protected void writeIndividualComments(OWLNamedIndividual ind) { writeComment(ind.getIRI().toString()); } @Override protected void writeObjectPropertyComment(final OWLObjectProperty prop) { writeComment(prop.getIRI().toString()); } @Override protected void writeBanner(final String name) { writeComment(""); writeComment(""); writeComment("#################################################################"); writeComment("#"); writeComment("# " + name); writeComment("#"); writeComment("#################################################################"); writeComment(""); writeComment(""); } private void writeComment(final String comment) { try { writer.handleComment(comment); } catch (RDFHandlerException e) { throw new OWLRuntimeException(e); } } private void writeNamespaces() { // Send the prefixes from the prefixmanager to the RDFHandler // NOTE: These may be derived from a PrefixOWLDocumentFormat for (String prefixName : pm.getPrefixName2PrefixMap().keySet()) { final String prefix = pm.getPrefix(prefixName); // OWLAPI generally stores prefixes with a colon at the end, while // Sesame Rio expects // prefixes without the colon if (prefixName.endsWith(":")) { prefixName = prefixName.substring(0, prefixName.length() - 1); } try { writer.handleNamespace(prefixName, prefix); } catch (RDFHandlerException e) { throw new OWLRuntimeException(e); } } } @Override public void render(final RDFResource node, boolean root) { if (pending.contains(node)) { return; } pending.add(node); final Collection<RDFTriple> triples = getRDFGraph().getTriplesForSubject(node); if (LOGGER.isTraceEnabled()) { LOGGER.trace("triples.size()={}", Integer.valueOf(triples.size())); if (!triples.isEmpty()) { LOGGER.trace("triples={}", triples); } } for (final RDFTriple triple : triples) { RDFTriple tripleToRender = remapNodesIfNecessary(node, triple); try { if (!renderedStatements.contains(tripleToRender)) { renderedStatements.add(tripleToRender); // then we go back and get context-sensitive statements and // actually pass those to the RDFHandler for (Statement statement : RioUtils.tripleAsStatements(tripleToRender, contexts)) { writer.handleStatement(statement); if (tripleToRender.getObject() instanceof RDFResource) { render((RDFResource) tripleToRender.getObject(), false); } } } else if (LOGGER.isTraceEnabled()) { LOGGER.trace("not printing duplicate statement, or recursing on its object: {}", tripleToRender); } } catch (RDFHandlerException e) { throw new OWLRuntimeException(e); } } pending.remove(node); } }