#####################################################################
#####################################################################
## Copyright 2005 Steven R. Newcomb                                ##
##                                                                 ##
## This software is licensed under the Apache License, Version 2.0 ##
## (the "License"); you may not use this file except in compliance ##
## with the License.  Copies of the License are available at       ##
##        http://www.apache.org/licenses/LICENSE-2.0               ##
##                                                                 ##
## Unless required by applicable law or agreed to in writing,      ##
## software distributed under the License is distributed on an "AS ##
## IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either ##
## express or implied.  See the License for the specific language  ##
## governing permissions and limitations under the License.        ##
##                                                                 ##
## Copies of the source code and the license are available at      ##
##        http://www.versavant.org                                 ##
#####################################################################
#####################################################################


#####################################################################
## Implementation of the conferral rules "inferFrom_a_sip_"
## in Topic Map Application "BIGASSERT".
#####################################################################

####################################
cvsRevision = "$Revision: 1.4 $" ##
####################################


import sys, copy

def inferFrom_a_sip_( vsv, conferralRule, **args):

##         a_sip properties trigger conferrals as follows:

##            - if assertionModel == 'BigAssert' or assertionModel == 'TRA_assert':
##              a t-proxy, with its t_sip and t_assertions properties.
##              The t_sip property's value is a list of references to the
##              set of r-proxies (the ones that are referenced as the
##              first member of each tuple in the a_sip property's
##              value).  The t_assertions property's value is a list of
##              proxy references with one item in it - a reference to
##              the a-proxy that has this a_sip property.

##            - for each tuple in the a_sip property value, the following
##              are conferred into existence:

##               . if assertionModel == 'BigAssert':
##                 a c-proxy, with its c_sip property.  (See c_sip,
##                 below.)

##               . if assertionModel == 'BigAssert':
##                 an r-proxy, with its r_type and r_castings properties,
##                 plus an SIP that is not governed by this TMA but is
##                 already extant.

##               . if assertionModel == 'TRA_assert':
##                 an r-proxy, with its r_type and r_rolePlayers properties,
##                 plus an SIP that is not governed by this TMA but is
##                 already extant.

##            - for each tuple in the a_sip property value that has two
##              members (i.e., that has a reference to an x-proxy)

##               . if assertionModel == 'BigAssert':
##                 an x-proxy, with its x_castings property, plus the SIP
##                 not governed by this TMA but already extant

##               . if assertionModel == 'TRA_assert':
##                 an x-proxy, with its x_roles property, which in
##                 this case consists of duples, the first member of
##                 which is a reference to an r-proxy, and the second
##                 member of which is a reference to an a-proxy, plus
##                 the SIP not governed by this TMA but already extant

##               . if assertionModel == 'A_assert':
##                 an x-proxy, with its x_roles property, which in
##                 this case consists of duples, the first member of
##                 which is a rolename of an (unreified) role, and the second
##                 member of which is a reference to an a-proxy, plus
##                 the SIP not governed by this TMA but already extant

##            - if assertionModel == 'BigAssert' or assertionModel == 'TRA_assert':
##              an a_type property on a new a_proxy that has a copy of
##              the triggering a_sip property.

