#!/usr/bin/python3.10
# -*-coding:Utf-8 -*

#==============================================================================
# TENET: AMR CTR at 'Net Expansion' level
#------------------------------------------------------------------------------
# Module grouping compositional transduction rule_sets (CTR) for the analysis of 
# AMR structures, at 'Net Expansion' level
#==============================================================================

#==============================================================================
# Query Builder Imports
#==============================================================================

#import query_builder.construct as construct
from query_builder.builders import *


#==============================================================================
# CTR Set (CTR as Sparql querries)
#==============================================================================

rule_set = {}

 
# ---------------------------------------------
# Net Expansion: Composite Class Net from Property Net
# ---------------------------------------------

rule_set['create-composite-class-net-from-property-1'] = {
    'label': "create-composite-class-net-from-property-1",
    'comment': ("Create Composite Class Net (and Restriction Net): ", 
                " (1) from relation between two classes as ARG0 and ARG1, ",
                " (2) with a relation corresponding to Core Role property",
                " (3) in normal direction"),
    'construction': f"""
        # -- New Restriction Net
        ?newRestrictionNet a net:Restriction_Net ;
            net:hasStructure {atom_property_net.structure} ;
            net:coverBaseNode ?baseLeaf ;
            net:coverTargetNode {atom_property_net.base_node}, 
                                ?nodeOfArg1Net ;
            net:hasRestrictionOnProperty {atom_property_net.id} ;
            net:hasRestrictionNetValue ?arg1Net.
            
        # -- New Class Net
        ?newNet a net:Composite_Class_Net ;
            net:hasStructure {atom_property_net.structure} ;
            net:coverBaseNode ?baseLeaf ;
            net:coverNode {atom_property_net.base_node}, 
                                ?nodeOfArg0Net, 
                                ?nodeOfArg1Net ;
            net:hasClassName ?newClassName ;
            net:hasMotherClassNet ?arg0Net ;
            net:hasRestriction01 ?newRestrictionNet.
            
        # -- Propagation of relations (from nodes to nets)
        ?inRelationRole a net:Relation.
        ?inNet ?inRelationRole ?newNet.
        ?outRelationRole a net:Relation.
        ?newNet ?outRelationRole ?outNet.
    """,
    'clause': f"""
        # -- Identify Property(arg0:Class, arg1:Class)
        
        {atom_property_net.identify(core_role='true')}
        
        {atom_property_net.id} amr:role_ARG0 ?arg0Net.
        ?arg0Net a [rdfs:subClassOf* net:Class_Net] ;
 			net:coverBaseNode ?baseLeaf ;
     			net:coverNode ?nodeOfArg0Net ;
 			net:hasClassName ?arg0Name.
            
        {atom_property_net.id} amr:role_ARG1 ?arg1Net.
        ?arg1Net a [rdfs:subClassOf* net:Class_Net] ;
 			net:coverBaseNode ?arg1Leaf ;
     			net:coverNode ?nodeOfArg1Net ;
 			net:hasClassName ?arg1Name.
            
        # -- condition: disjoint cover
        FILTER NOT EXISTS {{?arg0Net net:coverNode ?node.
			               ?arg1Net net:coverNode ?node.}}
            
        # -- Identify inbound relations linked to the base leaf (for propagation) 
         	OPTIONAL {{?inNet a [rdfs:subClassOf* net:Net] ;
                        net:coverBaseNode ?inLeaf.
                  ?inLeaf ?inRelationEdge ?baseLeaf.    
                  ?inRelationEdge amr:hasAmrRole ?inRelationRole.}}
            
        # -- Identify outgoing relations linked to the base leaf (for propagation) 
         	OPTIONAL {{?outNet a [rdfs:subClassOf* net:Net] ;
                        net:coverBaseNode ?outLeaf.
                  ?baseLeaf ?outRelationEdge ?outLeaf.    
                  ?outRelationEdge amr:hasAmrRole ?outRelationRole.}}
    """,
    'binding': f"""
		# -- New Class Name
		BIND (CONCAT(?arg0Name, '-', {atom_property_net.property_name01}) AS ?cn1).
        BIND (CONCAT(?cn1, '-', ?arg1Name) AS ?newClassName).
        
		# -- New Restriction Net
		BIND (CONCAT(str(net:), 'restriction') AS ?rn1).
		BIND (CONCAT(?rn1, '_', {atom_property_net.property_name01}) AS ?rn2).
		BIND (CONCAT(?rn2, '_', str(?arg1Name)) AS ?rn3).
        BIND (uri(?rn3) AS ?newRestrictionNet).
        
		# -- New Class Net
		BIND (CONCAT(str(net:), 'compositeClass') AS ?n1).
		BIND (CONCAT(?n1, '_', ?newClassName) AS ?n2).
        BIND (uri(?n2) AS ?newNet).
    """
}


