#####################################################################
#####################################################################
## 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                                 ##
#####################################################################
#####################################################################

####################################
cvsRevision = "$Revision: 1.2 $" ##
####################################


import sys

#################################################################
## a_sip PC implementation                                     ##
## (mostly it's in ${VSVEXECDIR}/Lib/PCsetOfString_ProxyRefTuples.py, ##
#################################################################

#######################################################
def ValueIsInvalidFor_a_sip_Property( vsv, propertyValue, propertyClass, propertyInstance = None, **args):
    TMAName = propertyClass.TMA.TMAName
    topicMap = propertyClass.topicMap

    if len( propertyValue) < 2:
        if propertyInstance:
            vsv.errMsg( 'Value of %s property contains %d tuples; should have at least two tuples.  A relationship must have at least two roles, even if some of them are unplayed.' % ( propertyInstance.propertyInstanceKey, len( propertyValue)))
        else:
            vsv.errMsg( 'Value of %s presumptive property contains %d tuples; should have at least two tuples.  A relationship must have at least two roles, even if some of them are unplayed.' % ( vsv.catKey( TMAName, propertyClass), len( propertyValue)))
        return True

    foundDuple = False
    for tuple in propertyValue:
        memberCount = len( tuple)
        if memberCount == 2:
            foundDuple = True
        elif memberCount == 1:
            pass
        else:
            if propertyInstance:
                vsv.errMsg( 'Tuple in %s property\'s value has %d members; should have 1 (an unplayed role name) or 2 (a role name and a role player).' % ( propertyInstance.propertyInstanceKey, memberCount))
            else:
                vsv.errMsg( 'Tuple in presumptive %s property\'s value has %d members; should have 1 (an unplayed role name) or 2 (a role name and a role player).' % ( vsv.catKey( TMAName, propertyClass.propertyClassName), memberCount))
            return True
        memberNumber = 0
        roleNameDict = {}
        for member in tuple:
            memberNumber += 1

            if memberNumber == 1:
                roleName = member
                if vsv.looksLikeProxyId( member):
                    bool, proxyIdLookalikeREString = vsv.looksLikeProxyId( member)
                    if propertyInstance:
                        vsv.errMsg( 'member %s of tuple "%s" ("%s") of %s property is bad because it looks like a proxyId.  Role names cannot match the regular expression "%s".' % ( memberNumber, tuple, member, propertyInstance.propertyInstanceKey, proxyIdLookalikeREString))
                    else:
                        vsv.errMsg( 'member %s of tuple "%s" ("%s") of presumptive %s property is bad because it looks like a proxyId.  Role names cannot match the regular expression "%s".' % ( memberNumber, tuple, member, vsv.catKey( propertyClass.TMA.TMAName, propertyClass.propertyClassName), proxyIdLookalikeREString))
                    return True
                    
                if roleNameDict.has_key( member):
                    if propertyInstance:
                        vsv.errMsg( 'multiple appearances of the same role name (%s) in property %s.  No role name can be used more than once in any given assertion.' % ( member, propertyInstance.propertyInstanceKey))
                    else:
                        vsv.errMsg( 'multiple appearances of the same role name (%s) in presumptive property %s.  No role name can be used more than once in any given assertion.' % ( member, vsv.catKey( TMAName, propertyClass.propertyClassName)))
                    return True
                roleNameDict[ member] = None

            elif memberNumber == 2:  ## this should be a reference to an x_proxy
                proxy = vsv.isProxyId( member, topicMap)
                if not proxy:
                    if propertyInstance:
                        vsv.errMsg( 'Tuple in value of %s property has as its second member "%s", which is not a proxyId.' % ( propertyInstance.propertyInstanceKey, member))
                    else:
                        vsv.errMsg( 'Tuple in value of presumptive %s property has as its second member "%s", which is not a proxyId.' % ( vsv.catKey( TMAName, propertyClass.propertyClassName), member))
                    return True
                if proxy.forwardTo:
                    if propertyInstance:
                        vsv.errMsg( 'Tuple in value of %s property as its second member "%s", which is the proxyId of a dead proxy.' % ( propertyInstance.propertyInstanceKey, member))
                    else:
                        vsv.errMsg( 'Tuple in value of presumptive %s property has as its second member "%s", which is the proxyId of a dead proxy.' % ( vsv.catKey( TMAName, propertyClass.propertyClassName), member))
                    return True

                if not vsv.currentProcOperation:
                    found_x_roles_property = False
                    for propertyInstanceKey2 in proxy.propertyInstances:
                        tmaName, checkablePropertyClassName = vsv.parsePropertyKey2( propertyInstanceKey2)
                        if TMAName == tmaName:
                            if checkablePropertyClassName == 'x_roles':
                                found_x_roles_property = True
                                foundRoleName = False
                                for thatTuple in propertyInstance._value:
                                    if thatTuple[ 0] == roleName:
                                        foundRoleName = True
                                        break
                                if not foundRoleName:
                                    if propertyInstance:
                                        vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of %s property has an x_roles property that does not mention the role name "%s" which is the first member of the tuple.' % ( thisTuple, propertyInstance.propertyInstanceKey, roleName))
                                    else:
                                        vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of presumptive %s property has an x_roles property that does not mention the role name "%s" which is the first member of the tuple.' % ( thisTuple, vsv.catKey( TMAName, propertyClass.propertyClassName), roleName))
                                    return True
                    if ( not found_x_roles_property):
                        if propertyInstance:
                            vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of %s property has no x_roles property.' % ( thisTuple, propertyInstance.propertyInstanceKey))
                        else:
                            vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of presumptive %s property has no x_roles property.' % ( thisTuple, vsv.catKey( TMAName, propertyClass.propertyClassName)))
                        return True

    if not foundDuple:
        if propertyInstance:
            vsv.errMsg( 'No tuple in value of %s property has 2 members.  There must be at least one tuple that has two members; a relationship between nothing and nothing is not a relationship.' % ( propertyInstance.propertyInstanceKey))
        else:
            vsv.errMsg( 'No tuple in value of presumptive %s property has 2 members.  There must be at least one tuple that has two members; a relationship between nothing and nothing is not a relationship.' % ( vsv.catKey( TMAName, propertyClass.propertyClassName)))
        return True

    return False




