RelationshipManipulation.py :  » Database » Modeling-Framework » Modeling-0.9 » Modeling » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Database » Modeling Framework 
Modeling Framework » Modeling 0.9 » Modeling » RelationshipManipulation.py
# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------


"""
Allows the generic manipulation of objects in relation by inspecting the
underlying model and taking appropriate actions.

  This modules consists of two parts:

    - module functions implementing the default behaviour for the API
  
    - a mix-in class using this default implementation
  
  See interfaces.RelationshipManipulating for a full description of the
  default implementation.

  CVS information

    $Id: RelationshipManipulation.py 932 2004-07-20 06:21:57Z sbigaret $

"""


__version__='$Revision: 932 $'[11:-2]

from logging import warn

# Framework
from Modeling.utils import capitalizeFirstLetter

# interfaces
from interfaces.RelationshipManipulation import RelationshipManipulationInterface

def addObjectToBothSidesOfRelationshipWithKey(self, anObject, aKey):
  "See interfaces.RelationshipManipulating"
  toOnes  = self.classDescription().toOneRelationshipKeys()
  toManys = self.classDescription().toManyRelationshipKeys()
  if aKey not in toOnes+toManys:
    raise TypeError, "Key %s is not a relationship's key"%aKey
    
  ## First step: update this side
  ##
  if aKey in toManys:
    _addObjectToPropertyWithKey(self, anObject, aKey, toOnes, toManys)
  else:
    # toOne relationship: is it already set?
    _selfRelObj=self.valueForKey(aKey)
    if _selfRelObj: # Yes: now remove it
      _removeObjectFromBothSidesOfRelationshipWithKey(self, _selfRelObj, aKey,
                                                      toOnes, toManys)
    _addObjectToPropertyWithKey(self, anObject, aKey, toOnes, toManys)
  
  ## Second step: update the other side
  ##
  _backRelKey=self.inverseForRelationshipKey(aKey)
  if _backRelKey is None: return
  
  otoOnes  = anObject.classDescription().toOneRelationshipKeys()
  otoManys = anObject.classDescription().toManyRelationshipKeys()

  destClassDesc=self.classDescription().\
                 classDescriptionForDestinationKey(aKey)
  if _backRelKey in destClassDesc.toManyRelationshipKeys():
    _addObjectToPropertyWithKey(anObject, self, _backRelKey, otoOnes, otoManys)
  else:
    # toOne relationship: is it already set?
    _backRelObj=anObject.valueForKey(_backRelKey)
    #if _backRelObj and _backRelObj.persistentID()!=self.persistentID():
    if _backRelObj and _backRelObj!=self:
      # Yes: now remove it
      _removeObjectFromBothSidesOfRelationshipWithKey(anObject, _backRelObj, _backRelKey, otoOnes, otoManys)
    _addObjectToPropertyWithKey(anObject, self, _backRelKey, otoOnes, otoManys)

def addObjectToPropertyWithKey(self, anObject, aKey):
  "See interfaces.RelationshipManipulating"
  toOnes  = self.classDescription().toOneRelationshipKeys()
  toManys = self.classDescription().toManyRelationshipKeys()
  return _addObjectToPropertyWithKey(self, anObject, aKey, toOnes, toManys)
  
def removeObjectFromBothSidesOfRelationshipWithKey(self, anObject, aKey):
  "See interfaces.RelationshipManipulating"
  toOnes  = self.classDescription().toOneRelationshipKeys()
  toManys = self.classDescription().toManyRelationshipKeys()
  return _removeObjectFromBothSidesOfRelationshipWithKey(self, anObject, aKey,
                                                         toOnes, toManys)

def removeObjectFromPropertyWithKey(self, anObject, aKey):
  "See interfaces.RelationshipManipulating"
  toOnes  = self.classDescription().toOneRelationshipKeys()
  toManys = self.classDescription().toManyRelationshipKeys()
  return _removeObjectFromPropertyWithKey(self,anObject,aKey,toOnes,toManys)

def _addObjectToPropertyWithKey(self, anObject, aKey, toOnes, toManys):
  """
  Private method used by the methods in this module to avoid the
  re-computation of to-one and to-many relationships when it is not necessary.

  Parameters are the same as for addObjectToPropertyWithKey, with the
  additional parameters:

    toOnes -- should equal to
      self.classDescription().toOneRelationshipKeys()

    toManys -- should equal to
      self.classDescription().toManyRelationshipKeys()
    
  """
  if aKey not in toOnes+toManys:
    raise ValueError, "Key %s is not a relationship's key"%aKey
  if aKey in toOnes:
    # toOne: Simply uses KVC
    self.takeValueForKey(anObject, aKey)
  else:
    # toMany: search addToKey
    Key=capitalizeFirstLetter(aKey)
    setter=getattr(self, 'addTo'+Key, None)  # addToKey()
    if callable(setter):
      apply(setter, (anObject,))
      return
    # addToKey not found: apply changes on the (sequence) variable directly
    values=list(self.valueForKey(aKey))
    if anObject not in values:
      values.append(anObject)
    self.takeValueForKey(tuple(values), aKey)

