/*******************************************************************************
 * Copyright 2012 by the Department of Computer Science (University of Oxford)
 * 
 *    This file is part of LogMap.
 * 
 *    LogMap 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 3 of the License, or
 *    (at your option) any later version.
 * 
 *    LogMap 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 LogMap.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package uk.ac.ox.krr.logmap2.web_service;

import java.util.Calendar;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Map;

import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLDataFactory;
//import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.AddImport;

import uk.ac.ox.krr.logmap2.Parameters;
import uk.ac.ox.krr.logmap2.io.OutPutFilesManager;
import uk.ac.ox.krr.logmap2.io.WriteFile;
import uk.ac.ox.krr.logmap2.io.LogOutput;
import uk.ac.ox.krr.logmap2.repair.*;
import uk.ac.ox.krr.logmap2.statistics.StatisticsManager;
import uk.ac.ox.krr.logmap2.overlapping.*;
import uk.ac.ox.krr.logmap2.owlapi.SynchronizedOWLManager;
import uk.ac.ox.krr.logmap2.utilities.PrecomputeIndexCombination;
import uk.ac.ox.krr.logmap2.lexicon.LexicalUtilities;
import uk.ac.ox.krr.logmap2.utilities.Utilities;

import uk.ac.ox.krr.logmap2.indexing.*;
import uk.ac.ox.krr.logmap2.interactive.*;

import uk.ac.ox.krr.logmap2.mappings.MappingManager;
import uk.ac.ox.krr.logmap2.mappings.CandidateMappingManager;

//import uk.ac.ox.krr.logmap2.io.LogOutput;





/**
 * This class will be invoked from LogMap's web facility 
 * @author ernesto
 *
 */
public class LogMap_WebService {
	
	private OverlappingExtractor overlappingExtractor;
	
	private IndexManager index;
	
	private OntologyProcessing onto_process1;
	private OntologyProcessing onto_process2;
	
	//private AnchorExtraction mapping_extractor;
	private MappingManager mapping_extractor;
	
	private AnchorAssessment mappings_assessment;
	
	private InteractiveProcess interactiveProcessManager;
	
	private long init_global, init, fin;
	
	private boolean cleanD_G=true;
	
	
	private HTMLResultsFileManager progress_manager;
	
	private String path_output; //for mappings and overlapping
	
	private String iri_output;

	//Input URIS
	private String iri1_str;
	private String iri2_str;
	
	private LexicalUtilities lexicalUtilities = new LexicalUtilities();
		
	
	/**
	 * 
	 * @param iri1_str
	 * @param iri2_str
	 * @param diagnosis
	 * @param path_output
	 * @param progress_manager
	 * @throws Exception
	 */
	public LogMap_WebService(
			String iri1_str, 
			String iri2_str,
			boolean diagnosis,
			String path_output,
			String iri_output,
			HTMLResultsFileManager progress_manager) throws OWLOntologyCreationException, Exception{
		
		
		//try {
			init_global = init = Calendar.getInstance().getTimeInMillis();
			
			this.iri1_str=iri1_str;
			this.iri2_str=iri2_str;
			
			this.cleanD_G = diagnosis;
			
			this.progress_manager = progress_manager;
			
			this.path_output = path_output;
			this.iri_output=iri_output;
			
			
			//INIT LOGMAP: lex and precomp integer combinations
			InitLogMap();		
			
			
			//Overlapping estimation
			OverlappingEstimation(iri1_str, iri2_str);
			updateHTMLProgress("Loading and overlapping...done");
			
	
			//Indexes lexicon (IF creation) and structure
			IndexLexiconAndStructure();
			
			
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Global Time Parsing and Index Lexicon (s): " + (float)((double)fin-(double)init_global)/1000.0);			
			updateHTMLProgress("Lexical indexing...done");
			
			
			//EXTRACT, CLEAN ANCHORS and INDEX INTLABELLING
			createAndCleanAnchors();			
			updateHTMLProgress("Extraction and diagnosis of reliable mappings...done");
			
			
			
			//Extract new candidates, clean them and index labelling
			createCandidateMappings();			
						
			//INTERACTIVE PROCESS
			//Also weakened in previous iterations
			createMappingsInteractiveProcess(false);
			updateHTMLProgress("Diagnosis of candidate mappings...done");
			
			
			
			
			init = Calendar.getInstance().getTimeInMillis();
			//TODO This should be integrated within te D&G repair
			mapping_extractor.createObjectPropertyAnchors();
			mapping_extractor.createDataPropertyAnchors();
			
			updateHTMLProgress("Extraction of property mappings...done");
			
			//Delete inverted files for properties
			onto_process1.clearInvertedFiles4properties();
			onto_process2.clearInvertedFiles4properties();
			
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Time creating property mappings (s): " + (float)((double)fin-(double)init)/1000.0);
			
			
			
			
			init = Calendar.getInstance().getTimeInMillis();
			//INDIVIDUALS
			if (Parameters.perform_instance_matching){
				createAndAssessInstanceMappings();
			}
			updateHTMLProgress("Extraction of instance mappings...done");
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Time creating instance mappings (s): " + (float)((double)fin-(double)init)/1000.0);
			
			
						
			
			updateHTMLProgress("Matching task finished. Storing output files...");
			
				
			//Mapping and module OUTPUT FILES
			try{
				saveExtractedMappings();
				saveOverlappingModules();
			} 
			catch (Exception e){
				System.out.println(e.getMessage());
				e.printStackTrace();
				throw new Exception();
			}
			
			
			index.clearTaxonomicalStructures();
			
			fin = Calendar.getInstance().getTimeInMillis();			
			writeInternalLog("TOTAL TIME (s): " + (float)((double)fin-(double)init_global)/1000.0);
			
			
			
		//}
		//catch (Exception e){
			//writeInternalLog("ERROR: " + e.getMessage());
			//writeInternalLog("ERROR: " + e.getLocalizedMessage());
		//}
		
	}
	
	
	