##            - if assertionModel == 'BigAssert':
##              an a_castings property on a new a_proxy that has a
##              copy of the triggering a_sip property.


    assertionModel = args[ 'assertionModel']  ## possible values: 'BigAssert', 'TRA_assert', 'A_assert'

    topicMap = conferralRule.topicMap  ## make the below code less verbose (and maybe run slightly faster)
    TMA = conferralRule.TMA  ## this is the TMA that defines this conferral rule
    old_a_sip_overheadDict = TMA.propertyClasses[ 'a_sip'].overheadDict

    old_a_sip_hashableValueList = old_a_sip_overheadDict.keys()

    for old_a_sip_hashableValue in old_a_sip_hashableValueList:

        old_a_proxyIdList = old_a_sip_overheadDict[ old_a_sip_hashableValue]

        for old_a_proxyId in old_a_proxyIdList:

            old_a_proxy = topicMap.proxies[ old_a_proxyId]
            old_a_sip_instance = old_a_proxy.propertyInstances[ vsv.catKey( TMA.TMAName, 'a_sip')]

            ## Don't be triggered by any a_sip_instance that was
            ## output by an operation of this rule, and don't be
            ## triggered by an a_sip_instance property more than once.
            conferralRuleTriggerRoleId = vsv.catKey( conferralRule.conferralRuleKey, 'a_sip value')
            if old_a_sip_instance.conferralTriggerAncestry.has_key( conferralRuleTriggerRoleId) or \
                old_a_sip_instance.conferralsTriggered.has_key( conferralRuleTriggerRoleId):
                continue

            triggers = {}  ## new dictionary to work in
            triggers[ 'a_sip value'] = old_a_sip_instance.propertyInstanceKey
            conferredValueSources = {}  ## new dictionary to work in
            conferredValueSources[ 'a_sip value'] = old_a_sip_instance.propertyInstanceKey

            if vsv.conferralMayBeSignificant( conferralRule, triggers, conferredValueSources):

                if assertionModel == 'BigAssert' or assertionModel == 'TRA_assert':
                    ## new t_proxy
                    t_proxy = vsv.newProxyObject( topicMap)
                    r_proxyIdList = []
                    new_c_proxyIdList = []

                for currentTuple in old_a_sip_instance._value:

                    if len( currentTuple) == 2: ## If there's a role player
                        ## make new x_proxy
                        old_x_proxy = topicMap.proxies[ currentTuple[ 1]]
                        old_x_proxy_sip = vsv.SIPOfProxy( old_x_proxy)

                        x_proxy = vsv.newProxyObject( topicMap)

                        vsv.newPropertyInstance( x_proxy,  ## copy the x_proxy's SIP
                                                 old_x_proxy_sip.propertyClass.TMA,
                                                 old_x_proxy_sip.propertyClass.propertyClassName,
                                                 vsv.versaCopy( old_x_proxy_sip._value),   ## important!  Must be a copy; cannot be same object.
                                                 triggers,
                                                 conferredValueSources)

                    if assertionModel == 'BigAssert' or assertionModel == 'TRA_assert':
                        r_proxyIdList.append( currentTuple[ 0])

                        if assertionModel == 'BigAssert': ## BIGASSERT, not TRA_assert
                            ## new c_proxy
                            c_proxy = vsv.newProxyObject( topicMap)
                            new_c_proxyIdList.append( c_proxy.proxyId)

                            if len( currentTuple) == 1:
                                c_sip_value = [ currentTuple[ 0], old_a_proxy.proxyId]
                            else:  ## len( currentTuple) == 2:
                                c_sip_value = [ currentTuple[ 0], old_a_proxy.proxyId, currentTuple[ 1]]

                                vsv.newPropertyInstance( x_proxy,
                                                         conferralRule.TMA,
                                                         'x_castings',
                                                         [ c_proxy.proxyId],
                                                         triggers,
                                                         conferredValueSources)



                            vsv.newPropertyInstance( c_proxy,
                                                     conferralRule.TMA,
                                                     'c_sip',
                                                     c_sip_value,
                                                     triggers,
                                                     conferredValueSources)

                        ## new r_proxy
                        old_r_proxy = topicMap.proxies[ currentTuple[ 0]]
                        old_r_proxy_sip = vsv.SIPOfProxy( old_r_proxy)

                        r_proxy = vsv.newProxyObject( topicMap)

                        vsv.newPropertyInstance( r_proxy,  ## copy the r_proxy's SIP, so the new proxy will merge with the old one
                                                 old_r_proxy_sip.propertyClass.TMA,
                                                 old_r_proxy_sip.propertyClass.propertyClassName,
                                                 vsv.versaCopy( old_r_proxy_sip._value),  ## important that it's a copy, not a reference!
                                                 triggers,
                                                 conferredValueSources)

                        vsv.newPropertyInstance( r_proxy,
                                                 conferralRule.TMA,
                                                 'r_type',
                                                 [ t_proxy.proxyId],
                                                 triggers,
                                                 conferredValueSources)

                        if assertionModel == 'BigAssert': ## BIGASSERT only, not TRA_assert or A_assert
                            vsv.newPropertyInstance( r_proxy,
                                                     conferralRule.TMA,
                                                     'r_castings',
                                                     [ c_proxy.proxyId],
                                                     triggers,
                                                     conferredValueSources)

                        elif assertionModel == 'TRA_assert': ## TRA_assert only, not BIGASSERT or A_assert
                            vsv.newPropertyInstance( r_proxy,
                                                     conferralRule.TMA,
                                                     'r_rolePlayers',
                                                     [ x_proxy.proxyId],
                                                     triggers,
                                                     conferredValueSources)

                    if assertionModel == 'TRA_assert': ## TRA_assert, not BIGASSERT, nor A_assert
                        if len( currentTuple) == 2:
                            vsv.newPropertyInstance( x_proxy,
                                                     conferralRule.TMA,
                                                     'x_roles',
                                                     [ tuple( [ r_proxy.proxyId, old_a_proxy.proxyId])],
                                                     triggers,
                                                     conferredValueSources)

                    if assertionModel == 'A_assert': ## A_assert, not BIGASSERT, nor TRA_assert
                        currentTupleList = list( currentTuple)
                        if len( currentTupleList) == 1:
                            vsv.newPropertyInstance( x_proxy,
                                                     conferralRule.TMA,
                                                     'x_roles',
                                                     [ tuple( [ currentTupleList[ 0]])],
                                                     triggers,
                                                     conferredValueSources)
                        if len( currentTupleList) == 2:
                            vsv.newPropertyInstance( x_proxy,
                                                     conferralRule.TMA,
                                                     'x_roles',
                                                     [ tuple( [ currentTupleList[ 0], old_a_proxy.proxyId])],
                                                     triggers,
                                                     conferredValueSources)

                if assertionModel == 'BigAssert' or assertionModel == 'TRA_assert':
                    ## set t_proxy's properties
                    vsv.newPropertyInstance( t_proxy,
                                             conferralRule.TMA,
                                             't_sip',
                                             r_proxyIdList,
                                             triggers,
                                             conferredValueSources)

                    vsv.newPropertyInstance( t_proxy,
                                             conferralRule.TMA,
                                             't_assertions',
                                             [ old_a_proxyId],
                                             triggers,
                                             conferredValueSources)



                    ## set new a_proxy's properties
                    new_a_proxy = vsv.newProxyObject( topicMap)

                    vsv.newPropertyInstance( new_a_proxy,  ## copy the a_proxy's SIP
                                             conferralRule.TMA,
                                             'a_sip',
                                             vsv.versaCopy( old_a_sip_instance._value),
                                             triggers,
                                             conferredValueSources)

                    vsv.newPropertyInstance( new_a_proxy,
                                             conferralRule.TMA,
                                             'a_type',
                                             [ t_proxy.proxyId],
                                             triggers,
                                             conferredValueSources)

                    if assertionModel == 'BigAssert':  ## BIGASSERT, not TRA_assert or A_assert
                        vsv.newPropertyInstance( new_a_proxy,
                                                 conferralRule.TMA,
                                                 'a_castings',
                                                 new_c_proxyIdList,
                                                 triggers,
                                                 conferredValueSources)



