#####################################################################
#####################################################################
## 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.5 $" ##
####################################


import sys


#######################################
## proxyIdList PC implementation ##
#######################################

## NOTE: use the "proxyIdSet" functions for *sets* of proxy ids.
##       The below "proxyIdList" functions are for lists of proxy ids
##       in which the order must be preserved.

## These functions are useful as implementations of SIPs or OPs whose
## values are lists of references to proxies.  Obviously, the name
## "proxyIdList" only applies to these (library) functions; TMA
## designers can use any name(s) for such properties.

#######################################################
def Add_proxyIdList_PropToOverheadDict( vsv, propertyInstance, overheadDict):
    value = propertyInstance._value
    hashablePropertyValue = propertyInstance.hashablePropertyValue = tuple( value)

    if overheadDict.has_key( hashablePropertyValue):
        if propertyInstance.proxyId not in overheadDict[ hashablePropertyValue]:
            overheadDict[ hashablePropertyValue].append( propertyInstance.proxyId)
    else:
        overheadDict[ hashablePropertyValue] = [ propertyInstance.proxyId]

    workDict = {}
    for member in value:
        workDict[ member] = None
    propertyInstance.listOfIdsOfReferencedProxies = workDict.keys()
    vsv.addNewProxyReferencesToReferencedProxiesDict( propertyInstance)

#######################################################
def Remove_proxyIdList_PropFromOverheadDict( vsv, propertyInstance, overheadDict):
    hashablePropertyValue = propertyInstance.hashablePropertyValue
    if not overheadDict.has_key( hashablePropertyValue):
        vsv.errMsg( 'No entry in overheadDict of property class for the value (%s) of property %s' % (
            propertyInstance._value,
            vsv.catKey( propertyInstance.topicMap.topicMapName, propertyInstance.propertyInstanceKey)))
        sys.exit( 1)

    if propertyInstance.proxyId not in overheadDict[ hashablePropertyValue]:
        vsv.errMsg( 'ProxyId %s not found in the overheadDict of property class for the value (%s) of property %s' % (
            propertyInstance.proxyId,
            propertyInstance._value,
            vsv.catKey( propertyInstance.topicMap.topicMapName, propertyInstance.propertyInstanceKey)))
        sys.exit( 1)

    overheadDict[ hashablePropertyValue].remove( propertyInstance.proxyId)
    if not len( overheadDict[ hashablePropertyValue]):
        del overheadDict[ hashablePropertyValue]

    vsv.removeOldProxyReferencesFromReferencedProxiesDict( propertyInstance)

#######################################################
def Merge_proxyIdList_PropertyValues( vsv, value1, value2):
    if value1 == value2:
        return value1
    else:
        return None  ## merge is unsuccessful

#######################################################
def ValuesOf_proxyIdList_PropertyInstancesAreSignificantlyDifferent( vsv, value1, value2):
    if value1 != value2:
        return True
    return False

#######################################################
def MergeProxiesBecause_proxyIdList_PropertyInstancesSpecifySameSubject( vsv, propertyClass):
    for key in propertyClass.overheadDict:
        if len( propertyClass.overheadDict[ key]) > 1:
            vsv.mergeListOfProxies( propertyClass, propertyClass.overheadDict[ key])

#######################################################
def ProxiesOfSubjectIdentifiedBy_proxyIdList_Value( vsv, propertyClass, value):
    hashableValue = tuple( value)
    if propertyClass.overheadDict.has_key( hashableValue):
        return propertyClass.overheadDict[ hashableValue]
    else:
        return []  ## empty list -- no match

#######################################################
def UpdateProxyReferencesIn_proxyIdList_Value( vsv, propertyInstance, proxyIdToReplace, replacementProxyId):

    oldValue = propertyInstance._value

    workDict = {}
    newList = []
    foundProxyIdToReplace = False
    for oldItem in oldValue:
        if oldItem == proxyIdToReplace:
            newList.append( replacementProxyId)
            workDict[ replacementProxyId] = None
            foundProxyIdToReplace = True
        else:
            newList.append( oldItem)
            workDict[ oldItem] = None


    if not foundProxyIdToReplace:
        vsv.errMsg( 'Did not find reference to proxy %s in propertyInstance %s; value == %s.' % ( proxyIdToReplace, propertyInstance.propertyInstanceKey, propertyInstance._value))
        sys.exit( 1)

    propertyClass = propertyInstance.propertyClass

    ## Remove old value from the "overhead" data for this property class
    if propertyClass.Remove__PropFromOverheadDictFArgString:
        execStr = 'propertyClass.Remove__PropFromOverheadDictF( vsv, propertyInstance, propertyClass.overheadDict, %s)' % (
            propertyClass.Remove__PropFromOverheadDictFArgString)
        exec execStr
    else:
        propertyClass.Remove__PropFromOverheadDictF( vsv, propertyInstance, propertyClass.overheadDict)

    ## Replace the old value with the new one
    del oldValue[:]
    oldValue.extend( newList)
        
    ## Expose the list of proxy references that appear in the value as a list of proxyIds
    propertyInstance.listOfIdsOfReferencedProxies = workDict.keys()

    ## Add new value to the "overhead" data for this property class  (This will set propertyInstance.hashableValue, too!)
    if propertyClass.Add__PropToOverheadDictFArgString:
        execStr = 'propertyClass.Add__PropToOverheadDictF( vsv, propertyInstance, propertyClass.overheadDict, %s)' % (
            propertyClass.Add__PropToOverheadDictFArgString)
        exec execStr
    else:
        propertyClass.Add__PropToOverheadDictF( vsv, propertyInstance, propertyClass.overheadDict)



