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: '"
    			         + r.relationName
    			         + "' \n\nCausal relation: "
    			         + showRelation(r) 
    			         + "\n\nRemark: This individual represents a reified causal event"
    			         + " capturing the sociological defined by the name of the relation"
    			         + " and the symbolic description. The "
    			         + cce + " is named individuals of the Collective_Causal_Event class,"
    			         + " with identifiers reflecting their systematic role in modeling"
    			         + " 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") ;
            /*
System.out.println(  "individual: " + individual 
                   + "  -  data property: " + rmd.dataPropertyName  
                   + "  -  type: "  + dbu.getDataPropertyType(this.conn, rmd.dataPropertyName)  
                   + "  -  Value :" + rmd.dataPropertyValue) ;            
            */
            
            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") ;
/*
        if (dpValue == null       || 
            dpValue.length() == 0 || 
            dpValue.compareToIgnoreCase("null") == 0)
        {
            switch (dpType) 
            {
            	case "xsd:boolean":         dpValue = "true" ; break ; 
            	case "xsd:decimal":         dpValue = "0.0"  ; break ; 
            	case "xsd:double":          dpValue = "0.0d" ; break ; 
            	case "xsd:float":           dpValue = "0.0f" ; break ; 
            	case "xsd:int":             dpValue = "0"    ; break ;
            	case "xsd:integer":         dpValue = "0"    ; break ; 
            	case "xsd:language":        dpValue = "en"   ; break ; 
            	case "xsd:long":            dpValue = "0"    ; break ; 
            	case "xsd:negativeInteger": dpValue = "0"    ; break ; 
            	case "xsd:short":           dpValue = "0"    ; break ; 
            	case "xsd:string":          dpValue = ""     ; break ;
            	case "xsd:unsignedInt":     dpValue = "0"    ; break ; 
            	default:                    return ;      // unknown type

            }   //  end of switch (dpType)
            
        }   //  end of if (dbValue == null)
*/
    	/**
    	 *  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
