#! /usr/bin/env python
# ______________________________________________________________________
"""Module ANOIDimension
Jonathan Riehl
$Id: ANOIDimension.py,v 1.5 2005/01/19 00:42:09 jriehl Exp $
"""
# ______________________________________________________________________
# Module imports
import ANOIBaseSpace
import ANOITrie
import ANOITypes
# ______________________________________________________________________
# Module data
__DEBUG__ = False
# ______________________________________________________________________
# Class definition
class ANOIDimension (object):
"""Class ANOIDimension
Remember that POS is supposed to be the successor, so POS points to the
tail, while NEG points to the head.
"""
# ____________________________________________________________
def __init__ (self, space, rootNS, uid = None):
"""ANOIDimension.__init__()
"""
self.space = space
crossEq = self.space.crossEquals
self.rootTrie = ANOITrie.getNamespace(space, rootNS)
self.typeSystem = ANOITypes.ANOITypeManager(space, rootNS)
# Get navigational stuff.
self.posUid = self.typeSystem.getOrCreatePropertyKey("POS")
self.negUid = self.typeSystem.getOrCreatePropertyKey("NEG")
self.refUid = self.typeSystem.getOrCreatePropertyKey("REF")
self.parentUid = self.typeSystem.getOrCreatePropertyKey("PARENT")
# Get type stuff.
self.dimensionType = self.rootTrie.getName("ANOIDimensionType")
# Make sure the environment has the proper stuff.
if self.dimensionType == ANOIBaseSpace.NIL:
dType = self.typeSystem.createType("ANOIDimensionType")
self.dimensionType = dType
dnType = self.typeSystem.createType("ANOIDimensionNodeType")
self.dimensionNodeType = dnType
dSlots = {self.posUid : dnType,
self.negUid : dnType}
self.typeSystem.updateSlots(dType, dSlots)
dnSlots = {self.parentUid : dType,
self.posUid : dnType,
self.negUid : dnType,
self.refUid : self.typeSystem.atomType}
self.typeSystem.updateSlots(dnType,dnSlots)
else:
self.dimensionNodeType = self.rootTrie.getName(
"ANOIDimensionNodeType")
assert self.dimensionNodeType != ANOIBaseSpace.NIL
# Now see if this is a pre-existing dimension.
if uid == None:
# We've been asked to create a new dimension.
self.uid = self.typeSystem.createInstance(self.dimensionType)
else:
self.uid = uid
# ____________________________________________________________
def append (self, uid):
"""ANOIDimension.append()
"""
cross = self.space.cross
crossEq = self.typeSystem.safeCrossEquals
# Find the tail node
tailUid = self.getTail()
# Create the spine node
retVal = self.typeSystem.createInstance(self.dimensionNodeType)
crossEq(retVal, self.parentUid, self.uid)
crossEq(retVal, self.negUid, tailUid)
crossEq(retVal, self.refUid, uid)
crossEq(self.uid, self.posUid, retVal)
# XXX - Shouldn't one check to see if this UID is already in the
# dimension? Or can we just be happy with the contained atom
# referring to only the most recent spine node to reference it?
crossEq(uid, self.uid, retVal)
if tailUid == ANOIBaseSpace.NIL:
crossEq(self.uid, self.negUid, retVal)
else:
crossEq(tailUid, self.posUid, retVal)
return retVal
# ____________________________________________________________
def remove (self, uid):
"""ANOIDimension.remove()
NOTE - This method used to free the spine UID by calling
self.space.freeUid(spineUid). Currently, management of the unlinked
spine atom is left to the caller. Ideally some GC component would
work here.
"""
cross = self.space.cross
crossEq = self.typeSystem.safeCrossEquals
if cross(uid, self.typeSystem.typeAttr) == self.dimensionNodeType:
spineUid = uid
uid = cross(spineUid, self.refUid)
else:
spineUid = cross(uid, self.uid)
assert spineUid != ANOIBaseSpace.NIL, ("UID %d is not in the "
"dimension." % uid)
assert cross(spineUid, self.parentUid) == self.uid
prev = cross(spineUid, self.negUid)
next = cross(spineUid, self.posUid)
if prev != ANOIBaseSpace.NIL:
crossEq(prev, self.posUid, next)
else:
crossEq(self.uid, self.negUid, next)
if next != ANOIBaseSpace.NIL:
crossEq(next, self.negUid, prev)
else:
crossEq(self.uid, self.posUid, prev)
crossEq(uid, self.uid, ANOIBaseSpace.NIL)
return spineUid
# ____________________________________________________________
def getIter (self, start = None):
"""ANOIDimension.getIter()
"""
if start != None:
crntUid = start
# Make sure we're in the right dimension.
assert self.space.cross(start, self.parentUid) == self.uid
else:
crntUid = self.space.cross(self.uid, self.negUid)
while crntUid != ANOIBaseSpace.NIL:
yield crntUid
crntUid = self.space.cross(crntUid, self.posUid)
raise exceptions.StopIteration
# ____________________________________________________________
def getHead (self):
"""ANOIDimension.getHead()
"""
return self.space.cross(self.uid, self.negUid)
# ____________________________________________________________
def getTail (self):
"""ANOIDimension.getTail()
"""
return self.space.cross(self.uid, self.posUid)
# ______________________________________________________________________
# End of ANOIDimension.py