def bridgeAcross_a_sip_Models( vsv, conferralRule, **args):
    ## from bridgeFromTMAName,,a_sip properties, infer a_sip
    ## properties in the conferralRule's TMA.  (With all that that
    ## entails.)

    bridgeFromTMAName  = args[ 'bridgeFromTMAName']
    bridgeFromTMAModel = args[ 'bridgeFromTMAModel']  ## possible values: 'BigAssert', 'TRA_assert', 'A_assert'
    bridgeToTMAModel   = args[ 'bridgeToTMAModel']    ## possible values: 'BigAssert', 'TRA_assert', 'A_assert'
    
    ## this happens later, iff bridging to A_assert:
    ##   bridgeFromR_ProxyTMAName = args[ 'bridgeFromR_ProxyTMAName']
    ##   bridgeFromR_ProxyPropertyName = args[ 'bridgeFromR_ProxyPropertyName']

    ## this happens later, iff bridging from A_assert:
    ##   bridgeToR_ProxyTMAName = args[ 'bridgeToR_ProxyPropertyName']
    ##   bridgeToR_ProxyPropertyName = args[ 'bridgeToR_ProxyPropertyName']
    ## Note that the bridgeToR_Proxy property must be an SIP, and there must already be an instance
    ## of it to merge with, or Versavant will refuse to honor a request to create it.  Therefore,
    ## an up-translation may require an original population task to pre-create the r-proxies.

    topicMap = conferralRule.topicMap  ## make the below code less verbose (and maybe run slightly faster)
    TMA = conferralRule.TMA  ## this is the TMA that defines this conferral rule
    bridgeFromTMA = topicMap.TMAs[ bridgeFromTMAName]
    bridgeFrom_a_sip_overheadDict = bridgeFromTMA.propertyClasses[ 'a_sip'].overheadDict

    old_a_sip_hashableValueList = bridgeFrom_a_sip_overheadDict.keys()

    for old_a_sip_hashableValue in old_a_sip_hashableValueList:

        old_a_proxyIdList = vsv.versaCopy( bridgeFrom_a_sip_overheadDict[ old_a_sip_hashableValue])

        for old_a_proxyId in old_a_proxyIdList:

            old_a_proxy = topicMap.proxies[ old_a_proxyId]
            old_a_sip_instance = old_a_proxy.propertyInstances[ vsv.catKey( bridgeFromTMA.TMAName, 'a_sip')]

            ## Don't be triggered by an a_sip_instance property more
            ## than once, and don't be triggered by any a_sip_instance
            ## that was output by an operation of this rule
            conferralRuleTriggerRoleId = vsv.catKey( conferralRule.conferralRuleKey, 'a_sip value')
            if old_a_sip_instance.conferralTriggerAncestry.has_key( conferralRuleTriggerRoleId) or \
                   old_a_sip_instance.conferralsTriggered.has_key( conferralRuleTriggerRoleId):
                continue

            triggers = {}  ## new dictionary to work in
            triggers[ 'a_sip value'] = old_a_sip_instance.propertyInstanceKey
            conferredValueSources = {}  ## new dictionary to work in
            conferredValueSources[ 'a_sip value'] = old_a_sip_instance.propertyInstanceKey

            if vsv.conferralMayBeSignificant( conferralRule, triggers, conferredValueSources):

                ## new a_proxy
                a_proxy = vsv.newProxyObject( topicMap)

                vsv.newPropertyInstance( a_proxy,  ## copy the existing old_a_proxy's a_sip
                                         bridgeFromTMA,
                                         'a_sip',
                                         vsv.versaCopy( old_a_sip_instance._value),
                                         triggers,
                                         conferredValueSources)

                ## calculate this TMA's SIP value

                if bridgeFromTMAModel not in [ 'BigAssert', 'TRA_assert', 'A_assert']:
                    vsv.errMsg( 'unrecognized bridgeFromTMAModel value: "%s"' % ( bridgeFromTMAModel))
                    sys.exit( 1)

                if bridgeToTMAModel not in [ 'BigAssert', 'TRA_assert', 'A_assert']:
                    vsv.errMsg( 'unrecognized bridgeToTMAModel value: "%s"' % ( bridgeToTMAModel))
                    sys.exit( 1)

                if bridgeFromTMAModel == bridgeToTMAModel:
                    vsv.errMsg( 'does not make sense to bridge from bridgeFromTMAModel "%s" to bridgeToTMAModel "%s".' % ( bridgeFromTMAModel, bridgeToTMAModel))
                    sys.exit( 1)

                if ( bridgeFromTMAModel == 'BigAssert' and bridgeToTMAModel == 'TRA_assert') or ( bridgeFromTMAModel == 'TRA_assert' and bridgeToTMAModel == 'BigAssert'):
                    ## There's no difference between the a_sip properties of BigAssert vs. TRA_assert.  Just duplicate it.
                    thisTMAs_a_sip_instanceValue = old_a_sip_instance._value

                elif ( bridgeFromTMAModel == 'BigAssert' or bridgeFromTMAModel == 'TRA_assert') and ( bridgeToTMAModel == 'A_assert'):
                    ## Here we need to convert each r-proxy reference (the first member of each tuple) into a string which will serve as the role name.
                    bridgeFromR_ProxyPropertyName = args[ 'bridgeFromR_ProxyPropertyName']
                    bridgeFromR_ProxyTMAName = args[ 'bridgeFromR_ProxyTMAName']

                    thisTMAs_a_sip_instanceValue = []
                    roleNames = {}
                    for thisTuple in old_a_sip_instance._value:
                        r_proxy = topicMap.proxies[ thisTuple[ 0]]
                        r_proxy_sip = r_proxy.propertyInstances[ vsv.catKey( bridgeFromR_ProxyTMAName, bridgeFromR_ProxyPropertyName)]
                        roleName = '%s' % ( r_proxy_sip._value)
                        if roleName in roleNames:
                            vsv.errMsg( 'a_sip value of proxy %s cannot be bridged from TMA %s (model %s) to TMA %s (model %s); two or more roleNames turn out to be "%s".' % ( old_a_proxyId, bridgeFromTMAName, bridgeFromTMAModel, TMA.TMAName, bridgeToTMAModel, roleName))
                            sys.exit( 1)
                        roleNames[ roleName] = None
                        newTupleList = [ roleName, thisTuple[ 1]]
                        thisTMAs_a_sip_instanceValue.append( tuple( newTupleList))

                elif ( bridgeFromTMAModel == 'A_assert') and ( bridgeToTMAModel == 'BigAssert' or bridgeToTMAModel == 'TRA_assert'):
                    bridgeToR_ProxyTMAName = args[ 'bridgeToR_ProxyTMAName']
                    bridgeToR_ProxyPropertyName = args[ 'bridgeToR_ProxyPropertyName']

                    thisTMAs_a_sip_instanceValue = []
                    for thisTuple in old_a_sip_instance._value:
                        r_proxy = vsv.newProxyObject( topicMap)
                        vsv.newPropertyInstance( r_proxy,
                            bridgeToR_ProxyTMAName,
                            bridgeToR_ProxyPropertyName,
                            vsv.versaCopy( thisTuple[ 0]),  ## here is the role name that we're reifying with this new r-proxy
                            triggers,
                            conferredValueSources)

                        newTupleList = [ r_proxy.proxyId, thisTuple[ 1]]  ## thisTuple[ 1] is the proxyId of the role player
                        thisTMAs_a_sip_instanceValue.append( tuple( newTupleList))

                else:
                    vsv.errMsg( 'This should never happen.  bridgeFromTMAModel == "%s"; bridgeToTMAModel == "%s".' % ( bridgeFromTMAModel, bridgeToTMAModel))
                    sys.exit( 1)

                vsv.newPropertyInstance( a_proxy,  ## set this TMA's a_sip to the same value
                                         TMA,
                                         'a_sip',
                                         vsv.versaCopy( thisTMAs_a_sip_instanceValue),
                                         triggers,
                                         conferredValueSources)