	private void updateHTMLProgress(String text_progress){
		progress_manager.updateProgress(text_progress);
	}
	
	
	
	private WriteFile internal_log;
	/**
	 * To keep logmap progress... internal use
	 */
	private void writeInternalLog(String text_log){
		
		//System.out.println(text_log);
		
		//We open/close it each time		
		internal_log = new WriteFile(path_output + "/logmap_internal_progress.log", true);
		
		internal_log.writeLine(text_log);
		
		internal_log.closeBuffer();
	}
	
	
	
	
	
	
	private void InitLogMap() throws Exception{
		
		//Show print outs (not used for the web facility)
		//We store instead a log
		LogOutput.showOutpuLog(true);
		
		lexicalUtilities.loadStopWords();
		//LexicalUtilities.loadStopWordsExtended();
		
		if (Parameters.use_umls_lexicon)
			lexicalUtilities.loadUMLSLexiconResources();
		
		lexicalUtilities.setStemmer(); //creates stemmer object (Paice by default)
		
		//Lib.debuginfo(LexicalUtilities.getStemming4Word("Prolactin") + " " + LexicalUtilities.getStemming4Word("brachii") + "\n");
		
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time initializing lexical utilities (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		//init = Calendar.getInstance().getTimeInMillis();
		//PrecomputeIndexCombination.preComputeIdentifierCombination();
		//fin = Calendar.getInstance().getTimeInMillis();
		//writeInternalLog("Time precomputing index combinations (s): " + (float)((double)fin-(double)init)/1000.0);
		
	}
	
	
	
	private void OverlappingEstimation(String iri1_str, String iri2_str) throws OWLOntologyCreationException, Exception{
		
		writeInternalLog("OVERLAPPING");
		init = Calendar.getInstance().getTimeInMillis();
	
		Parameters.setMinSize4Overlapping(5000);

		
		if (!Parameters.use_overlapping){
			overlappingExtractor = new NoOverlappingExtractor();
		}
		else{
			overlappingExtractor = new LexicalOverlappingExtractor(lexicalUtilities, true);
		}
		

		
		overlappingExtractor.createOverlapping(iri1_str, iri2_str);
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time extracting overlapping (s): " + (float)((double)fin-(double)init)/1000.0);
	}
	
	
	
	private void IndexLexiconAndStructure() throws Exception{
		 
		//Create Index and new Ontology Index...
		index = new JointIndexManager();
		

		updateHTMLProgress("Overlapping ontology 1: " + 
				overlappingExtractor.getOverlappingOnto1().getClassesInSignature(true).size() + " classes, " +
				(overlappingExtractor.getOverlappingOnto1().getDataPropertiesInSignature(true).size() +
				overlappingExtractor.getOverlappingOnto1().getObjectPropertiesInSignature(true).size()) + " properties, " +
				overlappingExtractor.getOverlappingOnto1().getIndividualsInSignature(true).size() + " individuals.");
		
		updateHTMLProgress("Overlapping ontology 2: " + 
				overlappingExtractor.getOverlappingOnto2().getClassesInSignature(true).size() + " classes, " +
				(overlappingExtractor.getOverlappingOnto2().getDataPropertiesInSignature(true).size() +
				overlappingExtractor.getOverlappingOnto2().getObjectPropertiesInSignature(true).size()) + " properties, " +
				overlappingExtractor.getOverlappingOnto2().getIndividualsInSignature(true).size() + " individuals.");
		
		//Process ontologies: lexicon and taxonomy (class) and IFs
		onto_process1 = new OntologyProcessing(overlappingExtractor.getOverlappingOnto1(), index, lexicalUtilities);
		onto_process2 = new OntologyProcessing(overlappingExtractor.getOverlappingOnto2(), index, lexicalUtilities);

		
		
		//Extracts lexicon
		init = Calendar.getInstance().getTimeInMillis();
		onto_process1.precessLexicon();
		onto_process2.precessLexicon();
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time extracting lexicon and IF (s): " + (float)((double)fin-(double)init)/1000.0);
		
		//I guess can be deleted here
		lexicalUtilities.clearStructures();
		
		
		init = Calendar.getInstance().getTimeInMillis();
		//Init Mapping extractor: intersects IF and extract IF weak
		//mapping_extractor = new LexicalMappingExtractor(index, onto_process1, onto_process2);
		mapping_extractor = new CandidateMappingManager(index, onto_process1, onto_process2);
		
		
		//Statistics (necessray to avoid error...)
		StatisticsManager.reInitValues();
		StatisticsManager.setMappingManager(mapping_extractor);
		
		
		
		mapping_extractor.intersectInvertedFiles();
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time intersecting IF and extracting IF weak (s): " + (float)((double)fin-(double)init)/1000.0);
		
		//Clear ontology stemmed labels 
		onto_process1.clearStemmedLabels();
		onto_process2.clearStemmedLabels();
		
		//Extracts Taxonomy
		//Also extracts A^B->C
		init = Calendar.getInstance().getTimeInMillis();
		onto_process1.setTaxonomicData();
		onto_process2.setTaxonomicData();
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time extracting structural information (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		
		//We do not need the references to OWLEntities anymore
		onto_process1.clearOntologyRelatedInfo();
		onto_process2.clearOntologyRelatedInfo();

		
		//We first create weak anchors to be used for scopes
		init = Calendar.getInstance().getTimeInMillis();
		mapping_extractor.extractAllWeakMappings();
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time creating all weak anchors (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		//Extract subsets from all weak mappings to evaluate later
		//----------------------------------------------------------
		init = Calendar.getInstance().getTimeInMillis();
		mapping_extractor.extractCandidatesSubsetFromWeakMappings();
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time creating candidate subset of weak anchors (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		//Remove structures used for frequency extractor
		
		//Frequency structures
		onto_process1.clearFrequencyRelatedStructures();
		onto_process2.clearFrequencyRelatedStructures();
		index.clearSingleWordInvertedIndex();
		
		//Only used by frequency-like weak mappings
		index.clearStemmedAlternativeLabels4Classes();
		
		
	}
	
	
	
	private void createAndCleanAnchors() throws Exception{
		
		writeInternalLog("\nANCHOR DIAGNOSIS ");
		
		init = Calendar.getInstance().getTimeInMillis();
		mapping_extractor.createAnchors();
		
		//Create different groups: "exact", ambiguity and no_scope (different sets...). We will add them later (almost done)
		
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time creating anchors (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		
		mappings_assessment = new AnchorAssessment(index, mapping_extractor);
				
		if (cleanD_G){		
			//TODO comment
			/*init = Calendar.getInstance().getTimeInMillis();
			mappings_assessment.CountSatisfiabilityOfIntegration_DandG(mapping_extractor.getAnchors());
			fin = Calendar.getInstance().getTimeInMillis();
			LogOutput.printAlways("Time checking satisfiability D&G (s): " + (float)((double)fin-(double)init)/1000.0);
			*/
			
			init = Calendar.getInstance().getTimeInMillis();
			mappings_assessment.CheckSatisfiabilityOfIntegration_DandG(mapping_extractor.getLogMapMappings());
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Time cleaning anchors D&G (s): " + (float)((double)fin-(double)init)/1000.0);
		}
		
		//After repairing exact
		mapping_extractor.setExactAsFixed(true);
		
		
		
		//TODO extract further disjointness based on weak anchors and mappings
		//TODO LATER....
		
		
		//INTERVAL LABELLING SCHEMA
		//--------------------------
		init = Calendar.getInstance().getTimeInMillis();
		
		//Index already have the necessary taxonomical information apart from the equiv mappings
		//TODO Extract ident2directkids with clean anchors
		index.setIntervalLabellingIndex(mapping_extractor.getFixedMappings());
		
		index.clearAuxStructuresforLabellingSchema();
		
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time indexing hierarchy + anchors (ILS) (s): " + (float)((double)fin-(double)init)/1000.0);
		
	}
	
	
	
	
	
	
	
	
	private void createCandidateMappings() throws Exception{
		
		writeInternalLog("\nCANDIDATE DIAGNOSIS 1");
		
		//After this method we will have 3 sets: Mappings2Review with DandG, Mappings to ask user, and discarded mappoings
		
		init = Calendar.getInstance().getTimeInMillis();
		mapping_extractor.createCandidates();
		
		
		//Delete Alt labels in class index
		//We won't extract more mappings
		index.clearAlternativeLabels4Classes();
		
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time creating candidates (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		//TODO Uncomment if no fixed anchors
		//We add candidates to anchors, nothing noew is fixed
		//mapping_extractor.setExactAsFixed(false);
		//mapping_extractor.moveMappingsToReview2AnchorList();
		
		
		//Clean with Dawling and Gallier mappings 2 review
		//-- D&G
		//countAnchors();
		//mappings_assessment = new AnchorAssessment(index, mapping_extractor);
		init = Calendar.getInstance().getTimeInMillis();
		if (cleanD_G){
			//Adds clean mappings to anchors. Conflictive and split mappings to respective sets
			init = Calendar.getInstance().getTimeInMillis();
			mappings_assessment.CheckSatisfiabilityOfIntegration_DandG(mapping_extractor.getMappings2Review());  //With Fixed mappings!
			//mappings_assessment.CheckSatisfiabilityOfIntegration_DandG(mapping_extractor.getAnchors());  //No fixed mappings
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Time cleaning new candidates D&G (s): " + (float)((double)fin-(double)init)/1000.0);
		}
		
		//TODO Merge mappings 2 review and anchors
		//Comment if no fixed anchors
		mapping_extractor.moveMappingsToReview2AnchorList();
		
		
		
	
		
		
		
		//Remove mappings to review
		mapping_extractor.getMappings2Review().clear();
		
		
		//INTERVAL LABELLING SCHEMA
		//--------------------------
		init = Calendar.getInstance().getTimeInMillis();
		index.setIntervalLabellingIndex(mapping_extractor.getLogMapMappings());//It also contains mappings 2 review
		index.clearAuxStructuresforLabellingSchema();
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time indexing hierarchy + anchors and candidates I (ILS) (s): " + (float)((double)fin-(double)init)/1000.0);
		
		//LogOutput.print("\n\nNEW UNSAT:");
		//To check not solved cases of unsatisfiability
		//mappings_assessment.CheckSatisfiabilityOfConcreteClasses_DandG(mapping_extractor.getAnchors(), index.getUnsatisfiableClassesILS());
		
		//Assess mappings 2 ask user
		mapping_extractor.assessMappings2AskUser();
		
				
		
		
		
		
		
		
		
	}
	
	
	
	
	
	
	private void createMappingsInteractiveProcess(boolean useThreshold) throws Exception{
		
		boolean useInteractivity=false;
		boolean useHeuristics=false;
		boolean orderQuestions=false;
		int error_user=0;
		boolean ask_everything=false;
		boolean record_interactivity=false;
		String logmap_mappings_path="";
	
		
		writeInternalLog("\nCANDIDATE DIAGNOSIS 2");
		
		
		//At this point we only have mappings to ask user
		init = Calendar.getInstance().getTimeInMillis();
		
		if (!useThreshold)
			interactiveProcessManager = 
				new InteractiveProcessAmbiguity(
						index, mapping_extractor, useHeuristics, orderQuestions, error_user, ask_everything,
						record_interactivity,
						logmap_mappings_path + "SimulationInteractivity_" + useInteractivity + "_" + useHeuristics + "_" + orderQuestions + ".txt");
		else 
			interactiveProcessManager = new InteractiveProcessThreshold(index, mapping_extractor);
		
		if (useInteractivity){
			interactiveProcessManager.startInteractiveProcess(); //Starts "automatic" user interaction			
		}
		//TODO!!!!
		interactiveProcessManager.endInteractiveProcess(mapping_extractor.isFilterWithHeuristicsSecondLevelMappings()); //adds mappings selected by user and logmap heuristics
		/*else {
			for (MappingObjectInteractivity mapping : mapping_extractor.getListOfMappingsToAskUser()){
				
				mapping_extractor.addSubMapping2Mappings2Review(mapping.getIdentifierOnto1(), mapping.getIdentifierOnto2());
				mapping_extractor.addSubMapping2Mappings2Review(mapping.getIdentifierOnto2(), mapping.getIdentifierOnto1());
				
			}
		}*/
		fin = Calendar.getInstance().getTimeInMillis();
		writeInternalLog("Time interactive process (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		//Also index interval labelling?? Problem, no mappings 1-1 for index....
		//We keep previous index
		
		
		
		//TODO Add weakened mappings by D and G iff no conflictive or already inferred
		//Add no conflictive to anchors and the clean together with interactivity
		//We should add a low confidence so that if they are involved in an error then remove
		//isMappingWeakenedDandG
		//TODO Included in assesMappings2AskUser
		//mapping_extractor.assesWeakenedMappingsDandG(true, false); //we add them to mappings to review
		
		
		
		
		//Clean interactive-like mappings + weakened with DandG		
		
		init = Calendar.getInstance().getTimeInMillis();
		if (cleanD_G){
			
			
			//TODO comment
			/*init = Calendar.getInstance().getTimeInMillis();
			mappings_assessment.CountSatisfiabilityOfIntegration_DandG(mapping_extractor.getMappings2Review());
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Time checking satisfiability D&G (s): " + (float)((double)fin-(double)init)/1000.0);
			*/
			
			//Adds clean mappings to anchors. Conflictive and split mappings to respective sets
			init = Calendar.getInstance().getTimeInMillis();
			mappings_assessment.CheckSatisfiabilityOfIntegration_DandG(mapping_extractor.getMappings2Review());  //With Fixed mappings!
			//mappings_assessment.CheckSatisfiabilityOfIntegration_DandG(mapping_extractor.getAnchors());  //No fixed mappings
			fin = Calendar.getInstance().getTimeInMillis();
			writeInternalLog("Time cleaning interactive mappings D&G (s): " + (float)((double)fin-(double)init)/1000.0);
		}
		
		//TODO Merge mappings 2 review and anchors
		//Comment if no fixed anchors
		mapping_extractor.moveMappingsToReview2AnchorList();
		
		
		//Add new weakened mappings
		//TODO Do not add them? Since they are suspicious>?
		//mapping_extractor.assesWeakenedMappingsDandG(false, true); //we add them to anchors
		
		
		//Remove mappings to review
		mapping_extractor.getMappings2Review().clear();
		
		
	}
	
	
	
	/**
	 * Discovery and assessment of Instance mappings
	 */
	private void createAndAssessInstanceMappings(){
		
		mapping_extractor.createInstanceAnchors();
		
		//Clean D&G
		if (mapping_extractor.getInstanceMappings().size()>0 && cleanD_G){
			
			init = Calendar.getInstance().getTimeInMillis();
			
			//We have an specific method since there is not a top-down search. And we first repair classes
			mappings_assessment.CheckSatisfiabilityOfIntegration_DandG_Individuals(
					mapping_extractor.getInstanceMappings());
			
			fin = Calendar.getInstance().getTimeInMillis();
			LogOutput.printAlways("Time cleaning instance mappings D&G (s): " + (float)((double)fin-(double)init)/1000.0);
		}
		
		
		onto_process1.clearInvertedFiles4Individuals();
		onto_process2.clearInvertedFiles4Individuals();
	
	
	}
	
	
	
	
	/**
	 * This method creates the OWL files correspondent to the overlapping/module files
	 */
	private void saveOverlappingModules() throws Exception{
		
		
		//OWLDataFactory dataFactory = OWLManager.getOWLDataFactory();
		OWLDataFactory dataFactory = SynchronizedOWLManager.createOWLDataFactory();
		
		String iri_module1 = iri_output + "/module1.owl";
		String iri_module2 = iri_output + "/module2.owl";
		String iri_mappings = iri_output + "/mappings.owl";
		String iri_integrated_onto = iri_output + "/integratedOntology.owl";
		String iri_integrated_onto_modules = iri_output + "/integratedOntologyWithModules.owl";
		
		//We need the IRIs to use the reasoner (optional)
		//progress_manager.setIntegratedOntologyIRIStr(iri_integrated_onto);
		//progress_manager.setIntegratedOntologyModulesIRIStr(iri_integrated_onto_modules);
		
		
		List<AddImport> listImports2Add= new ArrayList<AddImport>();
		
		init = Calendar.getInstance().getTimeInMillis();
		
		
		///INTEGRATED ONTOLOGY		
		listImports2Add.clear();
		
		//OWLOntologyManager managerIntegratedOnto = OWLManager.createOWLOntologyManager();
		OWLOntologyManager managerIntegratedOnto = SynchronizedOWLManager.createOWLOntologyManager();
		
		OWLOntology integratedOntology = 
				managerIntegratedOnto.createOntology(IRI.create(iri_integrated_onto));
		
		listImports2Add.add(
				new AddImport(
						integratedOntology,
						dataFactory.getOWLImportsDeclaration(IRI.create(iri1_str))
						));
		
		listImports2Add.add(
				new AddImport(
						integratedOntology,
						dataFactory.getOWLImportsDeclaration(IRI.create(iri2_str))
						));
		
		listImports2Add.add(
				new AddImport(
						integratedOntology,
						dataFactory.getOWLImportsDeclaration(IRI.create(iri_mappings))
						));
		
		managerIntegratedOnto.applyChanges(listImports2Add);
		
		//managerIntegratedOnto.saveOntology(
		//		integratedOntology, new RDFXMLOntologyFormat(), IRI.create("file:" + path_output + "/integratedOntology.owl"));
		SynchronizedOWLManager.saveOntology(managerIntegratedOnto, integratedOntology, "file:" + path_output + "/integratedOntology.owl");

		
		
		updateHTMLProgress("Full integrated ontology: " + 
				"<a href=\"" + iri_integrated_onto + "\">[Original ontologies + mappings]</a>, " + 
				//"<a href=\"" + iri_integrated_onto_modules + "\">[Overlapping ontologies + mappings]</a> " + 
				"<i>(note that this ontology only imports the respective OWL files)</i>");
		
		
		
		
		
		//----------------------------------------
		///INTEGRATED ONTOLOGY WITH MODULES
		//-----------------------------------------
		
		//OWLOntologyManager moduleManager1 = OWLManager.createOWLOntologyManager();
		//OWLOntologyManager moduleManager1 = SynchronizedOWLManager.createOWLOntologyManager();
		//OWLOntologyManager moduleManager2 = OWLManager.createOWLOntologyManager();
		//OWLOntologyManager moduleManager2 = SynchronizedOWLManager.createOWLOntologyManager();
		
		//moduleManager1.saveOntology(
		//		overlappingExtractor.getOverlappingOnto1(), new RDFXMLOntologyFormat(), IRI.create("file:" + path_output + "/module1.owl"));
		
		//moduleManager2.saveOntology(
		//		overlappingExtractor.getOverlappingOnto2(), new RDFXMLOntologyFormat(), IRI.create("file:" + path_output + "/module2.owl"));
		
		//Module 1
		SynchronizedOWLManager.saveOntology(overlappingExtractor.getOverlappingOnto1(), "file:" + path_output + "/module1.owl");
		
		//Module 2
		SynchronizedOWLManager.saveOntology(overlappingExtractor.getOverlappingOnto2(), "file:" + path_output + "/module2.owl");
		
		
		
		updateHTMLProgress("Overlapping ontology modules: " + 
				"<a href=\"" + iri_module1 + "\">[Module 1]</a>, " + 
				"<a href=\"" + iri_module2 + "\">[Module 2]</a>.");
		
		
		
		//Create ontologies importing integrated ontologies		
		
		
		
		
		
		//OWLOntologyManager managerIntegratedOntoWithModules = OWLManager.createOWLOntologyManager();
		OWLOntologyManager managerIntegratedOntoWithModules = SynchronizedOWLManager.createOWLOntologyManager();
		
		OWLOntology integratedOntologyWithModules = 
				managerIntegratedOntoWithModules.createOntology(IRI.create(iri_integrated_onto_modules));
		
		listImports2Add.add(
				new AddImport(
						integratedOntologyWithModules,
						dataFactory.getOWLImportsDeclaration(IRI.create(iri_module1))
						));
		
		listImports2Add.add(
				new AddImport(
						integratedOntologyWithModules,
						dataFactory.getOWLImportsDeclaration(IRI.create(iri_module2))
						));
		
		listImports2Add.add(
				new AddImport(
						integratedOntologyWithModules,
						dataFactory.getOWLImportsDeclaration(IRI.create(iri_mappings))
						));
		
		
		managerIntegratedOntoWithModules.applyChanges(listImports2Add);
		
		//managerIntegratedOntoWithModules.saveOntology(
		//		integratedOntologyWithModules, new RDFXMLOntologyFormat(), IRI.create("file:" + path_output + "/integratedOntologyWithModules.owl"));
		SynchronizedOWLManager.saveOntology(managerIntegratedOntoWithModules, integratedOntologyWithModules, "file:" + path_output + "/integratedOntologyWithModules.owl");
		
		
				
		
		
		updateHTMLProgress("Integrated ontology using overlappings/modules: " + 
				//"<a href=\"" + iri_integrated_onto + "\">[Original ontologies + mappings]</a>, " + 
				"<a href=\"" + iri_integrated_onto_modules + "\">[Overlapping ontologies + mappings]</a> " + 
				"<i>(note that this ontology only imports the respective OWL files)</i>");
		
		
		
		
		fin = Calendar.getInstance().getTimeInMillis();			
		writeInternalLog("Time Saving overlapping and integrated ontologies (s): " + (float)((double)fin-(double)init)/1000.0);
		
		
		
		
	}
	
	
	
	private void saveExtractedMappings() throws Exception{
		
		init = Calendar.getInstance().getTimeInMillis();
		
		
		int dir_mapping;
		
		int num_class_mappings=0;
		int num_prop_mappings=0;
		int num_instance_mappings=0;
		
		OutPutFilesManager outPutFilesManager = new OutPutFilesManager();
		
		
		outPutFilesManager.createOutFiles(
					path_output + "/mappings", 
					OutPutFilesManager.AllFormats,
					onto_process1.getOntoIRI(),
					onto_process1.getOntoIRI());
			
						
			for (int ide1 : getClassMappings().keySet()){
				for (int ide2 : getClassMappings().get(ide1)){
					
					dir_mapping = getDirClassMapping(ide1, ide2);
					
					if (dir_mapping!=Utilities.NoMap){
						
						num_class_mappings++;
						
						if (dir_mapping!=Utilities.R2L){
									
							outPutFilesManager.addClassMapping2Files(
									getIRI4ConceptIdentifier(ide1),
									getIRI4ConceptIdentifier(ide2),
									dir_mapping,
									getConfidence4ConceptMapping(ide1, ide2)
									);
						}
						else{
							outPutFilesManager.addClassMapping2Files(								
									getIRI4ConceptIdentifier(ide2),
									getIRI4ConceptIdentifier(ide1),
									dir_mapping,
									getConfidence4ConceptMapping(ide2, ide1)
									);
						}
					}
				}
			}
			
			for (int ide1 : getDataPropMappings().keySet()){
				
				num_prop_mappings++;
				
				outPutFilesManager.addDataPropMapping2Files(
							getIRI4DataPropIdentifier(ide1),
							getIRI4DataPropIdentifier(getDataPropMappings().get(ide1)),
							Utilities.EQ,  
							getConfidence4DataPropConceptMapping(ide1, getDataPropMappings().get(ide1))							
							);
			}
			
			for (int ide1 : getObjectPropMappings().keySet()){		
				
				num_prop_mappings++;
				
				outPutFilesManager.addObjPropMapping2Files(
							getIRI4ObjectPropIdentifier(ide1),
							getIRI4ObjectPropIdentifier(getObjectPropMappings().get(ide1)),
							Utilities.EQ, 
							getConfidence4ObjectPropConceptMapping(ide1, getObjectPropMappings().get(ide1))
							);
			}
			
			
			//TODO: update!!
			if (Parameters.perform_instance_matching && Parameters.output_instance_mappings){
				
				for (int ide1 : getInstanceMappings().keySet()){
					for (int ide2 : getInstanceMappings().get(ide1)){
						
						num_instance_mappings++;
					
						outPutFilesManager.addInstanceMapping2Files(
								getIRI4InstanceIdentifier(ide1), 
								getIRI4InstanceIdentifier(ide2), 
								getConfidence4InstanceMapping(ide1, ide2)
							);
						
					}
				
				}
			}
			
			
						
			outPutFilesManager.closeAndSaveFiles();
			
			String iri_mappings_owl = iri_output + "/mappings.owl";
			String iri_mappings_txt = iri_output + "/mappings.txt";
			String iri_mappings_rdf = iri_output + "/mappings.rdf";
			
			updateHTMLProgress("Output mappings (class mappings = " + num_class_mappings + 
						", property mappings = " + num_prop_mappings + ", instance mappings = " + num_instance_mappings + "): " + 
						"<a href=\"" + iri_mappings_owl +  "\">[OWL format]</a>, " + 
						"<a href=\"" + iri_mappings_txt + "\">[TXT format]</a>, " + 
						"<a href=\"" + iri_mappings_rdf + "\">[OAEI Alignment format]</a>.");
			
			
			
			fin = Calendar.getInstance().getTimeInMillis();			
			writeInternalLog("Time Saving output mapping files (s): " + (float)((double)fin-(double)init)/1000.0);
			
		
		
		
	}

	
	
	

	
	
	
	
	
	
	
	
	

	

	
	
	
	public Map<Integer, Set<Integer>> getClassMappings(){
		return mapping_extractor.getLogMapMappings();
		
	}
	
	public int getDirClassMapping(int ide1, int ide2){
		return mapping_extractor.getDirMapping(ide1, ide2);
	}
	
	
	public String getIRIOntology1(){
		return onto_process1.getOntoIRI();
	}
	
	public String getIRIOntology2(){
		return onto_process2.getOntoIRI();
	}

	public Map<Integer, Integer> getDataPropMappings(){
		return mapping_extractor.getDataPropertyAnchors();	
	}
	
	
	public Map<Integer, Integer> getObjectPropMappings(){
		return mapping_extractor.getObjectPropertyAnchors();	
	}
	
	
	public Map<Integer, Set<Integer>> getInstanceMappings(){
		return mapping_extractor.getInstanceMappings();	
	}
	
	
	public double getConfidence4ConceptMapping(int ide1, int ide2){
		return mapping_extractor.getConfidence4Mapping(ide1, ide2);
	}
	
	public double getConfidence4DataPropConceptMapping(int ide1, int ide2){
		return mapping_extractor.getConfidence4DataPropertyAnchor(ide1, ide2);
	}
	
	public double getConfidence4ObjectPropConceptMapping(int ide1, int ide2){
		return mapping_extractor.getConfidence4ObjectPropertyAnchor(ide1, ide2);
	}
	
	public double getConfidence4InstanceMapping(int ide1, int ide2){
		return mapping_extractor.getConfidence4InstanceMapping(ide1, ide2);
	}
	
	public String getIRI4ConceptIdentifier(int ide){
		return index.getIRIStr4ConceptIndex(ide);
	}
	
	public String getIRI4DataPropIdentifier(int ide){
		return index.getIRIStr4DataPropIndex(ide);
	}
	
	public String getIRI4ObjectPropIdentifier(int ide){
		return index.getIRIStr4ObjPropIndex(ide);
	}
	
	
	public String getIRI4InstanceIdentifier(int ide){
		return index.getIRIStr4IndividualIndex(ide);
	}
	
	
	public void clearIndexStructures(){
		index.clearTaxonomicalStructures();
	}
	
	
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