# -- old ---
# rule_set['create-composite-class-net-from-property-1'] = {
#     'label': "create-composite-class-net-from-property-1",
#     'comment': ("Create Composite Class Net (and Restriction Net): ", 
#                 " (1) from relation between two classes as ARG0 and ARG1, ",
#                 " (2) with a relation corresponding to Core Role property",
#                 " (3) in normal direction"),
#     'construction': """
#         # -- New Restriction Net
#         ?newRestrictionNet a net:Restriction_Net ;
#             net:hasStructure ?sentenceRef ;
#             net:coverBaseNode ?baseLeaf ;
#             net:coverTargetNode ?propertyLeaf, 
#                                 ?nodeOfArg1Net ;
#             net:hasRestrictionOnProperty ?propertyNet ;
#             net:hasRestrictionNetValue ?arg1Net.
            
#         # -- New Class Net
#         ?newNet a net:Composite_Class_Net ;
#             net:hasStructure ?sentenceRef ;
#             net:coverBaseNode ?baseLeaf ;
#             net:coverNode ?propertyLeaf, 
#                                 ?nodeOfArg0Net, 
#                                 ?nodeOfArg1Net ;
#             net:hasClassName ?newClassName ;
#             net:hasMotherClassNet ?arg0Net ;
#             net:hasRestriction01 ?newRestrictionNet.
            
#         # -- Propagation of relations (from nodes to nets)
#         ?inRelationRole a net:Relation.
#         ?inNet ?inRelationRole ?newNet.
#         ?outRelationRole a net:Relation.
#         ?newNet ?outRelationRole ?outNet.
#     """,
#     'clause': """
#         # -- Identify Property(arg0:Class, arg1:Class)
#         ?propertyNet a [rdfs:subClassOf* net:Property_Net] ;
#             net:isCoreRoleLinked true ;
#             net:hasStructure ?sentenceRef ;
#             net:coverNode ?propertyLeaf ;
#             net:hasPropertyName01 ?propertyName01.
#             # -- old --- net:hasPropertyDirection net:normal_direction.
#         ?propertyNet amr:role_ARG0 ?arg0Net.
#         ?arg0Net a [rdfs:subClassOf* net:Class_Net] ;
#  			net:coverBaseNode ?baseLeaf ;
#      			net:coverNode ?nodeOfArg0Net ;
#  			net:hasClassName ?arg0Name.
#         ?propertyNet amr:role_ARG1 ?arg1Net.
#         ?arg1Net a [rdfs:subClassOf* net:Class_Net] ;
#  			net:coverBaseNode ?arg1Leaf ;
#      			net:coverNode ?nodeOfArg1Net ;
#  			net:hasClassName ?arg1Name.
            
#         # -- condition: disjoint cover
#         FILTER NOT EXISTS {?arg0Net net:coverNode ?node.
# 			               ?arg1Net net:coverNode ?node.}
            