def bridgeAcross_t_sip_Models( vsv, conferralRule, **args):
    ## from bridgeFromTMAName,,t_sip properties, infer t_sip
    ## properties in the conferralRule's TMA.  (With all that that
    ## entails.)

    bridgeFromTMAName = args[ 'bridgeFromTMAName']

    topicMap = conferralRule.topicMap  ## make the below code less verbose (and maybe run slightly faster)
    TMA = conferralRule.TMA  ## this is the TMA that defines this conferral rule
    bridgeFromTMA = topicMap.TMAs[ bridgeFromTMAName]
    bridgeFrom_t_sip_overheadDict = bridgeFromTMA.propertyClasses[ 't_sip'].overheadDict

    t_sip_hashableValueList = bridgeFrom_t_sip_overheadDict.keys()

    for t_sip_hashableValue in t_sip_hashableValueList:

        t_proxyIdList = vsv.versaCopy( bridgeFrom_t_sip_overheadDict[ t_sip_hashableValue])

        for t_proxyId in t_proxyIdList:

            t_proxy = topicMap.proxies[ t_proxyId]
            t_sip_instance = t_proxy.propertyInstances[ vsv.catKey( bridgeFromTMA.TMAName, 't_sip')]

            ## Don't be triggered by an t_sip_instance property more
            ## than once, and don't be triggered by any t_sip_instance
            ## that was output by an operation of this rule
            conferralRuleTriggerRoleId = vsv.catKey( conferralRule.conferralRuleKey, 't_sip value')
            if t_sip_instance.conferralTriggerAncestry.has_key( conferralRuleTriggerRoleId) or \
                   t_sip_instance.conferralsTriggered.has_key( conferralRuleTriggerRoleId):
                continue

            triggers = {}  ## new dictionary to work in
            triggers[ 't_sip value'] = t_sip_instance.propertyInstanceKey
            conferredValueSources = {}  ## new dictionary to work in
            conferredValueSources[ 't_sip value'] = t_sip_instance.propertyInstanceKey

            if vsv.conferralMayBeSignificant( conferralRule, triggers, conferredValueSources):

                ## new t_proxy
                t_proxy = vsv.newProxyObject( topicMap)

                vsv.newPropertyInstance( t_proxy,  ## copy the existing t_proxy's t_sip
                                         bridgeFromTMA,
                                         't_sip',
                                         vsv.versaCopy( t_sip_instance._value),
                                         triggers,
                                         conferredValueSources)

                vsv.newPropertyInstance( t_proxy,  ## set this TMA's t_sip to the same value
                                         TMA,
                                         't_sip',
                                         vsv.versaCopy( t_sip_instance._value),
                                         triggers,
                                         conferredValueSources)


