/*
 * Copyright (C) 1999-2006 <a href="mailto:paschke@in.tum.de">Adrian Paschke</a>
 * 
 * The OWL2Prova library is part of the Rule Based Service Level Agreement (RBSLA)
 * framework, available at 
 * <a href=" http://ibis.in.tum.de/staff/paschke/rbsla/index.htm">RBSLA</a>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package rbsla.owl;


import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.rdf.model.Model;
import rbsla.owl.converter.dlp.*;

/**
 * <p>Decsription Logic Program converter.</p>
 * <p>The DLPConverter converts a RDF/RDFS/OWL model into a description logic program.
 * The converter supports three predefined conversion modes:</p>
 * <ul>
 * <li>	"lite" = translation into a normal DLP, no equivalent individuals (owl:sameAs) and anons
 * <li>	"standard" = translation into a extended DLP with equivalent individuals
 * <li>	"full" = translation into a completey inferred DLP (to be used onyl in combination with OWL reasoner)
 * </ul> 
 * @author <A HREF="mailto:paschke@in.tum.de">Adrian Paschke</A>
 * @version 0.1 <1 Feb 2005>
 * @since 0.1
 */
public class DLPConverter implements Converter {
	
	
	private ProvaModel provaModel;
	private MapperList mapList;
	private IndividualList classList;
	private IndividualList groupList;
	
	private boolean instanceMapping; // instance mapping on/off
	private boolean classMapping; // class mapping on/off
	private boolean anonMapping; // anon mapping on/off
		
	
	/**
	 * Constructor.
	 * DLP standard (with instance mapping)
	 */
	public DLPConverter() {
		provaModel = new ProvaModel();
		instanceMapping=true;
		classMapping=false;
		anonMapping=true;
	}
	
	/**
	 * Constructor.
	 * This is the standard constructor which should be used to set the DLP translation mode.
	 * @param name: 
	 * <ul><li>"full" = maps equivalent classes and individuals (to be used with OWL reasoner)
	 * <li>"standard" = maps equivalent instances and treats equivalence loops in SLDNF (negation as finite failure) resolution
	 * <li>"lite" = pure DLP conversion (leads to loops in SLDNF for equivalent classes, properties, can be interpreted with other semantics e.g. well-founded)</ul>
	 */
	public DLPConverter(String name) {
		if (name.toLowerCase().equals("lite")) {
			anonMapping=true;
			instanceMapping=false;
			classMapping=false;
		}
		else if ((name.toLowerCase().equals("standard")) || (name.toLowerCase().equals("default")) ) {
			anonMapping=true;
			instanceMapping=true;
			classMapping=false;
		} else if (name.toLowerCase().equals("full")) {
			anonMapping=true;
			instanceMapping=true;
			classMapping=true;
		}
		provaModel = new ProvaModel();
	}
	
	/**
	 * Translate the model.
	 * @param model the input model.
	 * @return ProvaModel the output model.
	 */
	public ProvaModel translate(Model model) {
		Model jenaModel = model;
	
		NameSpaceList nsl = new NameSpaceList(jenaModel); 
				
				
		/*
		 * Mapping of the OWL instances, anons to Identifiers (IDs) and class equivalence
		 */
		IdentifyMapper identMapper = new IdentifyMapper();
		identMapper.setInstanceMapping(instanceMapping);
		identMapper.setClassMapping(classMapping);
		identMapper.setAnonMapping(anonMapping);
		
		provaModel = identMapper.run(jenaModel, provaModel); 		
		
		/*
		 * The lists which are created by the IdentifyMapper. The map list contains the mapped Individuals and is needed
		 * for the further translation process. ClassList and groupList are needed 
		 * for update purposes.
		 */
		mapList = identMapper.getMapList();		// List of mapped equivalent instances and anons to IDs
		classList = identMapper.getClassList(); // List of classes
		groupList = identMapper.getGroupList(); // List of grouped equivalent classes
		
		/*
		 * Translation to Horn clauses
		 */
		for (StmtIterator it = jenaModel.listStatements(); it.hasNext();){
			OwlPredicateChooser opc;
			if (classMapping) opc = new OwlPredicateChooser(mapList, nsl, "full"); // full mapping
			else if (instanceMapping) opc = new OwlPredicateChooser(mapList, nsl, "standard"); // standard mapping
			else opc = new OwlPredicateChooser(mapList, nsl, "lite"); // lite DLP mapping
			Statement stmt = it.nextStatement();
			provaModel = opc.convertStatement(stmt, provaModel);			
		}
		
		return provaModel;
	}
	
	/**
	 * Update model.
	 * @param model the input model.
	 * @retrun ProvaModel the output model.
	 */
	public ProvaModel update (Model model) {
		Model jenaModel = model;
		
		provaModel.write("%------------------------ add update information:----------------------------" + "\n");
		
		NameSpaceList nsl = new NameSpaceList(jenaModel);
		
		/**
		 * Mapping of the OWL Instances to Identifier
		 */
		
		UpdateIdentifyMapper UpdateIdentMapper = new UpdateIdentifyMapper();
		UpdateIdentMapper.setInstanceMapping(instanceMapping);
		UpdateIdentMapper.setClassMapping(classMapping);
		UpdateIdentMapper.setAnonMapping(anonMapping);
		
		provaModel = UpdateIdentMapper.run(jenaModel, mapList, provaModel, classList, groupList);
		mapList = UpdateIdentMapper.getMapList();
		classList = UpdateIdentMapper.getClassList();
		groupList = UpdateIdentMapper.getGroupList();
		
		/**
		 * Translation to Horn clauses
		 */
		
		for (StmtIterator iter = jenaModel.listStatements(); iter.hasNext();){
			OwlPredicateChooser opc;
			if (classMapping) opc = new OwlPredicateChooser(mapList, nsl, "full"); // full mapping
			else if (instanceMapping) opc = new OwlPredicateChooser(mapList, nsl, "standard"); // standard mapping
			else opc = new OwlPredicateChooser(mapList, nsl, "lite"); // lite DLP mapping
			Statement stmt = iter.nextStatement();
			provaModel = opc.convertStatement(stmt, provaModel);
		}
		
		return provaModel;
	}

}