def _removeObjectFromBothSidesOfRelationshipWithKey(self, anObject, aKey,
                                                    toOnes, toManys):
  """
  Private method used by the methods in this module to avoid the
  re-computation of to-one and to-many relationships when it is not necessary.

  Parameters are the same as for
  removeObjectFromBothSidesOfRelationshipWithKey, with the additional
  parameters:

    toOnes -- should equal to self.classDescription().toOneRelationshipKeys()

    toManys -- should equal to
      self.classDescription().toManyRelationshipKeys()
    
  """
  if anObject is None:
    warn('removeObjectFromBothSidesOfRelationshipWithKey', \
          'called w/ anObject==None')
    return
  
  if aKey not in toOnes+toManys:
    raise ValueError, "Key %s is not a relationship"%aKey
    
  ## First step: update this side
  ##
  if aKey in toManys:
    _removeObjectFromPropertyWithKey(self,anObject, aKey, toOnes, toManys)
  else:
    # toOne: check this is the one!
    if self.valueForKey(aKey) != anObject:
      raise ValueError, 'anObject %s is not set for key %s'%(repr(anObject),
                                                             aKey)
    _addObjectToPropertyWithKey(self,None, aKey, toOnes,toManys)
  
  ## Second step: update the other side
  _backRelKey=self.inverseForRelationshipKey(aKey)
  if _backRelKey is None: return
  
  destClassDesc=self.classDescription().\
                 classDescriptionForDestinationKey(aKey)
  
  if _backRelKey in destClassDesc.toManyRelationshipKeys():
    try: # the other side may be unset
      anObject.removeObjectFromPropertyWithKey(self, _backRelKey)
    except ValueError:
      pass
  else:
    # toOne: do we need to check this is the one??
    #assert(anObject.objectForKey(_backRelKey).persistentID()==self.persistentID())
    anObject.addObjectToPropertyWithKey(None, _backRelKey)

def _removeObjectFromPropertyWithKey(self, anObject, aKey, toOnes, toManys):
  """
  Private method used by the methods in this module to avoid the
  re-computation of to-one and to-many relationships when it is not necessary.

  Parameters are the same as for removeObjectFromPropertyWithKey(), with the
  additional parameters:

    toOnes -- should equal to self.classDescription().toOneRelationshipKeys()

    toManys -- should equal to
      self.classDescription().toManyRelationshipKeys()
    
  """
  if aKey not in toOnes+toManys:
    raise ValueError, "Key %s is not a relationship's key"%aKey

  if aKey in toOnes:
    # toOne: Simply uses KVC
    if self.valueForKey(aKey)!=anObject:
      raise ValueError, 'anObject %s is not set for key %s'%(repr(anObject),
                                                             aKey)
    self.takeValueForKey(None, aKey)
  else:
    # toMany: search removeFromKey
    Key=capitalizeFirstLetter(aKey)
    setter=getattr(self, 'removeFrom'+Key, None)  # removeFromKey()
    if callable(setter):
      apply(setter, (anObject,))
      return
    #removeFromKey not found: apply changes on the (sequence) variable directly
    values=list(self.valueForKey(aKey))
    if anObject not in values:
      raise ValueError, 'anObject %s is not set for key %s'%(repr(anObject),
                                                             aKey)
    values.remove(anObject)
    self.takeValueForKey(tuple(values), aKey)

class RelationshipManipulation:
  """
  This mix-in class provides the default implementation for
  RelationshipManipulation interface to all subclasses.
  """

  __implements__=(RelationshipManipulationInterface,)

  def addObjectToBothSidesOfRelationshipWithKey(self, anObject, aKey):
    "See interfaces.RelationshipManipulating"
    addObjectToBothSidesOfRelationshipWithKey(self, anObject, aKey)
    
  def addObjectToPropertyWithKey(self, anObject, aKey):
    "See interfaces.RelationshipManipulating"
    addObjectToPropertyWithKey(self, anObject, aKey)

  def removeObjectFromBothSidesOfRelationshipWithKey(self, anObject, aKey):
    "See interfaces.RelationshipManipulating"
    removeObjectFromBothSidesOfRelationshipWithKey(self, anObject, aKey)
    
  def removeObjectFromPropertyWithKey(self, anObject, aKey):
    "See interfaces.RelationshipManipulating"
    removeObjectFromPropertyWithKey(self, anObject, aKey)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.