###########################################
## x_roles PC implementation               ##
## (mostly re-uses ${VSVEXECDIR}/Lib/PCsetOfString_ProxyRefTuples) ##
###########################################

#######################################################
def ValueIsInvalidFor_x_roles_Property( vsv, propertyValue, propertyClass, propertyInstance = None, **args):
    a_proxy_allowed_properties = args[ 'a_proxy_allowed_properties']
    TMAName = propertyClass.TMA.TMAName
    topicMap = propertyClass.topicMap

    for thisTuple in propertyValue:
        memberCount = len( thisTuple)
        if memberCount != 2:
            if propertyInstance:
                vsv.errMsg( 'Tuple in %s property\'s value has %d members; should have 2 (a role name and a relationship).' % ( propertyInstance.propertyInstanceKey, memberCount))
            else:
                vsv.errMsg( 'Tuple in presumptive %s property\'s value has %d members; should have 2 (a role name and a relationship).' % ( vsv.catKey( TMAName, propertyClass.propertyClassName), memberCount))
            return True
        memberNumber = 0
        for member in thisTuple:
            memberNumber += 1
            if memberNumber == 1:  ## this should be a roleName
                roleName = member
            else:                  ## memberNumber == 2; this should be a reference to an a-proxy
                proxy = vsv.isProxyId( member, topicMap)
                if not proxy:
                    if propertyInstance:
                        vsv.errMsg( 'Tuple in value of %s property has as its second member "%s", which is not a proxyId.' % ( propertyInstance.propertyInstanceKey, member))
                    else:
                        vsv.errMsg( 'Tuple in value of presumptive %s property has as its second member "%s", which is not a proxyId.' % ( vsv.catKey( TMAName, propertyClass.propertyClassName), member))
                    return True
                if proxy.forwardTo:
                    if propertyInstance:
                        vsv.errMsg( 'Tuple in value of %s property as its second member "%s", which is the proxyId of a dead proxy.' % ( propertyInstance.propertyInstanceKey, member))
                    else:
                        vsv.errMsg( 'Tuple in value of presumptive %s property has as its second member "%s", which is the proxyId of a dead proxy.' % ( vsv.catKey( TMAName, propertyClass.propertyClassName), member))
                    return True

                if not vsv.currentProcOperation:
                    found_a_sip_property = False
                    for propertyInstanceKey2 in proxy.propertyInstances:
                        tmaName, checkablePropertyClassName = vsv.parsePropertyKey2( propertyInstanceKey2)
                        if TMAName == tmaName:
                            if checkablePropertyClassName not in a_proxy_allowed_properties:
                                if propertyInstance:
                                    vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of %s property value has a "%s" property, which, as an a-proxy, it should not have.' % ( thisTuple, propertyInstance.propertyInstanceKey, checkablePropertyClassName))
                                else:
                                    vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of presumptive %s property value has a "%s" property, which, as an a-proxy, it should not have.' % ( thisTuple, vsv.catKey( TMAName, propertyClass.propertyClassName), checkablePropertyClassName))
                                return True
                            if checkablePropertyClassName == 'a_sip':
                                found_a_sip_property = True
                                foundRoleName = False
                                for thatTuple in propertyInstance._value:
                                    if thatTuple[ 0] == roleName:
                                        foundRoleName = True
                                        break
                                if not foundRoleName:
                                    if propertyInstance:
                                        vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of %s property has an a_sip property that does not mention the role name "%s" which is the first member of the tuple.' % ( thisTuple, propertyInstance.propertyInstanceKey, roleName))
                                    else:
                                        vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of presumptive %s property has an a_sip property that does not mention the role name "%s" which is the first member of the tuple.' % ( thisTuple, vsv.catKey( TMAName, propertyClass.propertyClassName), roleName))
                                    return True
                    if not found_a_sip_property:
                        if propertyInstance:
                            vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of %s property has no a_sip property.' % ( thisTuple, propertyInstance.propertyInstanceKey))
                        else:
                            vsv.errMsg( 'Proxy referenced as second member of tuple "%s" in value of presumptive %s property has no a_sip property.' % ( thisTuple, vsv.catKey( TMAName, propertyClass.propertyClassName)))
                        return True

    return False