#         # -- Identify inbound relations linked to the base leaf (for propagation) 
#          	OPTIONAL {?inNet a [rdfs:subClassOf* net:Net] ;
#                         net:coverBaseNode ?inLeaf.
#                   ?inLeaf ?inRelationEdge ?baseLeaf.    
#                   ?inRelationEdge amr:hasAmrRole ?inRelationRole.}
            
#         # -- Identify outgoing relations linked to the base leaf (for propagation) 
#          	OPTIONAL {?outNet a [rdfs:subClassOf* net:Net] ;
#                         net:coverBaseNode ?outLeaf.
#                   ?baseLeaf ?outRelationEdge ?outLeaf.    
#                   ?outRelationEdge amr:hasAmrRole ?outRelationRole.}
#     """,
#     'binding': """
# 		# -- New Class Name
# 		BIND (CONCAT(?arg0Name, '-', ?propertyName01) AS ?cn1).
#         BIND (CONCAT(?cn1, '-', ?arg1Name) AS ?newClassName).
        
# 		# -- New Restriction Net
# 		BIND (CONCAT(str(net:), 'restriction') AS ?rn1).
# 		BIND (CONCAT(?rn1, '_', str(?propertyName01)) AS ?rn2).
# 		BIND (CONCAT(?rn2, '_', str(?arg1Name)) AS ?rn3).
#         BIND (uri(?rn3) AS ?newRestrictionNet).
        
# 		# -- New Class Net
# 		BIND (CONCAT(str(net:), 'compositeClass') AS ?n1).
# 		BIND (CONCAT(?n1, '_', ?newClassName) AS ?n2).
#         BIND (uri(?n2) AS ?newNet).
#     """
# }
# -- ---

rule_set['create-composite-class-net-from-property-2'] = {
    'label': "create-composite-class-net-from-property-2",
    'comment': ("Create Composite Class Net (and Restriction Net): ", 
                " (1) from relation between two classes as ARG1 and ARG2, ",
                " (2) with a relation corresponding to Core Role property",
                " (3) in normal direction"),
    'construction': """
        # -- New Restriction Net
        ?newRestrictionNet a net:Restriction_Net ;
            net:hasStructure ?sentenceRef ;
            net:coverBaseNode ?baseLeaf ;
            net:coverTargetNode ?propertyLeaf, 
                                ?nodeOfArg2Net ;
            net:hasRestrictionOnProperty ?propertyNet ;
            net:hasRestrictionNetValue ?arg2Net.
            
        # -- New Class Net
        ?newNet a net:Composite_Class_Net ;
            net:hasStructure ?sentenceRef ;
            net:coverBaseNode ?baseLeaf ;
            net:coverTargetNode ?propertyLeaf, 
                                ?nodeOfArg1Net, 
                                ?nodeOfArg2Net ;
            net:hasClassName ?newClassName ;
            net:hasMotherClassNet ?arg1Net ;
            net:hasRestriction12 ?newRestrictionNet.
            
        # -- Propagation of relations (from nodes to nets)
        ?inRelationRole a net:Relation.
        ?inNet ?inRelationRole ?newNet.
        ?outRelationRole a net:Relation.
        ?newNet ?outRelationRole ?outNet.
    """,
    'clause': """
        # -- Identify Property(arg1:Class, arg2:Class)
        ?propertyNet a [rdfs:subClassOf* net:Property_Net] ;
            net:isCoreRoleLinked true ;
            net:hasStructure ?sentenceRef ;
            net:coverNode ?propertyLeaf ;
            net:hasPropertyName12 ?propertyName12.
        ?propertyNet amr:role_ARG1 ?arg1Net.
        ?arg1Net a [rdfs:subClassOf* net:Class_Net] ;
			net:coverBaseNode ?baseLeaf ;
    			net:coverNode ?nodeOfArg1Net ;
			net:hasClassName ?arg1Name.
        ?propertyNet amr:role_ARG2 ?arg2Net.
        ?arg2Net a [rdfs:subClassOf* net:Class_Net] ;
			net:coverBaseNode ?arg2Leaf ;
    			net:coverNode ?nodeOfArg2Net ;
			net:hasClassName ?arg2Name.
            
        # -- condition: disjoint cover
        FILTER NOT EXISTS {?arg1Net net:coverNode ?node.
			               ?arg2Net net:coverNode ?node.}
        
        # -- Identify inbound relations linked to the base leaf (for propagation) 
        	OPTIONAL {?inNet a [rdfs:subClassOf* net:Net] ;
                       net:coverBaseNode ?inLeaf.
                  ?inLeaf ?inRelationEdge ?baseLeaf.    
                  ?inRelationEdge amr:hasAmrRole ?inRelationRole.}
            
        # -- Identify outgoing relations linked to the base leaf (for propagation) 
        	OPTIONAL {?outNet a [rdfs:subClassOf* net:Net] ;
                       net:coverBaseNode ?outLeaf.
                  ?baseLeaf ?outRelationEdge ?outLeaf.    
                  ?outRelationEdge amr:hasAmrRole ?outRelationRole.}
    """,
    'binding': """
		# -- New Class Name
		BIND (CONCAT(?arg1Name, '-', ?propertyName12) AS ?cn1).
        BIND (CONCAT(?cn1, '-', ?arg2Name) AS ?newClassName).
        
		# -- New Restriction Net
		BIND (CONCAT(str(net:), 'restriction') AS ?rn1).
		BIND (CONCAT(?rn1, '_', str(?propertyName12)) AS ?rn2).
		BIND (CONCAT(?rn2, '_', str(?arg2Name)) AS ?rn3).
        BIND (uri(?rn3) AS ?newRestrictionNet).
        
		# -- New Class Net
		BIND (CONCAT(str(net:), 'compositeClass') AS ?n1).
		BIND (CONCAT(?n1, '_', ?newClassName) AS ?n2).
        BIND (uri(?n2) AS ?newNet).
    """
}

