package OWL2generator;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.ListIterator;

public class RelationsFetcher 
{
	private ArrayList<TypeOf_Relation> rels = null ; 
	
	RelationsFetcher(Connection conn) 
	{ 
		this.rels = getRels(conn) ;
		
		//  __testShowRelations() ;		
	
	}   //  end of 1st constructor
	
	RelationsFetcher() 
	{ 
		;

	}   //  end of 2nd constructor
	
	public ArrayList<TypeOf_Relation>getRelations() 
	{ 
	    return this.rels ; 
	    
	}   //  end of method getRelations()

	    /**
	     * Fetches all relations with their subjects/objects and associated data assertions.
	     * Assumes the current connection schema contains the tables:
	     *   N_ARY_RELATIONS, N_ARY_PARTICIPANTS, N_ARY_DATA_ASSERTIONS
	     */
	    public ArrayList<TypeOf_Relation> getRels(Connection conn) 
	    {
	        ArrayList<TypeOf_Relation> relations = new ArrayList<>();

	        final String selectRelationsSql =
	              "SELECT n_ary_relation_id, predicate_IRI, relation_name, " +
	                      "relation_annotation, causal_event_individual " +
	              "FROM N_ARY_RELATIONS ORDER BY relation_name";    // n_ary_relation_id";

	        final String selectParticipantsWithDataSql =
	              "SELECT p.participant_id, p.n_ary_relation_id, p.class_IRI, p.role_type, " +
	              "       a.data_property_IRI, a.data_property_value " +
	              "FROM N_ARY_PARTICIPANTS p " +
	              "LEFT JOIN N_ARY_DATA_ASSERTIONS a ON a.participant_id = p.participant_id " +
	              "WHERE p.n_ary_relation_id = ? " +
	              "ORDER BY p.participant_id, a.assertion_id";

	        try (PreparedStatement relStmt  = conn.prepareStatement(selectRelationsSql);
	             ResultSet relRs            = relStmt.executeQuery();
	             PreparedStatement partStmt = conn.prepareStatement(selectParticipantsWithDataSql)) 
	        {

	            while (relRs.next()) 
	            {
	                int relationId = relRs.getInt("n_ary_relation_id");

	                TypeOf_Relation tor = new TypeOf_Relation();
	                
	                tor.predicate           = relRs.getString("predicate_IRI")           ;
	                tor.relationName        = relRs.getString("relation_name")           ;
	                tor.relationAnnotation  = relRs.getString("relation_annotation")     ;
	            	tor.n_ary_relation_id   = relRs.getInt("n_ary_relation_id")          ;
	                tor.causal_event_indiv  = relRs.getString("causal_event_individual") ;
	                
	                partStmt.setInt(1, relationId);
	                
	                try (ResultSet partRs = partStmt.executeQuery()) 
	                {
	                    while (partRs.next()) 
	                    {
	                        TypeOf_Relation.RelationMemberData rmd = tor.new RelationMemberData();
	                        
	                        rmd.OWLclassName      = partRs.getString("class_IRI")           ;
	                        rmd.dataPropertyName  = partRs.getString("data_property_IRI")   ;
	                        rmd.dataPropertyValue = partRs.getString("data_property_value") ;
                            rmd.participant_id    = partRs.getInt("participant_id")         ;
	                        rmd.n_ary_relation_id = partRs.getInt("n_ary_relation_id")      ;
	                        
	                        String roleType       = partRs.getString("role_type")           ;

	                        String role = roleType == null ? "" : roleType.trim();
	                        if ("SUBJECT".equalsIgnoreCase(role)) 
	                            tor.subject.add(rmd);
	                        else if ("OBJECT".equalsIgnoreCase(role)) 
	                            tor.object.add(rmd);
	                        else 
	                            ; // Unknown role type; it can be ignored
	                    }
	                }

	                relations.add(tor);
	                
	            }   //  end of outer while-loop
	            
	        } 
	        catch (SQLException e) 
	        {
	            System.out.println("Cannot fetch relations");
	            System.out.println("SQLException: " + e.getMessage());
	            System.out.println("SQLState: " + e.getSQLState());
	            System.out.println("VendorError: " + e.getErrorCode());
	            e.printStackTrace();
	        }

	        new DBFO_main().log(new StringBuilder()
                                    .append("    returned  " 
	                                 + relations.size() 
	                                 + " n-ary casual relationships\n")
                                    .toString()
                               ) ; 
	        return relations;
	        
	    }   //  end of method getRels()
    
    private void __testShowRelations()
    {
        ListIterator<TypeOf_Relation> itr = this.rels.listIterator() ; 
    	
        while (itr.hasNext())
        {
        	TypeOf_Relation r = itr.next() ;
        	
            String relationName       = r.relationName       ;            	
            String relationAnnotation = r.relationAnnotation ;
            String predicate          = r.predicate          ;
            int    n_ary_relation_id  = r.n_ary_relation_id  ;
            String causal_event_indiv = r.causal_event_indiv ;

            
          System.out.println("\nrelationName        : " + relationName      ) ;
            System.out.println("relationAnnotation  : " + relationAnnotation) ;
            System.out.println("predicate           : " + predicate         ) ;
            System.out.println("n_ary_relation_id   : " + n_ary_relation_id ) ;
            System.out.println("causal_event_indiv  : " + causal_event_indiv) ;
            
            System.out.println("\nSUBJECTS") ; 
            ListIterator<TypeOf_Relation.RelationMemberData> sItr = r.subject.listIterator()  ;
            while (sItr.hasNext())
            {
            	TypeOf_Relation.RelationMemberData s = sItr.next() ;

              System.out.println("\n    class name           : >" + s.OWLclassName      + "<") ; 
                System.out.println("    data property name   : >" + s.dataPropertyName  + "<") ;
                System.out.println("    data property value  : >" + s.dataPropertyValue + "<") ;
                System.out.println("    participant_id       : >" + s.participant_id    + "<") ;
                System.out.println("    n_ary relation id    : >" + s.n_ary_relation_id + "<") ;
            }

            System.out.println("\nOBJECTS") ; 
            ListIterator<TypeOf_Relation.RelationMemberData> oItr = r.object.listIterator()  ;
            while (oItr.hasNext())
            {
            	TypeOf_Relation.RelationMemberData o = oItr.next() ;

              System.out.println("\n    class name           : >" + o.OWLclassName      + "<") ; 
                System.out.println("    data property name   : >" + o.dataPropertyName  + "<") ;
                System.out.println("    data property value  : >" + o.dataPropertyValue + "<") ;
                System.out.println("    participant_id       : >" + o.participant_id    + "<") ;
                System.out.println("    n_ary relation id    : >" + o.n_ary_relation_id + "<") ;
            }
            
        }   //  end of outer while-loop

    }   //  end of method showRelations() 
    
}   //  end of class RelationsFetcher
