package OWL2generator;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.util.*;


public class DBFO_GenOWL_n_ary_CasualRelationships 
{
	private Connection                 conn             = null ;
    private int                        countOfRelations = 0 ; 
    private DBFO_DButils               dbu              = new DBFO_DButils() ;
    private FileWriter                 fileWriter       = null ;
    private GenerateNewIndividualName  gni              = null ;
	private ArrayList<TypeOf_Relation> rels             = null ;
    
	DBFO_GenOWL_n_ary_CasualRelationships(String      OWLresultFile,  //  result file name 
                                          Connection  conn    //  active DB connection
                                         )
	{
		this.conn = conn ;
        this.gni  = new GenerateNewIndividualName(conn) ;
        this.rels = new RelationsFetcher(conn).getRelations() ;
        
        try 
        { 
            this.fileWriter = new FileWriter(new File(OWLresultFile), true) ;

            ListIterator<TypeOf_Relation> itr = this.rels.listIterator() ; 
        	
            while (itr.hasNext())
            {
                create_N_ary_casualRelation(itr.next()) ;
                
            	countOfRelations++ ;
            }
            
            /**
             *  closing the buffered writer
             */
            this.fileWriter.close() ;
        }
        catch(IOException IOex)
        {
            IOex.printStackTrace() ;
        }

        /**
         *  Logging of the output volume
         */
        DBFO_main OWL2G = new DBFO_main() ;
        
        OWL2G.log(new StringBuilder()
                      .append("    inserted  " + countOfRelations + 
                    		  " n_ary OWL casual relationship(s)\n")
                      .toString()  
                 ) ; 
    	
	}   //  end of constructor     
	
    private void connectCausesToEvent(String            cce, 
                                      ArrayList<String> dom_Individuals
                                     )
    {
    	writeOWLresult("\n    <!--  connecting causes to event  -->\n") ;
    	
    	Iterator<String> itr = dom_Individuals.iterator() ; 
    	
        while (itr.hasNext())
        {
            writeOWLresult(  "    <ObjectPropertyAssertion>\n"
                           + "        <ObjectProperty IRI=\"#contributesToCausalEvent\"/>\n"
                           + "        <NamedIndividual IRI=\"#" + itr.next() + "\"/>\n"
                           + "        <NamedIndividual IRI=\"#" + cce + "\"/>\n"
                           + "    </ObjectPropertyAssertion>\n") ;
        }
        
    }   //  end of method connectCausesToEvent()

    private void connectEventsToEffects(String            cce, 
                                        ArrayList<String> rng_Individuals
                                       )
    {
    	writeOWLresult("\n    <!--  connecting event to effects  -->\n") ;

    	Iterator<String> itr = rng_Individuals.iterator() ; 
    	
        while (itr.hasNext())
        {
            writeOWLresult(  "    <ObjectPropertyAssertion>\n"
                           + "        <ObjectProperty IRI=\"#causalEventProduces\"/>\n"
                           + "        <NamedIndividual IRI=\"#" + cce + "\"/>\n"
                           + "        <NamedIndividual IRI=\"#" + itr.next() + "\"/>\n"
                           + "    </ObjectPropertyAssertion>\n") ;
        }

    }   //  end of method connectEventsToEffects()

    private void create_N_ary_casualRelation(TypeOf_Relation r)
    {
        String relationName = r.relationName       ;            	
        String predicate    = r.predicate          ;
        String cce          = r.causal_event_indiv ;  //  collective_Causal_Event_ID0000nn
        
        writeOWLresult(  "\n    <!--\n        n-ary causal relation : " + relationName
        		       + "\n        " + showRelation(r)
        		       + "\n      -->\n") ;
        
        //            1         2         3
        //  01234567890123456789012345678901
        //  collective_Causal_Event_ID000014
        
        cce = "c" + cce.substring(12, 32) ;

        createAndAnnotateCurrCasualEventIndividual(cce, r) ;

        ArrayList<String> dom_Individuals = createAndAnnotateNewParticipantIndividuals(r, r.subject.listIterator(), "domain" ) ;
        ArrayList<String> rng_Individuals = createAndAnnotateNewParticipantIndividuals(r, r.object. listIterator(), "range") ;

        connectCausesToEvent(  cce, dom_Individuals) ;  //  not active yet
        connectEventsToEffects(cce, rng_Individuals) ;  //  not active yet

        performDescartesProduct(predicate,
                                dom_Individuals,
                                rng_Individuals
                               ) ;
        
    }   //  end of method create_N_ary_casualRelation()