rule_set['create-composite-class-net-from-property-3'] = {
    'label': "create-composite-class-net-from-property-3",
    'comment': ("Create Composite Class Net (and Restriction Net): ", 
                " (1) from relation between two classes, ",
                " (2) with a relation corresponding to Non-Core Role property"),
    'construction': """
        # -- New Restriction Net
        ?newRestrictionNet a net:Restriction_Net ;
            net:hasStructure ?sentenceRef ;
            net:coverBaseNode ?baseLeaf ;
            net:coverTargetNode ?argNodeOfBaseNet, ?nodeOfArgNet ;
            net:hasRestrictionOnProperty ?propertyNet ;
            net:hasRestrictionNetValue ?argNet.
            
        # -- New Class Net
        ?newClassNet a net:Composite_Class_Net ;
            net:hasStructure ?sentenceRef ;
            net:coverBaseNode ?baseLeaf ;
            net:coverNode ?nodeOfBaseNet, ?nodeOfArgNet ;
            net:hasClassName ?newClassName ;
            net:hasMotherClassNet ?baseNet ;
            net:hasRestriction ?newRestrictionNet.
            
        # -- Propagation of relations (from nodes to nets)
        ?inRelationRole a net:Relation.
        ?inNet ?inRelationRole ?newNet.
        ?outRelationRole a net:Relation.
        ?newNet ?outRelationRole ?outNet.
    """,
    'clause': """
        # -- Identify Property(Class, Class)
        ?propertyNet a [rdfs:subClassOf* net:Property_Net];
            net:isCoreRoleLinked false ;
            net:hasStructure ?sentenceRef ;
            net:coverBaseNode ?baseLeaf ;
            # -- old --- net:targetArgumentNode ?argLeaf ;
            net:hasPropertyRole ?propertyRole ;
            net:hasPropertyName ?propertyName.
        # -- old --- FILTER ( ?propertyName != 'hasFeature' ).
		?baseNet ?propertyRole ?argNet.
        ?baseNet a [rdfs:subClassOf* net:Class_Net] ;
			net:coverBaseNode ?baseLeaf ;
    			net:coverNode ?nodeOfBaseNet ;
			net:hasClassName ?baseName.
        ?argNet a [rdfs:subClassOf* net:Class_Net] ;
			net:coverNode ?nodeOfArgNet ;
			net:hasClassName ?argName.
            
        # -- condition: disjoint cover
        FILTER NOT EXISTS {?baseNet net:coverNode ?node.
                           ?argNet net:coverNode ?node.}
            
        # -- Identify inbound relations linked to the base leaf (for propagation) 
        	OPTIONAL {?inNet a [rdfs:subClassOf* net:Net] ;
                       net:coverBaseNode ?inLeaf.
                  ?inLeaf ?inRelationEdge ?baseLeaf.    
                  ?inRelationEdge amr:hasAmrRole ?inRelationRole.}
            
        # -- Identify outgoing relations linked to the base leaf (for propagation) 
        	OPTIONAL {?outNet a [rdfs:subClassOf* net:Net] ;
                       net:coverBaseNode ?outLeaf.
                  ?baseLeaf ?outRelationEdge ?outLeaf.    
                  ?outRelationEdge amr:hasAmrRole ?outRelationRole.}
    """,
    'binding': """
		# -- New Class Name
		BIND (CONCAT(str(?baseName), '-', str(?propertyName)) AS ?cn1).
        BIND (CONCAT(?cn1, '-', str(?argName)) AS ?newClassName1).
        BIND (CONCAT(str(?argName), '-', str(?baseName)) AS ?newClassName2).
        BIND (IF (?propertyName != 'hasFeature', 
                  ?newClassName1,
                  ?newClassName2) 
              AS ?newClassName).
        
		# -- New Restriction Net
		BIND (CONCAT(str(net:), 'restriction') AS ?rn1).
		BIND (CONCAT(?rn1, '_', str(?propertyName)) AS ?rn2).
		BIND (CONCAT(?rn2, '_', str(?argName)) AS ?rn3).
        BIND (uri(?rn3) AS ?newRestrictionNet).
        
		# -- New Class Net
		BIND (CONCAT(str(net:), 'compositeClass') AS ?n1).
		BIND (CONCAT(?n1, '_', ?newClassName) AS ?n2).
        BIND (uri(?n2) AS ?newClassNet).
    """
}


