#!/bin/env python
import unittest, os, time, sys
from cStringIO import StringIO
from FuXi.Syntax.InfixOWL import *
from FuXi.Horn import ComplementExpansion
from FuXi.Rete import ReteNetwork
from FuXi.Rete.RuleStore import N3RuleStore
from FuXi.DLP import MapDLPtoNetwork, non_DHL_OWL_Semantics
from FuXi.Rete.Util import generateTokenSet
from rdflib import URIRef, RDF, RDFS
from rdflib.syntax.NamespaceManager import NamespaceManager
from rdflib.Graph import ConjunctiveGraph, Graph, ReadOnlyGraphAggregate, Namespace

HEART_NS           = Namespace('tag:info@semanticdb.ccf.org,2007:HVICoreDataElements#')
PTREC_NS           = Namespace('tag:info@semanticdb.ccf.org,2007:PatientRecordTerms#')

ONE_OF_AXIOMS=\
"""<?xml version="1.0"?>
<!DOCTYPE rdf:RDF [
    <!ENTITY heart "tag:info@semanticdb.ccf.org,2007:HVICoreDataElements#" >
    <!ENTITY ptrec "tag:info@semanticdb.ccf.org,2007:PatientRecordTerms#" >
    <!ENTITY dnode "http://www.clevelandclinic.org/heartcenter/ontologies/DataNodes.owl#" >
]>
<rdf:RDF 
     xmlns:ptrec="tag:info@semanticdb.ccf.org,2007:PatientRecordTerms#"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <owl:Class rdf:about="&heart;AorticAneurysmRepair">
        <owl:intersectionOf rdf:parseType="Collection">
            <owl:Restriction>
                <owl:onProperty rdf:resource="&dnode;contains"/>
                <owl:someValuesFrom>
                    <owl:Restriction>
                        <owl:onProperty rdf:resource="&ptrec;hasVascularProcedureName"/>
                        <owl:someValuesFrom>
                            <owl:Class>
                                <owl:oneOf rdf:parseType="Collection">
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_replacement_by_hemashield_conduit"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_replacement_by_hemashield_conduit_with_remodeling_of_aortic_valve"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_repair_of_aneurysm_or_dissection"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_repair_of_aneurysm"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_elephant_trunk_stage_2"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_plication"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_elephant_trunk_stage_1"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_replacement_by_hemashield_conduit_with_reimplantation_of_aortic_valve"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_replacement_by_hemashield_conduit_with_resuspension_of_aortic_valve"/>
                                    <rdf:Description rdf:about="&ptrec;VascularProcedureName_bentall_-_hemashield_valved_conduit"/>
                                </owl:oneOf>
                            </owl:Class>
                        </owl:someValuesFrom>
                    </owl:Restriction>                            
                </owl:someValuesFrom>
            </owl:Restriction>
            <rdf:Description rdf:about="&ptrec;SurgicalProcedure_vascular_aorta"/>
        </owl:intersectionOf>
    </owl:Class>
</rdf:RDF>
"""

class NominalRangeTransformer(object):        
    NOMINAL_QUERY=\
    """SELECT ?RESTRICTION ?INTERMEDIATE_CLASS ?NOMINAL ?PROP
       { ?RESTRICTION owl:onProperty ?PROP;
                      owl:someValuesFrom ?INTERMEDIATE_CLASS .  
         ?INTERMEDIATE_CLASS owl:oneOf ?NOMINAL .  } """    
    
    def transform(self,graph):
        """
        Transforms a 'pure' nominal range into a disjunction of value restrictions
        """
        Individual.factoryGraph = graph
        for restriction,intermediateCl,nominal,prop in graph.query(
                                 self.NOMINAL_QUERY,
                                 initNs={u'owl':OWL_NS}):
            nominalCollection=Collection(graph,nominal)
            #purge restriction
            graph.remove((restriction,None,None))
            newConjunct=BooleanClass(restriction,
                                     OWL_NS.unionOf,
                                     [Property(prop)|value|val 
                                                 for val in nominalCollection],
                                     graph)
            #purge nominalization placeholder
            graph.remove((intermediateCl,None,None))
            nominalCollection.clear()
            graph.remove((nominal,None,None))
            print "..Transformed a nominal relation range to a disjunction of value restrictions.."

class NominalRangeTransformTest(unittest.TestCase):
    def setUp(self):
        nsMgr = NamespaceManager(Graph())
        nsMgr.bind(u'ptrec',PTREC_NS)
        self.tBoxGraph = Graph(namespace_manager=nsMgr).parse(StringIO(ONE_OF_AXIOMS))
        Individual.factoryGraph = self.tBoxGraph 
        
    def testRuleStore(self):
        network = ReteNetwork(N3RuleStore())
        NominalRangeTransformer().transform(self.tBoxGraph)
        print self.tBoxGraph.serialize(format='pretty-xml')
#        for restr in self.tBoxGraph.subjects(predicate=OWL_NS.hasValue):
#            print "owl:hasValue restriction: %s %s"%(restr,manchesterSyntax(restr,self.tBoxGraph))
        list(MapDLPtoNetwork(network,self.tBoxGraph))
        for tNode in network.terminalNodes:
            print tNode.clause.n3()

if __name__ == "__main__":
    unittest.main()
