#####################################################################
#####################################################################
## Versavant Topic Map Application Bus / Subject Addressing Engine ##
## 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 $" ##
####################################


#############################################
## "proxyIdList" value type implementation ##
#############################################

## This value type is useful for storing references to proxies,
## regardless of whether they are treated by the property classes that
## use this value type are lists or sets.  For example, you should use
## this "proxyIdList" value type for both "proxyIdSet"-type property
## classes and "proxyIdList"-type property classes.  At this level,
## it doesn't matter.

## Values are lists of proxyIds, i.e., proxy.proxyId values, which are
## always strings of decimal digits that begin with two zeroes.

## When you create other value types that contain proxy references,
## you can use this implementation as a guide.  It's tricky to
## manage proxy references, not only because they die when merged, but
## also because they can't possibly retain their original IDs when
## they are imported.

## NOTE: During importation of instances of this value type from XML,
## some recordkeeping is done in vsv.currentTopicMapHoldingDict[
## 'IoMapsDict'][ (TMA name)][ propertyClassName].  

import types, traceback

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

    if not isinstance( propertyValue, types.ListType):
        traceback.print_stack()
        if propertyInstance:
            vsv.errMsg( 'Value "%s" of property %s is not a list.' % ( propertyValue, propertyInstance.propertyInstanceKey))
        else:
            vsv.errMsg( 'Value "%s" of a prospective %s property is not a list.' % ( propertyValue, vsv.catKey( TMAName, propertyClassName)))
        return True

    for proxyId in propertyValue:
        if not isinstance(proxyId, types.StringType):
            if propertyInstance:
                vsv.errMsg( 'An item ("%s") in the value of property %s is not a string.' % ( proxyId, propertyInstance.propertyInstanceKey))
            else:
                vsv.errMsg( 'An item ("%s") in the value of a presumptive %s property is not a string.' % ( proxyId, vsv.catKey( TMAName, propertyClassName)))
            return True
        if not vsv.proxyIdStrValidatorRE.match( proxyId):
            if propertyInstance:
                vsv.errMsg( 'An item ("%s") in the value of property %s does not look like a proxy identifier string.' % ( proxyId, propertyInstance.propertyInstanceKey))
            else:
                vsv.errMsg( 'An item ("%s") in the value of a presumptive %s property does not look like a proxy identifier string.' % ( proxyId, vsv.catKey( TMAName, propertyClassName)))
            return True

        proxy = vsv.isProxyId( proxyId, topicMap)
        if not proxy:
            if proxyId not in vsv.currentTopicMapHoldingDict[ 'IoMapsDict'][ 'TMAs'][ propertyInstance.TMAName][ propertyClassName]:
                   ## We're probably in the process of importing a topic map, and these are
                   ## references to proxies that don't exist yet because they haven't been imported
                   ## yet.  The above check is supposed to calm our fears that this proxy reference
                   ## is invalid, giving us reason to believe that it will soon be valid, even
                   ## though it's not quite valid yet.

                if propertyInstance:
                    errString = 'An item ("%s") in the list is not the ID of any proxy in topic map "%s".' % ( proxyId, propertyInstance.topicMap.topicMapName)
                else:
                    errString = 'An item ("%s") in the list is not the ID of any proxy in any open topic map.' % ( proxyId)
                vsv.errMsg( errString)
                return True
        if proxy:
            if proxy.forwardTo:
                vsv.errMsg( 'An item ("%s") in the list that is the value of property %s is the ID of a dead proxy.  Only the IDs of living proxies are permitted.' % ( proxyId, propertyInstance.topicMap.topicMapName))
                return True

    return False  ## all's well, presumably.                    

#######################################################
def InstanceOf_proxyIdList_ValueTypeToXMLContentString(vsv, propertyInstance):
    return vsv.cPickleDumpObjectAsXMLContentString( propertyInstance._value)

#######################################################
def XMLContentStringToInstanceOf_proxyIdList_ValueType(vsv, string, propertyClass, **args):
    ## Import a list of proxy references, adjusting them as necessary to
    ## the new proxyIds of the imported proxies to which they refer.

    oldProxyIdList = vsv.cPickleLoadObjectFromXMLContentString( string)

    mem2xmlProxyIdDict = vsv.currentTopicMapHoldingDict[ 'IoMapsDict'][ 'ProxyIds.mem2xml']
        ## This dictionary allows us to look up the in-xml element id of a
        ## proxy, given the proxy's proxyId as it was in the topic map
        ## from which the proxy was exported as xml.

    firstImportedProxyId = vsv.firstImportedProxyId
        ## This is an integer which, if we were to convert it into a
        ## string of decimal digits with 2 prepended zero characters,
        ## would be the proxyId of the first (the first, that is, not
        ## counting the proxies created in order to register the TMAs
        ## of the xml topic map being imported) in-memory proxy to be
        ## imported into the being-imported-into topic map from the
        ## xml topic map that we're importing.

    propertyClassName = propertyClass.propertyClassName
    TMAName = propertyClass.TMA.TMAName

    newProxyIdList = []

    for oldProxyId in oldProxyIdList:
        xmlProxyNum = mem2xmlProxyIdDict[ int( oldProxyId)]
        newProxyNum = (xmlProxyNum + firstImportedProxyId) - 1
        newProxyId = '00%s' % ( newProxyNum)
        newProxyIdList.append( newProxyId)

        appDict = vsv.currentTopicMapHoldingDict[ 'IoMapsDict'][ 'TMAs'][ TMAName]
        if not appDict.has_key( propertyClassName):
            appDict[ propertyClassName] = [ newProxyId]
        else:
            if newProxyId not in appDict[ propertyClassName]:
                appDict[ propertyClassName].append( newProxyId)
    ## vsv.IoMapsDict[ args[ 'TMAName']][ propertyClassName] will be consulted by
    ## the ValueIsNotOfType__() function in order to avoid a logical logjam over this.
    ## The logical logjam is that we're referring to proxies that haven't been imported
    ## yet, and the ValueIsNotOfType__() function checks to see that the proxy references are valid.
    ## This gives the ValueIsNotOfType__() function something to fall back on, as it checks.
    ## See that function, above, for more.

    return newProxyIdList