def bridgeFromU_assert( vsv, conferralRule, **args):
    ## from bridgeFromTMAName,,x_LrnRrnRrp properties, infer a_sip
    ## properties in the conferralRule's TMA.  (With all that that
    ## entails.)

    u_assertTMAName = args[ 'bridgeFromTMAName']
    rolesTMAName = args[ 'rolesTMAName']
    roleNamePropertyClassName = args[ 'roleNamePropertyClassName']
    u_assertPropertyName = 'x_LrnRrnRrp'

    topicMap = conferralRule.topicMap
    TMA = conferralRule.TMA  ## this is the TMA that defines this conferral rule
    rolesTMA = topicMap.TMAs[ rolesTMAName]
    u_assertTMA = topicMap.TMAs[ u_assertTMAName]
    proxyIdList = u_assertTMA.propertyClasses[ u_assertPropertyName].overheadDict[ 'proxyIds'].keys()
    u_assertPropertyInstanceInProxyKey = vsv.catKey( u_assertTMAName, u_assertPropertyName)

    existingRoleDict = rolesTMA.propertyClasses[ 'role name'].overheadDict

    for proxyId in proxyIdList:

        proxy = topicMap.proxies[ proxyId]

        u_assertProperty = proxy.propertyInstances[ u_assertPropertyInstanceInProxyKey]

        ## Don't be triggered by a u_assert property more than once
        conferralRuleTriggerRoleId = vsv.catKey( conferralRule.conferralRuleKey, 'A')
        if u_assertProperty.conferralTriggerAncestry.has_key( conferralRuleTriggerRoleId) or \
               u_assertProperty.conferralsTriggered.has_key( conferralRuleTriggerRoleId):
            continue

        triggers = {}  ## new dictionary to work in
        triggers[ 'A'] = u_assertProperty.propertyInstanceKey
        conferredValueSources = {}  ## new dictionary to work in
        conferredValueSources[ 'A'] = u_assertProperty.propertyInstanceKey

        if vsv.conferralMayBeSignificant( conferralRule, triggers, conferredValueSources):

            dict1 = u_assertProperty._value

            for dict1Key in dict1:
                localRoleName = dict1Key
                localRoleProxyId = existingRoleDict[ localRoleName][ 0]
                dict2 = dict1[ dict1Key]
                for dict2Key in dict2:
                    remoteRoleName = dict2Key
                    remoteRoleProxyId = existingRoleDict[ remoteRoleName][ 0]
                    stringList = dict2[ dict2Key]
                    for remoteProxyId in stringList:


                        ## new a_proxy
                        a_proxy = vsv.newProxyObject( topicMap)

                        vsv.newPropertyInstance( a_proxy,  ## set this TMA's t_sip to the same value
                                                 TMA,
                                                 'a_sip',
                                                 [ ( localRoleProxyId, proxyId), ( remoteRoleProxyId, remoteProxyId)],
                                                 triggers,
                                                 conferredValueSources)