    private void createAndAnnotateCurrCasualEventIndividual(String          cce,
                                                            TypeOf_Relation r)
    {
    	writeOWLresult("\n    <!--  freshing reified individual   -->\n") ;
    	
    	writeOWLresult(  "    <Declaration>\n"
                       + "        <NamedIndividual IRI=\"#" + cce + "\"/>\n"
                       + "    </Declaration>\n"
                       + "    <ClassAssertion>\n"
                       + "        <Class IRI=\"#Collective_Causal_Event\"/>\n" 
                       + "        <NamedIndividual IRI=\"#" + cce + "\"/>\n" 
                       + "    </ClassAssertion>\n") ;
    	
    	String literal =   "The '" + cce + "' named individual is associated to the relation: "
    			         + "\n'"  + r.relationName + "'"
    			         + "\n\n" + r.relationAnnotation 
    			         + "\n\nFormal notation: "
    			         + showRelation(r) 
    			         + "\n\nRemark: The 'causal_Event_ID000nnn' individuals represent reified"
    			         + " causal events capturing sociological relations defined by their name"
    			         + " and the symbolic description. They are named individuals"
    			         + " of the 'Collective_Causal_Event' class, with identifiers"
    			         + " reflecting their systematic role in modelling"
    			         + " complex n-ary sociological relationships." ; 
    	
        writeOWLresult("\n    <AnnotationAssertion>\n"
                       + "        <AnnotationProperty abbreviatedIRI=\"skos:definition\"/>\n"
                       + "        <IRI>#" + cce + "</IRI>\n"
                       + "        <Literal>" + literal + "\n"
                       + "        </Literal>\n"
                       + "    </AnnotationAssertion>\n") ;

    }   //  end of method createAndAnnotateCurrCasualEventIndividual()

    private ArrayList<String> createAndAnnotateNewParticipantIndividuals(TypeOf_Relation                                  r,
                                                                         ListIterator<TypeOf_Relation.RelationMemberData> itr,
    		                                                             String title)
    {
    	writeOWLresult("\n    <!--  creating " + title + " individuals  -->\n") ;
    	
    	ArrayList<String> result = new ArrayList<String>() ; 
        while (itr.hasNext())
        {
        	TypeOf_Relation.RelationMemberData rmd = itr.next() ;

            String class_name = rmd.OWLclassName ;
            String individual = gni.getNewIndividualName(class_name) ;
            
            writeOWLresult(  "    <Declaration>\n"
                           + "        <NamedIndividual IRI=\"#" + individual + "\"/>\n"
                           + "    </Declaration>\n"
                           + "    <ClassAssertion>\n"
                           + "        <Class IRI=\"#" + class_name + "\"/>\n" 
                           + "        <NamedIndividual IRI=\"#" + individual + "\"/>\n" 
                           + "    </ClassAssertion>\n") ;
        	
        	String literal =   "The " + individual + " named individual (as part of"
        			 + " the " + title + " parameter set) is associated to the relation: '"
			         + r.relationName
			         + "' \n\nCausal relation: "
			         + showRelation(r) 
			         + "\n\nSemantical explanation of " + individual + ": \n" 
			         + dbu.getIndividualExplanation(this.conn, individual) ;
            
            writeOWLresult("\n    <AnnotationAssertion>\n"
                           + "        <AnnotationProperty abbreviatedIRI=\"skos:definition\"/>\n"
                           + "        <IRI>#" + individual + "</IRI>\n"
                           + "        <Literal>" + literal + "\n"
                           + "        </Literal>\n"
                           + "    </AnnotationAssertion>\n") ;
            
            connectDataPropertyToIndividual(individual, rmd) ;
             
            result.add(individual) ;
            
        }   //  end of while loop

        return result ;

    }   //  end of method createAndAnnotateNewParticipantIndividuals()
    
