/*
 * Copyright 2020 ETSI
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package fr.mines_stetienne.ci.saref.managers.parsers;

import java.util.HashMap;
import java.util.Map;

import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.semanticweb.owlapi.formats.RDFDocumentFormat;
import org.semanticweb.owlapi.io.AbstractOWLParser;
import org.semanticweb.owlapi.io.OWLOntologyDocumentSource;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.NodeID;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyLoaderConfiguration;
import org.semanticweb.owlapi.rdf.turtle.parser.OWLRDFConsumerAdapter;

import fr.mines_stetienne.ci.saref.SAREFPipeline;

public abstract class AbstractJenaModelOntologyParser extends AbstractOWLParser {

	private Map<String, IRI> string2IRI = new HashMap<String, IRI>();
	protected final SAREFPipeline pipeline;
	
	public AbstractJenaModelOntologyParser(SAREFPipeline pipeline) {
		this.pipeline = pipeline;		
	}
	
	protected RDFDocumentFormat parse(OWLOntologyDocumentSource source, OWLOntology ontology,
			OWLOntologyLoaderConfiguration config, Model model) {

		RDFDocumentFormat format = new JenaModelFormat();

		OWLRDFConsumerAdapter consumer = new OWLRDFConsumerAdapter(ontology, config);
		consumer.setOntologyFormat(format);
		consumer.startModel(source.getDocumentIRI());
		model.getNsPrefixMap().forEach((s, l) -> {
			consumer.handlePrefixDirective(s, l);
		});
		model.listStatements().forEachRemaining(stmt -> {
			Resource s = stmt.getSubject();
			Property p = stmt.getPredicate();
			RDFNode o = stmt.getObject();

			IRI s2 = getIRI(s);
			IRI p2 = getIRI(p);
			if (o.isResource()) {
				IRI o2 = getIRI(o.asResource());
				try {
					consumer.handleTriple(s2, p2, o2);
				} catch(Exception ex) {
					pipeline.getLogger("OWL Parser Error").warn(ex.getMessage());
				}
			} else {
				Literal l = o.asLiteral();
				String object = l.getLexicalForm();
				String dt = l.getDatatypeURI();
				String language = l.getLanguage();
				if (language != null && !language.isEmpty()) {
					consumer.handleTriple(s2, p2, object, language);
				} else if (dt != null) {
					IRI dt2 = IRI.create(dt);
					consumer.handleTriple(s2, p2, object, dt2);
				} else {
					consumer.handleTriple(s2, p2, object);
				}
			}
		});
		consumer.handleEnd();

		return format;
	}
	
	protected IRI getIRI(Resource s) {
		if (s.isAnon()) {
			return getBlankNode(s.getId().getLabelString());
		} else {
			return IRI.create(s.getURI());
		}
	}

	/**
	 * Gets the next blank node.
	 * 
	 * @param id the id
	 * @return the next blank node
	 */
	protected IRI getBlankNode(String id) {
		IRI iri = string2IRI.get(id);
		if (iri == null) {
			String string = NodeID.nextAnonymousIRI();
			iri = IRI.create(string);
			string2IRI.put(id, iri);
		}
		return iri;
	}

}
