/*
 * 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.converter.dlp;

import rbsla.owl.NameSpaceList;
import rbsla.owl.ProvaModel;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.impl.LiteralImpl;
import com.hp.hpl.jena.rdf.model.impl.ResourceImpl;

/**
 * Contains the methods for converting statements which contains user defined predicates
 * @version 0.1 <1 Feb 2005>
 * @since 0.1
 */
public class OWLStandardConverter {
	
	protected String Subject;
	protected String SubjectNameSpace;
	protected String SubjectLocalName;
	
	protected String Predicate;
	protected String PredicateNameSpace;
	protected String PredicateLocalName;
	
	protected String Object;
	protected String ObjectNameSpace;
	protected String ObjectLocalName;
	protected ResourceImpl RecourceImpl;
	protected boolean ObjectIsResourceImpl = false;
	protected boolean ObjectIsLiteralImpl = false;
	
	protected NameSpaceList NSL; 
	protected MapperList MapList;
	
	public OWLStandardConverter(NameSpaceList nsl) {NSL=nsl;}
	
	/**
	 * Converts the user defined statements in the form: predicate(subject, object).
	 * 
	 * @param _writer the ProvaModel
	 * @param _stmt the JENA statement
	 * @param _MapList the mapping list of Individuals
	 * @return ProvaModel
	 */
	public ProvaModel writeAllStatements(ProvaModel _writer, Statement _stmt, MapperList _MapList ){
	
		MapList = _MapList;		
		
		Statement stmt = _stmt;
		Resource res = stmt.getSubject();
		
		SubjectNameSpace = new String(stmt.getSubject().getNameSpace()); // subject namespace
		SubjectLocalName = new String(stmt.getSubject().getLocalName());
		Subject = NSL.getAbbreviation(SubjectNameSpace)+ SubjectLocalName; // subject
		
		PredicateNameSpace = new String(stmt.getPredicate().getNameSpace()); // predicate namespace
		PredicateLocalName = new String(stmt.getPredicate().getLocalName());
		Predicate = NSL.getAbbreviation(PredicateNameSpace) + PredicateLocalName; // predicate
	
		
		int Datatype = 0;
		
		if (stmt.getObject() instanceof ResourceImpl){ // resource
		
			ObjectIsResourceImpl = true;
			ObjectIsLiteralImpl = false;
			ResourceImpl resImpl = (ResourceImpl) stmt.getObject();
			
			Object = new String(NSL.getAbbreviation(resImpl.getNameSpace()) + resImpl.getLocalName());
			
		} else if(stmt.getObject() instanceof LiteralImpl){ // literal
			ObjectIsResourceImpl = false;
			ObjectIsLiteralImpl = true;
			LiteralImpl litImpl = (LiteralImpl) stmt.getObject();	
			/*
			 * Different Types of LiteralImpl have to be separated
			 * and mapped to Prova/Java types
			 * 
			 * 		0 = default Valus (handled as a string)
			 * 		1 = String
			 * 		2 = Integer
			 * 		3 = Float
			 */				
			if (litImpl.getDatatype() == null){
				Datatype = 0;
			}else{
				try {
					Datatype = this.getHashforDatatype(litImpl.getDatatype().getJavaClass().getName());
				} catch (Exception e) {
					if (litImpl.getDatatype().toString().indexOf("Integer")!=-1) Datatype = 2;
					// TODO: Other datatype conversions 
				}
			}
			Object = new String(litImpl.getString());
					
			
		}else{ // undefined Object --> convert to String
			ObjectIsResourceImpl = false;
			ObjectIsLiteralImpl = false;
			Object = stmt.getObject().toString();
		}
		
		
		
		if (MapList.isElementOfMapping(Subject) && MapList.isElementOfMapping(Object)){
			_writer.write(Predicate + "(X,Y) :- mapping(" +
					"\"" + MapList.getHashOfElement(Subject) + "\", X),"+
					"mapping(\"" + MapList.getHashOfElement(Object) + "\", Y)."
					+ "\r\n");
		} else if (MapList.isElementOfMapping(Subject) && (!MapList.isElementOfMapping(Object))){
			
			/**
			 * Conversions which depends on the datatype of the Object
			 */
			
			switch (Datatype){
				case 0: // Default value = String
					_writer.write(Predicate + "(X,\"" +	Object + "\") :- " +
							"mapping(\"" + MapList.getHashOfElement(Subject) + "\", X)."
							+ "\r\n");
					break;
				case 1: // String
					_writer.write(Predicate + "(X,\"" +	Object + "\") :- " +
							"mapping(\"" + MapList.getHashOfElement(Subject) + "\", X)."
							+ "\r\n");
					break;
				case 2: // Integer
					_writer.write(Predicate + "(X," +	Object + ") :- " +
							"mapping(\"" + MapList.getHashOfElement(Subject) + "\", X)."
							+ "\r\n");
					break;
				case 3: // Float
					_writer.write(Predicate + "(X," +	Object + ") :- " +
							"mapping(\"" + MapList.getHashOfElement(Subject) + "\", X)."
							+ "\r\n");
					break;
				default:
					_writer.write(Predicate + "(X,\"" +	Object + "\") :- " +
							"mapping(\"" + MapList.getHashOfElement(Subject) + "\", X)."
							+ "\r\n");
			}

		} else if ((!MapList.isElementOfMapping(Subject)) && MapList.isElementOfMapping(Object)){
			_writer.write(Predicate + "(" +
					"\"" + Subject + "\", X) :- " +
					"mapping(\""+MapList.getHashOfElement(Object) + "\",X)."
					+ "\r\n");
		} else {
			switch (Datatype){
			case 0:
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\",\"" +
						Object + "\")."
						+ "\r\n");
				break;
			case 1:
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\",\"" +
						Object + "\")."
						+ "\r\n");
				break;
			case 2:
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\"," +
						Object + ")."
						+ "\r\n");
				break;
			case 3:
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\"," +
						Object + ")."
						+ "\r\n");
				break;
			default:
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\",\"" +
						Object + "\")."
						+ "\r\n");
		}
		}
		

	return _writer;
	
}
	
	/**
	 * Converts the user defined statements in the form: predicate(subject, object).
	 * This method is called in the case of the appearence of reification keys-
	 * 
	 * @param _writer the ProvaModel
	 * @param _stmt the JENA statement
	 * @param _MapList the mapping list of Individuals
	 * @param isSubjectAnon indicates if the subject is a reification key
	 * @param isObjectAnon indicates if the object is a reification key
	 * @return ProvaModel
	 */
	public ProvaModel writeAllStatements(ProvaModel _writer,
										   Statement _stmt, 
										   MapperList _MapList,
										   boolean isSubjectAnon,
										   boolean isObjectAnon){
		
		MapList = _MapList;			
		Statement stmt = _stmt;
		Predicate = NSL.getAbbreviation(stmt.getPredicate().getNameSpace()) 
					+ stmt.getPredicate().getLocalName();	

		if (isSubjectAnon && isObjectAnon){
			// subject _anonX
			Subject = "_anon" + Integer.toString(
						MapList.getHashOfElement(
						stmt.getSubject().getId().toString()));	
			ResourceImpl resImpl = (ResourceImpl) stmt.getObject();
			// object _anonX
			Object = "_anon" + Integer.toString(
						MapList.getHashOfElement(
					    resImpl.getId().toString()));
			_writer.write(Predicate + "(" + "\"" +
						  Subject + "\",\"" + Object + "\")." + "\n");
		}else if (isSubjectAnon && (!isObjectAnon)){
			// subject _anonX
			Subject = "_anon" + Integer.toString(
					MapList.getHashOfElement(
							stmt.getSubject().getId().toString()));
			if (stmt.getObject() instanceof ResourceImpl){
				ResourceImpl resImpl = (ResourceImpl) stmt.getObject();	
				Object = new String(NSL.getAbbreviation(resImpl.getNameSpace()) + resImpl.getLocalName());
			}else if(stmt.getObject() instanceof LiteralImpl){
				LiteralImpl litImpl = (LiteralImpl) stmt.getObject();	
				Object = new String(litImpl.getString());	
			}else{
				Object = stmt.getObject().toString();
			}
			if (MapList.isElementOfMapping(Object)){
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\",X) :- mapping(\"" +
						MapList.getHashOfElement(Object) + "\",X)." + "\r\n");
			}else{
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\",\"" +
						Object + "\")." + "\n");
			}
		}else{
			Subject = NSL.getAbbreviation(stmt.getSubject().getNameSpace()) + stmt.getSubject().getLocalName();
			ResourceImpl resImpl = (ResourceImpl) stmt.getObject();
			// object anon
			Object = "_anon" + Integer.toString(
					MapList.getHashOfElement(
				    resImpl.getId().toString()));
			if (MapList.isElementOfMapping(Subject)){
				_writer.write(Predicate + "(X,\"" + Object +"\") :- mapping("+
						"\"" + MapList.getHashOfElement(Subject) + "\",X)." + "\r\n");
			}else{
				_writer.write(Predicate + "(" +
						"\"" + Subject + "\",\"" +
						Object + "\")." + "\n");
			}
		}
			
	return _writer;
	
	}
	
	
	
	/**
	 * @param Datatype the datatype name as a String
	 * @return Hash of Datatype
	 */
	protected int getHashforDatatype(String Datatype){
		if (Datatype.equals("java.lang.String")){
			return 1;
		}else if (Datatype.equals("java.lang.Integer")){
			return 2;
		}else if (Datatype.equals("java.lang.Float")){
			return 3;
		}else{
			return 0;
		}
	}
	
}