#==============================================================================
# Development Test
#==============================================================================
    
if __name__ == '__main__':
    
    print('\n' + ' *** Development Test ***')    
        
    print('\n' + ' -- test: Atom Class Net')
    print(atom_class_net)
        
    print('\n' + ' -- test: update a test query (1)')
    test_query_1 = f"""[...]
        CONSTRUCT {{
            {atom_property_net.construct(base_node='?baseLeaf', 
                                         core_role='true',
                                         target_argument_node='?argLeaf',
                                         property_type='owl:ObjectProperty',
                                         property_name='?propertyName',
                                         property_name01='?propertyName01',
                                         property_name10='?propertyName10',
                                         property_name12='?propertyName12')}
            
        
        }}
        WHERE {{
            {atom_property_net.identify(core_role='true')}
            
            {atom_property_net.complete_clauses_for_construction('?baseLeaf')}
            
            {atom_property_net.bind_uri('{{node1.concept_label}}',
                                     '{{node1.variable_label}}')}
            
        }}
    """
    print(test_query_1)
        
    print('\n' + ' -- test: update a test query (2)')
    test_query_2 = f"""[...]
    CONSTRUCT {{
        {individual_net.construct(base_node='?baseLeaf', 
                                  mother_class_net='?classNet',
                                  individual_label='?valueLabel')}
            
       
            
    }}
    WHERE {{
            
            
    }}
    """
    print(test_query_2)
    
    
    print('\n' + ' *** - ***')