    private void connectDataPropertyToIndividual(String individual, TypeOf_Relation.RelationMemberData rmd)
    {
        String dpName  = rmd.dataPropertyName  ;
        if (   dpName  == null)  return ;

        String dpType  = dbu.getDataPropertyType(this.conn, dpName) ;
        String dpValue = rmd.dataPropertyValue ;

    	writeOWLresult("\n    <!--  connect data property/individual: " 
    	               + dpName + " / " + individual + "  -->\n") ;
    	/**
    	 *  namespace prefix cannot be resolved in this case !
    	 */
    	dpType = "http://www.w3.org/2001/XMLSchema#" + 
    	         dpType.substring(4, dpType.length())   ;
    	
        String s =  "    <DataPropertyAssertion> \n"
                  + "        <DataProperty IRI=\"#"    + dpName     + "\"/> \n"
                  + "        <NamedIndividual IRI=\"#" + individual + "\"/> \n"
                  + "        <Literal datatypeIRI=\""  + dpType     + "\">" + dpValue + "</Literal> \n"
                  + "    </DataPropertyAssertion> \n" ; 
        
        writeOWLresult(s) ;
        
    }   //  end of method connectDataPropertyToIndividual()
    
    private void performDescartesProduct(String            predicate,
    		                             ArrayList<String> dom_Individuals, 
    		                             ArrayList<String> rng_Individuals 
                                        )
    {
    	writeOWLresult("\n    <!--  direct Cartesian product assertions  -->\n") ;
    		
        for (String d : dom_Individuals)
        {
            for (String r : rng_Individuals)
            {
                writeOWLresult(  "    <ObjectPropertyAssertion>\n"
                               + "        <ObjectProperty  IRI=\"#" + predicate + "\"/>\n"
                               + "        <NamedIndividual IRI=\"#" + d         + "\"/>\n"
                               + "        <NamedIndividual IRI=\"#" + r         + "\"/>\n"
                               + "    </ObjectPropertyAssertion>\n") ;
            }
        }

    }   //  end of method performDescartesProduct()

    private String serializeParticipant(int arraySize, 
                                        ListIterator<TypeOf_Relation.RelationMemberData> itr)
    {
        String participants = "" ;
        int numofSubjects   = 0 ;

        while (itr.hasNext())
        {
            TypeOf_Relation.RelationMemberData x = itr.next() ;

            String class_name = x.OWLclassName      ; 
            
            if (++numofSubjects < arraySize)
                participants  += (class_name + ", ") ;
            else
                participants  += class_name ;
        }

        return participants ;
        
    }   //  end of method serializeParticipant()
    
    private String showRelation(TypeOf_Relation r)
    {
        String predicate          = r.predicate          ;

        String relation = "{" 
        + serializeParticipant(r.subject.size(), r.subject.listIterator())
        + "} → " + predicate 
        + " → {" 
        + serializeParticipant(r.object.size(), r.object.listIterator())
        + "}" ;

        return relation ; 
    	
    }   //  end of method showRelation()

    private void writeOWLresult(String s)
    {
        try { this.fileWriter.write(s) ; this.fileWriter.flush() ;}
        catch(IOException IOex) { IOex.printStackTrace() ;}

    }   //  end of method writeOWLresult()
    
}   //  end of class DBFO_GenOWL_n_ary_CasualRelationships
