commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r7194 - in trunk/gnue-appserver/src: . gcd generator gld


From: johannes
Subject: [gnue] r7194 - in trunk/gnue-appserver/src: . gcd generator gld
Date: Sun, 13 Mar 2005 04:41:17 -0600 (CST)

Author: johannes
Date: 2005-03-13 04:41:15 -0600 (Sun, 13 Mar 2005)
New Revision: 7194

Added:
   trunk/gnue-appserver/src/repository.py
Removed:
   trunk/gnue-appserver/src/classrep/
Modified:
   trunk/gnue-appserver/src/data.py
   trunk/gnue-appserver/src/gcd/GCParser.py
   trunk/gnue-appserver/src/gcd/readgcd.py
   trunk/gnue-appserver/src/geasFilter.py
   trunk/gnue-appserver/src/geasGsdGen.py
   trunk/gnue-appserver/src/geasInstance.py
   trunk/gnue-appserver/src/geasRpcServer.py
   trunk/gnue-appserver/src/geasSession.py
   trunk/gnue-appserver/src/geasSessionManager.py
   trunk/gnue-appserver/src/generator/classdef.py
   trunk/gnue-appserver/src/generator/form.py
   trunk/gnue-appserver/src/gld/GLParser.py
   trunk/gnue-appserver/src/gld/readgld.py
Log:
Improved class repository (repository-rewrite) and fixed some memory leaks from 
SIGHUP


Modified: trunk/gnue-appserver/src/data.py
===================================================================
--- trunk/gnue-appserver/src/data.py    2005-03-13 10:03:11 UTC (rev 7193)
+++ trunk/gnue-appserver/src/data.py    2005-03-13 10:41:15 UTC (rev 7194)
@@ -146,7 +146,7 @@
     if dirty is None:
       # We could use self.__has (), here but avoiding an additional function
       # call here is a big deal regarding performance, as this function is
-      # called about 100000 times for a (quite small) classrepository
+      # called about 100000 times for a (quite small) class-repository
       return (self.__old.has_key (table) and self.__old [table].has_key (row) \
               and self.__old [table][row].has_key (field)) or \
              (self.__new.has_key (table) and self.__new [table].has_key (row) \

Modified: trunk/gnue-appserver/src/gcd/GCParser.py
===================================================================
--- trunk/gnue-appserver/src/gcd/GCParser.py    2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/gcd/GCParser.py    2005-03-13 10:41:15 UTC (rev 
7194)
@@ -26,7 +26,7 @@
 from gnue.common.definitions.GParserHelpers import GContent
 from gnue.common.formatting import GTypecast
 from gnue.common.apps import errors
-from gnue.appserver.classrep import helpers, Namespace
+from gnue.appserver import repository
 
 
 xmlElements   = None
@@ -277,11 +277,12 @@
       fieldType = self.type.lower ().strip ()
       tpMatch   = re.compile ('^(\w+)').match (fieldType)
       if tpMatch is None:
-        raise helpers.TypeNameError, (fieldType)
+        raise repository.TypeNameError, (fieldType)
 
       typename = tpMatch.groups () [0]
-      if not typename in helpers.BASE_TYPES and len (typename.split ('_')) != 
2:
-        raise helpers.TypeNameError, (fieldType)
+      if not repository.BASE_TYPES.has_key (typename) and \
+         len (typename.split ('_')) != 2:
+        raise repository.TypeNameError, (fieldType)
 
       # try to extract length and scale from fieldType
       lsMatch = _LENGTH_SCALE.match (fieldType)
@@ -298,8 +299,8 @@
             raise DuplicateDefinitionError, (self.name, False)
           self.scale = int (sstr)
 
-      if typename in helpers.BASE_TYPES:
-        helpers.verifyBasetype (typename, self.length, self.scale)
+      if repository.BASE_TYPES.has_key (typename):
+        repository.verifyBasetype (typename, self.length, self.scale)
       else:
         if not self._refsAllowed:
           raise ReferenceNotAllowedError, (typename, self._type, self.name)
@@ -307,14 +308,14 @@
         self.isReference = True
 
         if self.length:
-          raise helpers.TypeFormatError, \
+          raise repository.TypeFormatError, \
               u_("Reference type '%s' must not have a length") % typename
         if self.scale:
-          raise helpers.TypeFormatError, \
+          raise repository.TypeFormatError, \
               u_("Reference type '%s' must not have a scale") % typename
 
-        typename = 'string'
-        self.length = 32
+        typename    = repository.REF_TYPE
+        self.length = repository.REF_LENGTH
 
       self.datatype = typename
 
@@ -378,7 +379,7 @@
     if self.module != self._parent.name:
       self.action = 'extend'
 
-    self.fullName = Namespace.createName (self.module, self.name)
+    self.fullName = repository.createName (self.module, self.name)
 
 
   # ---------------------------------------------------------------------------
@@ -399,7 +400,7 @@
           pType = 'string', length = 8, nullable = True)
 
       if hasattr (self, 'filter'):
-        (fModule, fName) = Namespace.splitName (self.filter)
+        (fModule, fName) = repository.splitName (self.filter)
         self.__addProperty (fName, module = fModule)
 
 
@@ -428,6 +429,11 @@
 
         self._children.remove (prop)
 
+        # Release references of the no longer needed property instance (for gc)
+        del prop._inits [:]
+        prop._parent = None
+
+
   # ---------------------------------------------------------------------------
   # Add a property to the class
   # ---------------------------------------------------------------------------
@@ -436,7 +442,7 @@
       length = None, nullable = False):
     items = [c.fullName for c in self.findChildrenOfType ('GCProperty')]
 
-    fullName = Namespace.createName (module, name)
+    fullName = repository.createName (module, name)
     if fullName in items:
       return None
 
@@ -477,7 +483,7 @@
   def _validate (self):
     GCTypeDefinition._validate (self)
     self.module   = self.findParentOfType ('GCModule').name
-    self.fullName = Namespace.createName (self.module, self.name)
+    self.fullName = repository.createName (self.module, self.name)
 
 
 # =============================================================================
@@ -498,7 +504,7 @@
   def _validate (self):
     GCTypeDefinition._validate (self)
     self.module   = self.findParentOfType ('GCModule').name
-    self.fullName = Namespace.createName (self.module, self.name)
+    self.fullName = repository.createName (self.module, self.name)
 
 
 # =============================================================================
@@ -525,7 +531,7 @@
 
   def _complete (self):
     self.module     = self.findParentOfType ('GCModule').name
-    self.fullName   = "ix_%s" % Namespace.createName (self.module, self.name)
+    self.fullName   = "ix_%s" % repository.createName (self.module, self.name)
     self.fields     = self.findChildrenOfType ('GCIndexField')
 
   def _getFieldNames (self):
@@ -543,7 +549,7 @@
   def _complete (self):
     if not '_' in self.name:
       self.module   = self._parent.module
-      self.fullName = Namespace.createName (self.module, self.name)
+      self.fullName = repository.createName (self.module, self.name)
     else:
-      self.module   = Namespace.splitName (self.name) [0]
+      self.module   = repository.splitName (self.name) [0]
       self.fullName = self.name

Modified: trunk/gnue-appserver/src/gcd/readgcd.py
===================================================================
--- trunk/gnue-appserver/src/gcd/readgcd.py     2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/gcd/readgcd.py     2005-03-13 10:41:15 UTC (rev 
7194)
@@ -33,7 +33,7 @@
 
 from gnue.appserver import VERSION
 from gnue.appserver.gcd import GCParser
-from gnue.appserver.classrep import Namespace, helpers
+from gnue.appserver import repository
 from gnue.appserver import geasConfiguration
 
 
@@ -99,7 +99,7 @@
 
 
 # =============================================================================
-# Update a database schema from GNUe Class Definitions and update classrep.
+# Update a database schema from GNUe Class Definitions and update repository.
 # =============================================================================
 
 class gcdClient (GClientApp):
@@ -224,24 +224,23 @@
     self._connections = connections
     self._database    = database
     self._filenames   = files
-    self._files       = []
+    self._files       = {}
     self._dump        = dump
     self._fileonly    = fonly
     self._uuidType    = gConfig ('uuidtype', section = 'appserver').lower ()
 
     # ResultSets
-    self.moduleRS = None
-    self.classRS  = None
-    self.propRS   = None
-    self.procRS   = None
-    self.parmRS   = None
+    self.__moduleRS = None
+    self.__classRS  = None
+    self.__propRS   = None
+    self.__procRS   = None
 
     # Lookup dictionaries
-    self.__lpModule   = {}        # gnue_id -> name, name -> gnue_id
-    self.__lpClass    = {}        # fqName -> gnue_id
+    self.lpModule     = {}        # gnue_id -> name, name -> gnue_id
+    self.lpClass      = {}        # fqName -> gnue_id
+    self.lpProperty   = {}        # class-id.module-id_name -> gnue_id
+    self.lpProcedure  = {}        # class-name.module-name_name -> gnue_id
     self.__lpFilter   = {}        # fqName -> gnue_id
-    self.__lpProperty = {}        # class-id.module-id_name -> gnue_id
-    self.__lpProcedure= {}        # class-name.module-name_name -> gnue_id
     self.__duplos     = {}        # fqName
 
     # Data from gcd files
@@ -264,10 +263,11 @@
 
     try:
       for filename in files:
-        self._files.append (openResource (filename))
+        self._files [filename] = openResource (filename)
 
     except IOError, err:
-      for item in self._files:
+      while self._files:
+        (name, item) = self._files.popitem ()
         item.close ()
 
       raise StartupError, u_("Unable to open input file: %s") % \
@@ -292,16 +292,27 @@
 
     print o (u_("Loading gcd files ..."))
 
-    for item in xrange (len (self._files)):
+    while self._files:
+      self.__currentFile, stream = self._files.popitem ()
+      self.__currentClass = None
+
       try:
-        self.__currentFile = self._filenames [item]
+        schema = GCParser.loadFile (stream)
 
-        schema = GCParser.loadFile (self._files [item])
-        schema.walk (self.__iterateObjects)
+        try:
+          schema.walk (self.__iterateObjects)
 
+        finally:
+          self.__currentClass = None
+
+          # Make sure to unlink all reference cycles to let the gc work
+          schema.unlink ()
+          schema = None
+
       finally:
-        self._files [item].close ()
+        stream.close ()
 
+
     self.__integrityCheck ()
 
     self.executeAndGenerateCode ()
@@ -370,7 +381,6 @@
     """
 
     if sObject._type == 'GCModule':
-      self.__currentModule = sObject
       self.__addModuleToRepository (sObject)
 
     elif sObject._type == 'GCClass':
@@ -403,21 +413,21 @@
     to ids and vice versa
     """
 
-    self.__lpModule = {}
+    self.lpModule.clear ()
 
-    if self.moduleRS is None:
-      self.moduleRS = self.__openSource ('gnue_module',
+    if self.__moduleRS is None:
+      self.__moduleRS = self.__openSource ('gnue_module',
                    ['gnue_id', 'gnue_name', 'gnue_comment']).createResultSet ()
 
-    rec = self.moduleRS.firstRecord ()
+    rec = self.__moduleRS.firstRecord ()
     while rec is not None:
       gid  = rec.getField ('gnue_id')
       name = rec.getField ('gnue_name')
 
-      self.__lpModule [gid]  = name
-      self.__lpModule [name.lower ()] = gid
+      self.lpModule [gid]  = name
+      self.lpModule [name.lower ()] = gid
 
-      rec  = self.moduleRS.nextRecord ()
+      rec  = self.__moduleRS.nextRecord ()
 
 
 
@@ -432,29 +442,29 @@
     defined it will be set into the filter dictionary.
     """
 
-    self.__lpClass  = {}
-    self.__lpFilter = {}
+    self.lpClass.clear ()
+    self.__lpFilter.clear ()
 
-    if self.classRS is None:
-      self.classRS = self.__openSource ('gnue_class', ['gnue_id', 'gnue_name',
+    if self.__classRS is None:
+      self.__classRS = self.__openSource ('gnue_class', ['gnue_id', 
'gnue_name',
           'gnue_module', 'gnue_comment', 'gnue_filter']).createResultSet ()
 
-    rec = self.classRS.firstRecord ()
+    rec = self.__classRS.firstRecord ()
     while rec is not None:
       gid  = rec.getField ('gnue_id')
       name = rec.getField ('gnue_name')
       mid  = rec.getField ('gnue_module')
       fid  = rec.getField ('gnue_filter')
 
-      fqName = Namespace.createName (self.__lpModule [mid], name)
+      fqName = repository.createName (self.lpModule [mid], name)
 
-      self.__lpClass [gid]    = fqName
-      self.__lpClass [fqName.lower ()] = gid
+      self.lpClass [gid]    = fqName
+      self.lpClass [fqName.lower ()] = gid
 
       if fid is not None:
         self.__lpFilter [fqName.lower ()] = fid
 
-      rec  = self.classRS.nextRecord ()
+      rec  = self.__classRS.nextRecord ()
 
 
 
@@ -468,23 +478,23 @@
     constructed from "classid.moduleid_propertyname".
     """
 
-    self.__lpProperty = {}
+    self.lpProperty.clear ()
 
-    if self.propRS is None:
-      self.propRS = self.__openSource ('gnue_property', ['gnue_id',
+    if self.__propRS is None:
+      self.__propRS = self.__openSource ('gnue_property', ['gnue_id',
           'gnue_module', 'gnue_class', 'gnue_name', 'gnue_type', 'gnue_length',
           'gnue_scale', 'gnue_nullable', 'gnue_comment']).createResultSet ()
 
-    rec = self.propRS.firstRecord ()
+    rec = self.__propRS.firstRecord ()
     while rec is not None:
       mid  = rec.getField ('gnue_module')
       cid  = rec.getField ('gnue_class')
       name = rec.getField ('gnue_name')
       key  = "%s.%s_%s" % (cid, mid, name.lower ())
 
-      self.__lpProperty [key] = rec.getField ('gnue_id')
+      self.lpProperty [key] = rec.getField ('gnue_id')
 
-      rec  = self.propRS.nextRecord ()
+      rec  = self.__propRS.nextRecord ()
 
 
   # ---------------------------------------------------------------------------
@@ -497,24 +507,24 @@
     from "classname.modulename_procedurename".
     """
 
-    self.__lpProcedure = {}
+    self.lpProcedure.clear ()
 
-    if self.procRS is None:
-      self.procRS = self.__openSource ('gnue_procedure', ['gnue_id',
+    if self.__procRS is None:
+      self.__procRS = self.__openSource ('gnue_procedure', ['gnue_id',
         'gnue_module', 'gnue_class', 'gnue_name', 'gnue_type', 'gnue_length',
         'gnue_scale', 'gnue_nullable', 'gnue_comment', 'gnue_code',
         'gnue_language']).createResultSet ()
 
-    rec = self.procRS.firstRecord ()
+    rec = self.__procRS.firstRecord ()
     while rec is not None:
-      mName = self.__lpModule.get (rec.getField ('gnue_module'))
-      cName = self.__lpClass.get (rec.getField ('gnue_class'))
+      mName = self.lpModule.get (rec.getField ('gnue_module'))
+      cName = self.lpClass.get (rec.getField ('gnue_class'))
       pName = rec.getField ('gnue_name')
       key   = "%s.%s_%s" % (cName, mName, pName)
 
-      self.__lpProcedure [key.lower ()] = rec.getField ('gnue_id')
+      self.lpProcedure [key.lower ()] = rec.getField ('gnue_id')
 
-      rec  = self.procRS.nextRecord ()
+      rec  = self.__procRS.nextRecord ()
 
 
   # ---------------------------------------------------------------------------
@@ -531,7 +541,7 @@
 
     mkey = item.name.lower ()
     mDef = self.__fetchTags (item, ['name', 'comment'])
-    mDef ['gnue_id'] = self.__lpModule.get (mkey)
+    mDef ['gnue_id'] = self.lpModule.get (mkey)
 
     if not self.modules.has_key (mkey):
       self.modules [mkey] = {}
@@ -602,7 +612,7 @@
 
     key  = item.fullName.lower ()
     cDef = self.__fetchTags (item, ['module', 'name', 'comment', 'filter'])
-    cDef ['gnue_id'] = self.__lpClass.get (key)
+    cDef ['gnue_id'] = self.lpClass.get (key)
 
     if not self.classes.has_key (key):
       self.classes [key] = {'_files': []}
@@ -660,10 +670,10 @@
     """
 
     fqName = "%s.%s" % (item._parent.fullName, item.fullName)
-    pkey   = "%s.%s_%s" % (self.__lpClass.get (item._parent.fullName.lower ()),
-                         self.__lpModule.get (item.module.lower ()), item.name)
+    pkey   = "%s.%s_%s" % (self.lpClass.get (item._parent.fullName.lower ()),
+                         self.lpModule.get (item.module.lower ()), item.name)
 
-    pDef = {'gnue_id'   : self.__lpProperty.get (pkey.lower ()),
+    pDef = {'gnue_id'   : self.lpProperty.get (pkey.lower ()),
             'gnue_class': item._parent.fullName,
             'gnue_type' : item.datatype}
 
@@ -738,20 +748,20 @@
       # Make sure the module referenced is a valid module, either an existing
       # or a new one
       mname = item ['gnue_module'].lower ()
-      if not self.__lpModule.get (mname) and not self.modules.get (mname):
+      if not self.lpModule.get (mname) and not self.modules.get (mname):
         raise ModuleNotFoundError, (item ['gnue_module'], item ['_files'])
 
       # Make sure the filter class will be available if one is defined
       if item.get ('gnue_filter') is not None:
         fname = item ['gnue_filter']
-        if not self.__lpClass.get (fname) and not self.classes.get (fname):
+        if not self.lpClass.get (fname) and not self.classes.get (fname):
           raise FilterNotFoundError, (name, fname, item ['_files'])
 
       # For an existing class we need to make sure the filter-attribute won't
       # get changed, because we cannot add a not NULL field to an existing 
class
       if item ['gnue_id'] is not None:
         iFilter = item.get ('gnue_filter') and \
-                  self.__lpClass [item ['gnue_filter'].lower ()]
+                  self.lpClass [item ['gnue_filter'].lower ()]
 
         if iFilter != self.__lpFilter.get (name):
           raise FilterChangeError, (name, item ['_files'])
@@ -762,9 +772,9 @@
       classDef = self.classes [item ['gnue_class'].lower ()]
 
       # If a property is a reference, make sure the referenced class exists
-      if not item ['gnue_type'] in helpers.BASE_TYPES:
+      if not repository.BASE_TYPES.has_key (item ['gnue_type']):
         refname = item ['gnue_type'].lower ()
-        if not self.__lpClass.get (refname) and not self.classes.get (refname):
+        if not self.lpClass.get (refname) and not self.classes.get (refname):
           raise ClassNotFoundError, (item ['gnue_type'], classDef ['_files'])
 
       # For an existing class make sure to *not* add NOT NULL properties 
@@ -793,14 +803,19 @@
     """
 
     # Update the result set and the lookup dictionary
-    stat = self.__processResultSet (self.moduleRS, self.modules, ['gnue_name'])
-    self.__getModuleLookup ()
+    try:
+      stat = self.__processResultSet (self.__moduleRS, self.modules,
+                                      ['gnue_name'])
+      self.__getModuleLookup ()
 
-    print o (u_("  Modules   : %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-                "unchanged.") \
-             % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
+      print o (u_("  Modules   : %(ins)3d inserted, %(upd)3d updated, "
+                  "%(kept)3d unchanged.") \
+               % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
 
-    return (stat [0] + stat [1]) > 0
+      return (stat [0] + stat [1]) > 0
+
+    finally:
+      self.__moduleRS.close ()
   
 
   # ---------------------------------------------------------------------------
@@ -815,51 +830,55 @@
     @return: True if a commit is needed, False otherwise
     """
 
-    # First make sure we have valid 'gnue_module' entries for all classes
-    self.__replaceReferences (self.classes, self.__lpModule, 'gnue_module')
+    try:
+      # First make sure we have valid 'gnue_module' entries for all classes
+      self.__replaceReferences (self.classes, self.lpModule, 'gnue_module')
 
-    # Then have a look at the filters defined on the classes
-    filterStack = []
+      # Then have a look at the filters defined on the classes
+      filterStack = []
 
-    for (fullName, item) in self.classes.items ():
-      if item.has_key ('gnue_filter'):
-        filterName = item ['gnue_filter']
-        filterId   = self.__lpClass.get (filterName)
+      for (fullName, item) in self.classes.items ():
+        if item.has_key ('gnue_filter'):
+          filterName = item ['gnue_filter']
+          filterId   = self.lpClass.get (filterName)
 
-        # If the filter-class is available we can use it
-        if filterId is not None:
-          item ['gnue_filter'] = filterId
-        else:
-          # since the filter-id will be created later, we add it to the queue
-          # and remove the attribute from the class.
-          filterStack.append ((item, filterName, fullName))
-          del item ['gnue_filter']
+          # If the filter-class is available we can use it
+          if filterId is not None:
+            item ['gnue_filter'] = filterId
+          else:
+            # since the filter-id will be created later, we add it to the queue
+            # and remove the attribute from the class.
+            filterStack.append ((item, filterName, fullName))
+            del item ['gnue_filter']
 
-    # Merge all changes into the current result set
-    cond = ['gnue_module', 'gnue_name']
-    stat = self.__processResultSet (self.classRS, self.classes, cond)
-    needCommit = (stat [0] + stat [1]) > 0
+      # Merge all changes into the current result set
+      cond = ['gnue_module', 'gnue_name']
+      stat = self.__processResultSet (self.__classRS, self.classes, cond)
+      needCommit = (stat [0] + stat [1]) > 0
 
-    # Update the lookup dictionary for classes
-    self.__getClassLookup ()
+      # Update the lookup dictionary for classes
+      self.__getClassLookup ()
 
-    # Process all classes with a 'new' filter class
-    filterChanged = False
+      # Process all classes with a 'new' filter class
+      filterChanged = False
 
-    if filterStack:
-      for (item, filterName, fullName) in filterStack:
-        item ['gnue_filter'] = self.__lpClass.get (filterName)
+      if filterStack:
+        for (item, filterName, fullName) in filterStack:
+          item ['gnue_filter'] = self.lpClass.get (filterName)
 
-      fst = self.__processResultSet (self.classRS, self.classes, cond)
-      filterChanged = fst [1] > 0
+        fst = self.__processResultSet (self.__classRS, self.classes, cond)
+        filterChanged = fst [1] > 0
 
-    print o (u_("  Classes   : %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-                "unchanged.") \
-          % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
+      print o (u_("  Classes   : %(ins)3d inserted, %(upd)3d updated, "
+                  "%(kept)3d unchanged.") \
+            % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
 
-    return needCommit or filterChanged
+      return needCommit or filterChanged
 
+    finally:
+      self.__classRS.close ()
 
+
   # ---------------------------------------------------------------------------
   # Update/add Properties to the class repository
   # ---------------------------------------------------------------------------
@@ -871,21 +890,26 @@
     @return: True if a commit is needed, False otherwise
     """
 
-    # Make sure all properties have a valid 'gnue_module' and 'gnue_class'
-    self.__replaceReferences (self.properties, self.__lpModule, 'gnue_module')
-    self.__replaceReferences (self.properties, self.__lpClass, 'gnue_class')
+    try:
+      # Make sure all properties have a valid 'gnue_module' and 'gnue_class'
+      self.__replaceReferences (self.properties, self.lpModule, 'gnue_module')
+      self.__replaceReferences (self.properties, self.lpClass, 'gnue_class')
 
-    # Load and update all properties
-    cond = ['gnue_module', 'gnue_class', 'gnue_name']
-    stat = self.__processResultSet (self.propRS, self.properties, cond)
+      # Load and update all properties
+      cond = ['gnue_module', 'gnue_class', 'gnue_name']
+      stat = self.__processResultSet (self.__propRS, self.properties, cond)
+      self.__getPropertyLookup ()
 
-    print o (u_("  Properties: %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-                "unchanged.") \
-             % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
+      print o (u_("  Properties: %(ins)3d inserted, %(upd)3d updated, "
+                  "%(kept)3d unchanged.") \
+               % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
 
-    return (stat [0] + stat [1]) > 0
+      return (stat [0] + stat [1]) > 0
 
+    finally:
+      self.__propRS.close ()
 
+
   # ---------------------------------------------------------------------------
   # Update/add Procedures to the class repository
   # ---------------------------------------------------------------------------
@@ -898,22 +922,26 @@
     @return: True if a commit is needed, False otherwise
     """
 
-    # Make sure all procedures have a valid 'gnue_module' and 'gnue_class'
-    self.__replaceReferences (self.procedures, self.__lpModule, 'gnue_module')
-    self.__replaceReferences (self.procedures, self.__lpClass, 'gnue_class')
+    try:
+      # Make sure all procedures have a valid 'gnue_module' and 'gnue_class'
+      self.__replaceReferences (self.procedures, self.lpModule, 'gnue_module')
+      self.__replaceReferences (self.procedures, self.lpClass, 'gnue_class')
 
-    # Load and update all procedures
-    cond = ['gnue_module', 'gnue_class', 'gnue_name']
-    stat = self.__processResultSet (self.procRS, self.procedures, cond)
-    self.__getProcedureLookup ()
+      # Load and update all procedures
+      cond = ['gnue_module', 'gnue_class', 'gnue_name']
+      stat = self.__processResultSet (self.__procRS, self.procedures, cond)
+      self.__getProcedureLookup ()
 
-    print o (u_("  Procedures: %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-                "unchanged.") \
-              % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
+      print o (u_("  Procedures: %(ins)3d inserted, %(upd)3d updated, "
+                  "%(kept)3d unchanged.") \
+                % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
 
-    return (stat [0] + stat [1]) > 0
+      return (stat [0] + stat [1]) > 0
 
+    finally:
+      self.__procRS.close ()
 
+
   # ---------------------------------------------------------------------------
   # Update/add parameters to the class repository
   # ---------------------------------------------------------------------------
@@ -926,24 +954,28 @@
     """
 
     # Make sure all parameters have a valid 'gnue_procedure'
-    self.__replaceReferences (self.parameters, self.__lpProcedure,
+    self.__replaceReferences (self.parameters, self.lpProcedure,
         'gnue_procedure')
 
-    self.parmRS = self.__openSource ('gnue_parameter', ['gnue_id',
+    resultSet = self.__openSource ('gnue_parameter', ['gnue_id',
         'gnue_procedure', 'gnue_name', 'gnue_type', 'gnue_scale',
         'gnue_length', 'gnue_comment']).createResultSet ()
 
-    # Load and update all parameters
-    cond = ['gnue_procedure', 'gnue_name']
-    stat = self.__processResultSet (self.parmRS, self.parameters, cond)
+    try:
+      # Load and update all parameters
+      cond = ['gnue_procedure', 'gnue_name']
+      stat = self.__processResultSet (resultSet, self.parameters, cond)
 
-    print o (u_("  Parameters: %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-                "unchanged.") \
+      print o (u_("  Parameters: %(ins)3d inserted, %(upd)3d updated, "
+                  "%(kept)3d unchanged.") \
               % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]})
 
-    return (stat [0] + stat [1]) > 0
+      return (stat [0] + stat [1]) > 0
 
+    finally:
+      resultSet.close ()
 
+
   # ---------------------------------------------------------------------------
   # Update references in a dictionary
   # ---------------------------------------------------------------------------
@@ -1135,6 +1167,5 @@
       return UUID.generateRandom ()
 
 
-
 if __name__ == "__main__":
   gcdClient ().run ()

Modified: trunk/gnue-appserver/src/geasFilter.py
===================================================================
--- trunk/gnue-appserver/src/geasFilter.py      2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/geasFilter.py      2005-03-13 10:41:15 UTC (rev 
7194)
@@ -22,7 +22,6 @@
 # $Id$
 
 from language import Session
-from classrep import Namespace
 from gnue.common.apps import errors
 
 
@@ -75,6 +74,7 @@
     """
 
     result = []
+    repository = self.__sm.repository
 
     for (fId, filterDef) in self.__labels:
       # Create an ordered sequence of all search/info-properties as stated in
@@ -88,10 +88,10 @@
       # order sequence by search-value or info-value
       fields.sort ()
 
-      classdef = self.__sm.classes.find (fId)
+      classdef = repository.classes [fId]
       master   = classdef.gnue_filter and classdef.gnue_filter or None
       if master is not None:
-        master = self.__sm.classes.find (master.gnue_id).fullName
+        master = repository.classes [master.gnue_id].fullName
 
       labels = [(f [1], f [2]['search'], f [2]['name']) for f in fields]
       names  = [f [2]['name'] for f in fields]
@@ -126,9 +126,8 @@
     self.__fDict = {}
 
     # First get all filters defined in class repository
-    for klass in self.__sm.classes.values ():
-      if klass.gnue_filter:
-        self.__addFilter (klass.gnue_filter)
+    for filterClass in self.__sm.repository.filters.values ():
+      self.__addFilter (filterClass)
 
     result = []
     add = self.__getIndependantFilters ()
@@ -232,7 +231,7 @@
 
       for label in labels:
         prop  = label.gnue_property
-        klass = self.__sm.classes.find (prop.gnue_class.gnue_id)
+        klass = self.__sm.repository.classes [prop.gnue_class.gnue_id]
 
         fullName = None
         for p in klass.properties.values ():
@@ -250,7 +249,7 @@
              'search': label.gnue_search is not None}
 
       if not len (labels):
-        filterClass = self.__sm.classes.find (filterId)
+        filterClass = self.__sm.repository.classes [filterId]
         prop = filterClass.properties ['gnue_id']
         entry [prop.gnue_id] = {'C': {'order' : 0,
                                       'label' : filterClass.fullName,
@@ -272,15 +271,15 @@
     currently in use. This dictionary has the filter-id's as keys and another
     dictionary - with language = label - as values.
 
-    @return: dictionary {filter-id: {language: label}, {language: label} ..}
+    @return: dictionary {filter-id: {language: label, language: label} ..}
     """
 
     result = {}
 
     for filterId in self.__filters:
-      filterClass = self.__sm.classes.find (filterId)
+      filterClass = self.__sm.repository.classes [filterId]
       prop = filterClass.properties ['gnue_id']
-      cond = ['eq', ['field', 'gnue_property'], ['const', prop.gnue_id]]
+      cond = {'gnue_property': prop.gnue_id}
 
       labels = self.__session.find ('gnue_label', cond, [],
                                     ['gnue_language', 'gnue_label'])
@@ -367,7 +366,7 @@
     """
 
     result    = {}
-    classname = self.__sm.classes.find (filterId).fullName
+    classname = self.__sm.repository.classes [filterId].fullName
 
     # if we have a master-filter add the master-field to the query as well as a
     # 'select-all' condition to prevent geasSession.request () of inserting a

Modified: trunk/gnue-appserver/src/geasGsdGen.py
===================================================================
--- trunk/gnue-appserver/src/geasGsdGen.py      2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/geasGsdGen.py      2005-03-13 10:41:15 UTC (rev 
7194)
@@ -184,7 +184,7 @@
     @param className: fully qualified name of the class to be exported
     """
 
-    cDef  = self.sm.classes [className]
+    cDef  = self.sm.repository.classes [className]
     print o(u_("Exporting data of class '%s' ...") % className)
 
     # Prepare the tabledata- and it's definition tags
@@ -470,12 +470,13 @@
     result = {}
     fNames = {}
 
+    repository = self.sm.repository
     # first replace all class-names by there gnue-id's
     for (filterName, data) in self.__filterParams.items ():
-      if not self.sm.classes.has_key (filterName):
+      if not repository.classes.has_key (filterName):
         raise StartupError, u_("Filter class '%s' not found") % filterName
 
-      fc = self.sm.classes [filterName]
+      fc = repository.classes [filterName]
       for field in data.keys ():
         if not fc.properties.has_key (field):
           raise StartupError, \
@@ -538,23 +539,25 @@
     @param args: list of classnames or modulenames to be exported
     """
 
+    repository = self.sm.repository
+
     if not len (args):
       if self.__useFilter:
         for filterId in self.filters.keys ():
-          filterClass = self.sm.classes.find (filterId)
+          filterClass = repository.classes [filterId]
           if not filterClass.fullName in args:
             args.append (filterClass.fullName)
 
       else:
-        for c in self.sm.classes.values ():
-          if c.module.fullName == 'gnue':
+        for c in repository.classes.values ():
+          if c.gnue_module.fullName == 'gnue':
             continue
           
           args.append (c.fullName)
 
     if self.OPTIONS ['system']:
-      for c in self.sm.classes.values ():
-        if c.module.fullName == 'gnue' and not c.fullName in args:
+      for c in repository.classes.values ():
+        if c.gnue_module.fullName == 'gnue' and not c.fullName in args:
           args.append (c.fullName)
 
     self.__classes = {}
@@ -585,7 +588,8 @@
     dependencies given by class-references.
     """
 
-    cDef = self.sm.classes [className]
+    repository = self.sm.repository
+    cDef       = repository.classes [className]
 
     # every class has a sequence of master-classes
     if not self.__classes.has_key (className):
@@ -612,7 +616,7 @@
 
     # if 'include-details' is set, we've to add all detail-classes of the
     # current class.
-    for cClass in self.sm.classes.values ():
+    for cClass in repository.classes.values ():
       for p in cClass.properties.values ():
         if p.isReference and p.referencedClass.gnue_id == cDef.gnue_id:
           if not self.__classes.has_key (cClass.fullName):
@@ -687,7 +691,7 @@
       return result
 
     for className in self.exports:
-      classdef = self.sm.classes [className]
+      classdef = self.sm.repository.classes [className]
 
       cond = []
 
@@ -744,21 +748,22 @@
     @return: tuple with the datasource and it's field list
     """
 
-    className = classdef.fullName
-    alias     = {classdef.table: ""}
+    className  = classdef.fullName
+    alias      = {classdef.table: ""}
+    repository = self.sm.repository
 
     # prepare a dictionary with aliases for all tables needed
     if self.conditions.has_key (className):
       alias [classdef.table] = 't0'
       index = 1
       for (srcrel, srcitem, dstrel, dstitem) in self.conditions [className]:
-        if not alias.has_key (self.sm.classes [srcrel].table):
-          alias [self.sm.classes [srcrel].table] = "t%d" % index
+        if not alias.has_key (repository.classes [srcrel].table):
+          alias [repository.classes [srcrel].table] = "t%d" % index
           index += 1
 
         if dstrel is not None and \
-            not alias.has_key (self.sm.classes [dstrel].table):
-          alias [self.sm.classes [dstrel].table] = "t%d" % index
+            not alias.has_key (repository.classes [dstrel].table):
+          alias [repository.classes [dstrel].table] = "t%d" % index
           index += 1
 
     # make sure the list of tables is sorted by alias
@@ -774,13 +779,13 @@
     conditions = None
     if self.conditions.has_key (className):
       for (srcrel, srcitem, dstrel, dstitem) in self.conditions [className]:
-        sValue = "%s.%s" % (alias [self.sm.classes [srcrel].table], srcitem)
+        sValue = "%s.%s" % (alias [repository.classes [srcrel].table], srcitem)
         if dstrel is None:
           dType  = 'const'
           dValue = dstitem
         else:
           dType  = 'field'
-          dValue = "%s.%s" % (alias [self.sm.classes [dstrel].table], dstitem)
+          dValue = "%s.%s" % (alias[repository.classes [dstrel].table], 
dstitem)
 
         c = GConditions.buildTreeFromList ( \
             ['eq', ['field', sValue], [dType, dValue]])

Modified: trunk/gnue-appserver/src/geasInstance.py
===================================================================
--- trunk/gnue-appserver/src/geasInstance.py    2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/geasInstance.py    2005-03-13 10:41:15 UTC (rev 
7194)
@@ -33,7 +33,6 @@
 from gnue import appserver
 from gnue.appserver.language import Object, Session
 from gnue.common.logic.language import getLanguageAdapter
-from gnue.appserver.classrep import Namespace
 from gnue.common.apps import errors
 
 # =============================================================================
@@ -280,14 +279,14 @@
     # Do not call OnChange triggers while in OnInit code and when setting
     # time/user stamp fields
     if regular and self.status () != 'initializing':
-      for proc in self.__classdef.procedures.values ():
-        if proc.gnue_name.upper () == 'ONCHANGE':
-          self.call (proc, {}, {'oldValue': self.__getValue (propertyname),
-                                'newValue': __value,
-                                'propertyName': propertydef.fullName})
+      for trigger in self.__classdef.OnChange:
+        self.call (trigger, {}, {'oldValue': self.__getValue (propertyname),
+                                 'newValue': __value,
+                                 'propertyName': propertydef.fullName})
 
     self.__record.putField (propertydef.column, __value)
 
+
   # ---------------------------------------------------------------------------
   # Set the values of a list of properties
   # ---------------------------------------------------------------------------
@@ -355,7 +354,7 @@
       cx.bindFunction ('direct_call',    self.__session.call)
 
       # set context for the procedure
-      sess.setcontext (proceduredef.module.gnue_name)
+      sess.setcontext (proceduredef.gnue_module.gnue_name)
 
       method = cx.buildFunction (proceduredef.gnue_name, 
proceduredef.gnue_code,
                                  parameters)
@@ -384,22 +383,8 @@
     is raised.
     """
 
-    # First get all validation procedures of the class
-    ownValidate = None
-    triggers    = []
-    for proc in self.__classdef.procedures.values ():
-      if proc.gnue_name.upper () == 'ONVALIDATE':
-        if proc.module.fullName == self.__classdef.module.fullName:
-          ownValidate = proc
-        else:
-          triggers.append (proc)
-
-    # now call all triggers
-    for proc in triggers:
-      self.call (proc, None)
-
-    if ownValidate is not None:
-      self.call (ownValidate, None)
+    for trigger in self.__classdef.OnValidate:
+      self.call (trigger, None)
     
     # after finishing all OnValidate calls, have a look at the required fields
     for prop in self.__classdef.properties.values ():

Modified: trunk/gnue-appserver/src/geasRpcServer.py
===================================================================
--- trunk/gnue-appserver/src/geasRpcServer.py   2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/geasRpcServer.py   2005-03-13 10:41:15 UTC (rev 
7194)
@@ -40,7 +40,7 @@
 from gnue.appserver import geasConfiguration
 
 
-_GC_DEBUG = False  # Set this to True to activate garbage collection debugging
+_GC_DEBUG = False   # Set this to True to activate garbage collection debugging
 
 # =============================================================================
 # RPC application class
@@ -285,30 +285,35 @@
       print o(u_("Debugging garbage collection not activated."))
       return
 
-    r = gc.collect ()
+    unreachable = gc.collect ()
 
     gf = open ('garbage.log', 'w')
 
     print "=" * 70
-    print "GARBAGE:", r, ":"
-    gf.write ('GARBAGE: %d\n' % r)
+    print "GC unreachable objects:", unreachable
+    gf.write ('GARBAGE: %d\n' % unreachable)
 
     n = 0
     for x in gc.garbage:
       n += 1
-      s = str(x)
-      if len(s) > 75: s = s[:75]
-      print type(x),"\n  ", s
-      gf.write ("%s: %s\n" % (type (x), repr (x)))
+      try:
+        s = repr (x)
+        if len (s) > 75: s = s [:75]
 
-      from gnue.common.datasources import GConditions
-      if isinstance (x, GConditions.GCondition):
-        gf.write ("Referrer of: %s\n" % x)
-        for y in gc.get_referrers (x):
-          gf.write ("--> %s: %s\n" % (type (y), y))
+        print type (x), "\n  ", s
+        gf.write ("%s: %s\n" % (type (x), repr (x)))
 
-        gf.write ("%s\n" % ("-" * 70))
+        #from gnue.appserver.gld import GLParser
+        #if isinstance (x, GLParser.GLModule):
+          #gf.write ("Referrer of: %s\n" % x)
+          #for y in gc.get_referrers (x):
+            #gf.write ("--> %s: %s\n" % (type (y), y))
 
+          #gf.write ("%s\n" % ("-" * 70))
+
+      except:
+        print "cannot create representation of object"
+
     gf.close ()
     del gc.garbage [:]
 

Modified: trunk/gnue-appserver/src/geasSession.py
===================================================================
--- trunk/gnue-appserver/src/geasSession.py     2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/geasSession.py     2005-03-13 10:41:15 UTC (rev 
7194)
@@ -31,7 +31,7 @@
 
 from gnue.appserver import data, geasList, geasInstance
 from gnue.appserver.geasAuthentication import AuthError
-from gnue.appserver.classrep.Property import PropertyNotFoundError
+from gnue.appserver.repository import PropertyNotFoundError
 
 
 # =============================================================================
@@ -135,7 +135,7 @@
     if not self.__authAdapter.hasAccess (self, self.user, classname):
       raise AccessDeniedError, (classname)
 
-    return self.sm.classes [classname]
+    return self.sm.repository.classes [classname]
 
 
   # ---------------------------------------------------------------------------
@@ -496,30 +496,23 @@
 
   def __newInstance (self, classdef):
 
-    table    = classdef.table
-    record   = self.__connection.insertRecord (table)
+    table      = classdef.table
+    record     = self.__connection.insertRecord (table)
+    repository = self.sm.repository
 
     instance = geasInstance.geasInstance (self, self.__connection, record,
                                           classdef)
     if classdef.gnue_filter:
       fId   = classdef.gnue_filter.gnue_id
-      fName = self.sm.classes.find (fId).fullName
+      fName = classdef.gnue_filter.fullName
       instance.put ([fName], [self.__filterValue (fId)])
 
     instance.updateStamp (True)
 
-    onInits = {}
-    for proc in classdef.procedures.values ():
-      if proc.gnue_name.upper () == 'ONINIT':
-        onInits [proc.module.fullName] = proc
+    # Fire all OnInit triggers of the class definition
+    for trigger in classdef.OnInit:
+      instance.call (trigger, None)
 
-    if onInits.has_key (classdef.module.fullName):
-      instance.call (onInits [classdef.module.fullName], None)
-      del onInits [classdef.module.fullName]
-
-    for proc in onInits.values ():
-      instance.call (proc, None)
-
     # all modifications are 'serious' from now on 
     record.initialized ()
 
@@ -553,7 +546,7 @@
             typelist.append ('procedure')
 
           else:
-            raise PropertyNotFoundError, (classdef.fullName, p)
+            raise PropertyNotFoundError, (p, classdef.fullName)
 
         result.append (typelist)
 
@@ -626,10 +619,10 @@
 
       for objectId in obj_id_list:
         instance = self.__findInstance (classdef, objectId, [])
-        for proc in classdef.procedures.values ():
-          if proc.gnue_name.upper () == 'ONDELETE':
-            instance.call (proc, None)
 
+        for trigger in classdef.OnDelete:
+          instance.call (trigger, None)
+
       for object_id in obj_id_list:
         self.__connection.deleteRecord (classdef.table, object_id)
         if self.__dirtyInstances.has_key (object_id):
@@ -701,7 +694,7 @@
   
     if classdef.gnue_filter:
       useFilter  = True
-      filterName = self.sm.classes.find (classdef.gnue_filter.gnue_id).fullName
+      filterName = classdef.gnue_filter.fullName
       cList = cTree.findChildrenOfType ('GCCField', allowAllChildren = True)
       if len (cList):
         for item in cList:
@@ -762,7 +755,7 @@
 
     if classdef.gnue_filter:
       filterId   = classdef.gnue_filter.gnue_id
-      filterName = self.sm.classes.find (filterId).fullName
+      filterName = classdef.gnue_filter.fullName
       filterCond = GConditions.buildConditionFromDict ( \
           {filterName: self.__filterValue (filterId)})
     else:
@@ -777,14 +770,14 @@
 
   def __filterValue (self, filterId):
 
-    filterName = self.sm.classes.find (filterId).fullName
+    filterName = self.sm.repository.classes [filterId].fullName
     if not self.filters.has_key (filterName):
       filterValue = self.parameters.get (filterName, None)
       if filterValue is None:
         raise NoFilterParamError, (filterName)
 
-      cond = ['eq', ['field', 'gnue_id'], ['const', filterValue]]
-      fList = self.request (filterName, cond, [], ['gnue_id'])
+      cond   = {'gnue_id': filterValue}
+      fList  = self.request (filterName, cond, [], ['gnue_id'])
       idList = self.fetch (fList, 0, 5)
 
       if not len (idList):

Modified: trunk/gnue-appserver/src/geasSessionManager.py
===================================================================
--- trunk/gnue-appserver/src/geasSessionManager.py      2005-03-13 10:03:11 UTC 
(rev 7193)
+++ trunk/gnue-appserver/src/geasSessionManager.py      2005-03-13 10:41:15 UTC 
(rev 7194)
@@ -25,7 +25,6 @@
 
 import geasSession
 import geasAuthentication
-import classrep
 import geasFilter
 import os.path
 import fnmatch
@@ -34,6 +33,7 @@
 from gnue import paths
 from gnue.common.datasources import GConnections
 from gnue.common.apps import i18n, GConfig, errors
+from gnue.appserver import repository
 from gnue.appserver.gcd import readgcd
 from gnue.appserver.gld import readgld
 
@@ -68,6 +68,7 @@
     #prof.runctx ('self.updateRepository (haltOnError = True)', globals (),
         #locals ())
     #prof.dump_stats ('appserver.profile')
+    self.repository = repository.Repository (self._internalSession)
     self.updateRepository (scanModules, haltOnError = True)
 
     cfg = gConfigDict (section = 'appserver')
@@ -127,22 +128,25 @@
     try:
       (gcd, gld) = self._scanModulePath ()
 
+      # Lookup dictionaries for reuse by readgld
+      lpModule    = {}
+      lpClass     = {}
+      lpProperty  = {}
+      lpProcedure = {}
+
       if len (gcd):
-        reader = readgcd.gcdReader (self._connections,
+        gcdreader = readgcd.gcdReader (self._connections,
                                     gConfig ('connection'), gcd)
-        reader.run ()
+        gcdreader.run ()
 
-        modRS = reader.moduleRS
-        clsRS = reader.classRS
-        prpRS = reader.propRS
-        prcRS = reader.procRS
-      else:
-        (modRS, clsRS, prpRS, prcRS) = (None, None, None, None)
+        lpModule     = gcdreader.lpModule
+        lpClass      = gcdreader.lpClass
+        lpProperty   = gcdreader.lpProperty
+        lpProcedure  = gcdreader.lpProcedure
 
       if len (gld):
-        reader = readgld.gldReader (self._connections,
-                                    gConfig ('connection'), gld,
-                                    modRS, clsRS, prpRS, prcRS)
+        reader = readgld.gldReader (self._connections, gConfig ('connection'),
+            gld, lpModule, lpClass, lpProperty, lpProcedure)
         reader.run ()
 
     except:
@@ -170,7 +174,7 @@
 
     self._internalSession.rollback ()
 
-    classrep.init (self)
+    self.repository.load ()
 
     self._filter = geasFilter.geasFilter (self)
 

Modified: trunk/gnue-appserver/src/generator/classdef.py
===================================================================
--- trunk/gnue-appserver/src/generator/classdef.py      2005-03-13 10:03:11 UTC 
(rev 7193)
+++ trunk/gnue-appserver/src/generator/classdef.py      2005-03-13 10:41:15 UTC 
(rev 7194)
@@ -23,7 +23,7 @@
 
 import mx
 
-from gnue.appserver.classrep import Namespace
+from gnue.appserver import repository
 from gnue.common.apps import errors
 
 # =============================================================================
@@ -57,7 +57,7 @@
     self.__session   = session
     self.__class     = klass
     self.__language  = language
-    self.classname   = Namespace.createName (klass.module.name, klass.name)
+    self.classname   = "%s_%s" % (klass.module.name, klass.name)
     self.classLabel  = "%s %s" % (klass.module.name.title (),
                                   klass.name.title ())
     self.isReference = asReference
@@ -97,6 +97,24 @@
 
 
   # ---------------------------------------------------------------------------
+  # Release all resources and pointers held by a classdef instance
+  # ---------------------------------------------------------------------------
+
+  def release (self):
+    """
+    Release all references and pointers of a class definition instance. This
+    allows the garbage collection to work fine.
+    """
+
+    for item in self.properties + self.specials:
+      item.parent = None
+      if item.reference is not None:
+        item.reference.release ()
+
+      item.reference = None
+
+
+  # ---------------------------------------------------------------------------
   # Create a sequence of languages to be processed for labels
   # ---------------------------------------------------------------------------
 
@@ -206,7 +224,7 @@
 
       for label in self.__session.find ('gnue_label', cond, [], pList):
 
-        full = Namespace.createName (label.gnue_property.module.name,
+        full = repository.createName (label.gnue_property.module.name,
                                      label.gnue_property.name)
         if full == 'gnue_id' and len (label.label):
           self.classLabel = label.label
@@ -278,7 +296,7 @@
     else:
       for item in self.properties:
         if '_' in item.propDef.gnue_type:
-          (refMod, refName) = Namespace.splitName (item.propDef.gnue_type)
+          (refMod, refName) = repository.splitName (item.propDef.gnue_type)
           refClass = self.__session.find ('gnue_class',
               {'gnue_name': refName, 'gnue_module.gnue_name': refMod}, [], [])
           cDef = ClassDef (self.__session, refClass [0], self.__language, True)
@@ -333,6 +351,7 @@
     return [(p, pageDict [p]) for p in pageNames]
 
 
+
     
 
 # =============================================================================
@@ -362,10 +381,10 @@
     self.info     = None
     self.labelPos = None
 
-    self.fullName = Namespace.createName (propDef.gnue_module.gnue_name,
+    self.fullName = repository.createName (propDef.gnue_module.gnue_name,
                                           propDef.gnue_name)
     if isCalculated:
-      self.dbField = Namespace.createName (propDef.gnue_module.gnue_name,
+      self.dbField = repository.createName (propDef.gnue_module.gnue_name,
                                            propDef.gnue_name [3:])
     else:
       self.dbField = self.fullName

Modified: trunk/gnue-appserver/src/generator/form.py
===================================================================
--- trunk/gnue-appserver/src/generator/form.py  2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/generator/form.py  2005-03-13 10:41:15 UTC (rev 
7194)
@@ -83,27 +83,31 @@
     @return: string with XML code of the generated form
     """
 
-    code = [u'<?xml version="1.0" encoding="utf-8"?>']
-    code.extend (self.__xml ('form', {'title': self.__classDef.classLabel,
-                                      None: self.__options}, "", True))
+    try:
+      code = [u'<?xml version="1.0" encoding="utf-8"?>']
+      code.extend (self.__xml ('form', {'title': self.__classDef.classLabel,
+                                        None: self.__options}, "", True))
 
-    for item in self.__sources.values ():
-      code.extend (self.__xml ('datasource', item, "  "))
+      for item in self.__sources.values ():
+        code.extend (self.__xml ('datasource', item, "  "))
 
-    code.extend (self.__xml ('logic', {None: self.__blocksToXML ()}, "  "))
+      code.extend (self.__xml ('logic', {None: self.__blocksToXML ()}, "  "))
 
-    tabPos = len (self.layoutManager.visualPages) > 1 and 'top' or 'none'
-    code.extend (self.__xml ('layout', {'xmlns:c': 'GNUe:Layout:Char',
-        'c:height': self.layoutManager.maxPageHeight,
-        'c:width' : self.layoutManager.maxPageWidth,
-        'tabbed'  : tabPos,
-        None: self.__pagesToXML ()}, "  "))
+      tabPos = len (self.layoutManager.visualPages) > 1 and 'top' or 'none'
+      code.extend (self.__xml ('layout', {'xmlns:c': 'GNUe:Layout:Char',
+          'c:height': self.layoutManager.maxPageHeight,
+          'c:width' : self.layoutManager.maxPageWidth,
+          'tabbed'  : tabPos,
+          None: self.__pagesToXML ()}, "  "))
 
-    code.append ('</form>')
+      code.append ('</form>')
 
-    return string.join (code, "\n")
+      return string.join (code, "\n")
 
+    finally:
+      self.__classDef.release ()
 
+
   # ---------------------------------------------------------------------------
   # Update the logic of the form (blocks and datasources)
   # ---------------------------------------------------------------------------

Modified: trunk/gnue-appserver/src/gld/GLParser.py
===================================================================
--- trunk/gnue-appserver/src/gld/GLParser.py    2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/gld/GLParser.py    2005-03-13 10:41:15 UTC (rev 
7194)
@@ -24,7 +24,7 @@
 from gnue.common.definitions import GParser, GObjects, GRootObj
 from gnue.common.definitions.GParserHelpers import GContent
 from gnue.common.formatting import GTypecast
-from gnue.appserver.classrep import helpers, Namespace
+from gnue.appserver import repository
 
 xmlElements   = None
 
@@ -209,7 +209,7 @@
     if len (nameParts) > 1:
       (self.module, self.name) = nameParts [:2]
 
-    self.fullName = Namespace.createName (self.module, self.name)
+    self.fullName = repository.createName (self.module, self.name)
 
     if not hasattr (self, 'page'):
       self.page = self._parent.page
@@ -269,7 +269,7 @@
     if not hasattr (self, 'module'):
       self.module = self._parent.name
 
-    self.fullName = Namespace.createName (self.module, self.name)
+    self.fullName = repository.createName (self.module, self.name)
 
 
   # ---------------------------------------------------------------------------
@@ -328,4 +328,4 @@
     parent        = self.findParentOfType ('GLModule')
     self.module   = parent.name
     self.language = parent.language
-    self.fullName = Namespace.createName (self.module, self.name)
+    self.fullName = repository.createName (self.module, self.name)

Modified: trunk/gnue-appserver/src/gld/readgld.py
===================================================================
--- trunk/gnue-appserver/src/gld/readgld.py     2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/gld/readgld.py     2005-03-13 10:41:15 UTC (rev 
7194)
@@ -33,7 +33,7 @@
 from gnue.appserver import VERSION
 from gnue.appserver import geasConfiguration
 from gnue.appserver.gld import GLParser
-from gnue.appserver.classrep import Namespace
+from gnue.appserver import repository
 
 from gnue.common.apps import GBaseApp
 
@@ -181,31 +181,34 @@
   # Constructor
   # ---------------------------------------------------------------------------
 
-  def __init__ (self, connections, database, files, modRS = None, clsRS = None,
-      prpRS = None, prcRS = None):
+  def __init__ (self, connections, database, files, moduleLookup = None,
+      classLookup = None, propertyLookup = None, procedureLookup = None):
     """
-    Create a new instance of a gcd reader
+    Create a new instance of a gld reader
 
     @param connections: GConnections instance to be used
     @param database: name of the connection to use (in connection.conf)
     @param files: sequence of filenames to integerate
-    @param modRS: resultSet instance for 'gnue_modules'
-    @param clsRS: resultSet instance for 'gnue_class'
-    @param prpRS: resultSet instance for 'gnue_property'
-    @param prcRS: resultSet instance for 'gnue_procedure'
+    @param moduleLookup: lookup dictionary for 'gnue_modules'
+    @param classLookup: lookup dictionary for 'gnue_class'
+    @param propertyLookup: lookup dictionary for 'gnue_property'
+    @param procedureLookup: lookup dictionary for 'gnue_procedure'
     """
 
     self._connections = connections
     self._database    = database
     self._filenames   = files
-    self._files       = []
+    self._files       = {}
     self._uuidtype    = gConfig ('uuidtype', section = 'appserver').lower ()
 
-    self.__modRS      = modRS
-    self.__clsRS      = clsRS
-    self.__prpRS      = prpRS
-    self.__prcRS      = prcRS
+    self.lpModule    = moduleLookup
+    self.lpClass     = classLookup
+    self.lpProperty  = propertyLookup
+    self.lpProcedure = procedureLookup
 
+    self.labels   = {}
+    self.messages = {}
+
     if not len (self._filenames):
       raise StartupError, u_("No input file specified.")
 
@@ -214,10 +217,11 @@
 
     try:
       for filename in files:
-        self._files.append (openResource (filename))
+        self._files [filename] = openResource (filename)
 
     except IOError, err:
-      for item in self._files:
+      while self._files:
+        (name, item) = self._files.popitem ()
         item.close ()
 
       raise StartupError, u_("Unable to open input file: %s") % \
@@ -234,26 +238,36 @@
     updates the repository using these dictionaries.
     """
 
-    self.labels   = {}
-    self.messages = {}
+    self.labels.clear ()
+    self.messages.clear ()
 
     print _("Loading GNUe language definitions")
 
-    for ix in xrange (len (self._files)):
-      gDebug (1, "Loading gld file '%s'" % self._filenames [ix])
+    while self._files:
+      self.__currentFile, stream = self._files.popitem ()
 
       try:
-        self.__currentFile   = self._filenames [ix]
+        gDebug (1, "Loading gld file '%s'" % self.__currentFile)
+
         self.__currentModule = None
         self.__currentClass  = None
 
         # Load xml file and process all it's objects
-        schema = GLParser.loadFile (self._files [ix])
-        schema.walk (self.__iterateObjects)
+        schema = GLParser.loadFile (stream)
+        try:
+          schema.walk (self.__iterateObjects)
 
+        finally:
+          self.__currentModule = None
+          self.__currentClass  = None
+
+          schema.unlink ()
+          schema = None
+
       finally:
-        self._files [ix].close ()
+        stream.close ()
 
+
     # Replace all references to modules, classes, properties and procedures
     self.__replaceReferences ()
 
@@ -262,6 +276,7 @@
     self.__updateMessages ()
 
 
+
   # ---------------------------------------------------------------------------
   # Iterate over all top level elements
   # ---------------------------------------------------------------------------
@@ -320,7 +335,7 @@
 
 
   # ---------------------------------------------------------------------------
-  # Translate a message into a dictionary for later classrep update
+  # Translate a message into a dictionary for later class-repository update
   # ---------------------------------------------------------------------------
 
   def __translateMessage (self, item):
@@ -343,6 +358,7 @@
         '_file'        : self.__currentFile}
 
 
+
   # ---------------------------------------------------------------------------
   # Get a dictionary with all keys listed in tags and values from sObject
   # ---------------------------------------------------------------------------
@@ -377,41 +393,49 @@
     """
 
     # Build lookup dictionaries
-    modules    = self.__getModuleLookup ()
-    classes    = self.__getClassLookup (modules)
-    properties = self.__getPrLookup (self.__prpRS, 'gnue_property')
-    procedures = self.__getPrLookup (self.__prcRS, 'gnue_procedure')
+    if self.lpModule is None:
+      self.lpModule = self.__getModuleLookup ()
 
+    if self.lpClass is None:
+      self.lpClass = self.__getClassLookup ()
+
+    if self.lpProperty is None:
+      self.lpProperty = self.__getPropertyLookup ()
+
+    if self.lpProcedure is None:
+      self.lpProcedure = self.__getProcedureLookup ()
+
     # Replace references for all labels
     for label in self.labels.values ():
       classname = label ['gnue_class'].lower ()
-      classid   = classes.get (classname)
+      classid   = self.lpClass.get (classname)
       if classid is None:
         raise ClassNotFoundError, (label ['gnue_class'], label ['_file'])
 
       del label ['gnue_class']
 
       if label ['gnue_property'] is not None:
-        (module, name) = Namespace.splitName (label ['gnue_property'].lower ())
-        key  = "%s.%s_%s" % (classid, modules [module], name)
-        ckey = "%s.%s_get%s" % (classid, modules [module], name)
-        if properties.has_key (key):
-          label ['gnue_property'] = properties [key]
+        (module, name) = repository.splitName (label ['gnue_property'].lower 
())
+        key  = "%s.%s_%s" % (classid, self.lpModule [module], name)
+        ckey = "%s.%s_get%s" % (classname, module, name)
+
+        if self.lpProperty.has_key (key):
+          label ['gnue_property']  = self.lpProperty [key]
           label ['gnue_procedure'] = None
 
-        elif procedures.has_key (ckey):
-          label ['gnue_procedure'] = procedures [ckey]
-          label ['gnue_property'] = None
+        elif self.lpProcedure.has_key (ckey):
+          label ['gnue_procedure'] = self.lpProcedure [ckey]
+          label ['gnue_property']  = None
 
         else:
           raise PropertyNotFoundError, \
               (classname, label ['gnue_property'], label ['_file'])
 
       elif label ['gnue_procedure'] is not None:
-        (module, name) = Namespace.splitName (label ['gnue_procedure'].lower 
())
-        key = "%s.%s_%s" % (classid, modules [module], name)
-        ckey = "%s.%s_get%s" % (classid, modules [module], name)
-        ref = procedures.get (key) or procedures.get (ckey)
+        (module, name) = repository.splitName (label 
['gnue_procedure'].lower())
+        key  = "%s.%s_%s" % (classname, module, name)
+        ckey = "%s.%s_get%s" % (classname, module, name)
+        ref  = self.lpProcedure.get (key, self.lpProcedure.get (ckey))
         if ref is None:
           raise ProcedureNotFoundError, \
               (classname, label ['gnue_procedure'], label ['_file'])
@@ -423,7 +447,7 @@
 
     # Replace references for all messages
     for message in self.messages.values ():
-      message ['gnue_module'] = modules [message ['gnue_module'].lower ()]
+      message ['gnue_module'] = self.lpModule [message ['gnue_module'].lower 
()]
       del message ['_file']
 
 
@@ -441,88 +465,129 @@
     
     result = {}
 
-    if self.__modRS is None:
-      src = self.__openSource ('gnue_module', ['gnue_id', 'gnue_name'])
-      self.__modRS = src.createResultSet ()
+    resultSet = self.__openSource ('gnue_module',
+                                   ['gnue_id', 'gnue_name']).createResultSet ()
+    try:
+      rec = resultSet.firstRecord ()
+      while rec is not None:
+        name = rec.getField ('gnue_name')
+        gid  = rec.getField ('gnue_id')
 
-    rec = self.__modRS.firstRecord ()
-    while rec is not None:
-      name = rec.getField ('gnue_name')
-      gid  = rec.getField ('gnue_id')
+        result [gid]           = name
+        result [name.lower ()] = gid
 
-      result [gid]           = name
-      result [name.lower ()] = gid
+        rec = resultSet.nextRecord ()
 
-      rec = self.__modRS.nextRecord ()
+      return result
 
-    return result
+    finally:
+      resultSet.close ()
 
 
   # ---------------------------------------------------------------------------
   # Create a lookup dictionary for classes
   # ---------------------------------------------------------------------------
 
-  def __getClassLookup (self, modules):
+  def __getClassLookup (self):
     """
     This function creates a lookup dictionary for classes, where the full
     qualified name is the key and the gnue_id is the value.
 
-    @param modules: lookup dictionary for modules
     @return: dictionary with class mapping
     """
 
     result = {}
 
-    if self.__clsRS is None:
-      src = self.__openSource ('gnue_class',
-                               ['gnue_id', 'gnue_module', 'gnue_name'])
-      self.__clsRS = src.createResultSet ()
+    resultSet = self.__openSource ('gnue_class',
+                    ['gnue_id', 'gnue_module', 'gnue_name']).createResultSet ()
+    try:
+      rec = resultSet.firstRecord ()
+      while rec is not None:
+        module = self.lpModule.get (rec.getField ('gnue_module'))
+        name   = rec.getField ('gnue_name')
+        gid    = rec.getField ('gnue_id')
+        key    = repository.createName (module, name)
 
-    rec = self.__clsRS.firstRecord ()
-    while rec is not None:
-      module = rec.getField ('gnue_module')
-      name   = rec.getField ('gnue_name')
-      key    = Namespace.createName (modules [module.lower ()], name)
-      result [key.lower ()] = rec.getField ('gnue_id')
+        result [key.lower ()] = gid
+        result [gid]          = key.lower ()
 
-      rec = self.__clsRS.nextRecord ()
+        rec = resultSet.nextRecord ()
 
-    return result
+      return result
 
+    finally:
+      resultSet.close ()
 
+
   # ---------------------------------------------------------------------------
-  # Create a lookup dictionary for properties or procedures
+  # Build a lookup-dictionary for properties
   # ---------------------------------------------------------------------------
 
-  def __getPrLookup (self, resultSet, table):
+  def __getPropertyLookup (self):
     """
-    This function creates a lookup dictionary for properties or procedures.
+    This function creates a lookup dictionary for properties where the key is
+    constructed from "classid.moduleid_propertyname".
+    """
 
-    @param resultSet: a resultSet instance to use or None if a new resultSet
-        should be created. 
-    @param table: if no resultSet is given this tablename will be used to
-        create a new one.
-    @return: dictionary with the property- or procedure-mapping
+    result = {}
+
+    resultSet = self.__openSource ('gnue_property', ['gnue_id',
+          'gnue_module', 'gnue_class', 'gnue_name', 'gnue_type', 'gnue_length',
+          'gnue_scale', 'gnue_nullable', 'gnue_comment']).createResultSet ()
+
+    try:
+      rec = resultSet.firstRecord ()
+      while rec is not None:
+        mid  = rec.getField ('gnue_module')
+        cid  = rec.getField ('gnue_class')
+        name = rec.getField ('gnue_name')
+        key  = "%s.%s_%s" % (cid, mid, name.lower ())
+
+        result [key] = rec.getField ('gnue_id')
+
+        rec  = resultSet.nextRecord ()
+
+      return result
+
+    finally:
+      resultSet.close ()
+
+
+  # ---------------------------------------------------------------------------
+  # Build a lookup-dictionary for procedures
+  # ---------------------------------------------------------------------------
+
+  def __getProcedureLookup (self):
     """
+    This function creates a procedure lookup dictionary where the key is built
+    from "classname.modulename_procedurename".
+    """
 
     result = {}
 
-    if resultSet is None:
-      src = self.__openSource (table,
-                         ['gnue_id', 'gnue_module', 'gnue_class', 'gnue_name'])
-      resultSet = src.createResultSet ()
+    resultSet = self.__openSource ('gnue_procedure', ['gnue_id',
+        'gnue_module', 'gnue_class', 'gnue_name', 'gnue_type', 'gnue_length',
+        'gnue_scale', 'gnue_nullable', 'gnue_comment', 'gnue_code',
+        'gnue_language']).createResultSet ()
 
-    rec = resultSet.firstRecord ()
-    while rec is not None:
-      key = "%s.%s_%s" % (rec ['gnue_class'], rec ['gnue_module'],
-                          rec ['gnue_name'])
-      result [key.lower ()] = rec ['gnue_id']
+    try:
+      rec = resultSet.firstRecord ()
+      while rec is not None:
+        mName = self.lpModule.get (rec.getField ('gnue_module'))
+        cName = self.lpClass.get (rec.getField ('gnue_class'))
+        pName = rec.getField ('gnue_name')
+        key   = "%s.%s_%s" % (cName, mName, pName)
 
-      rec = resultSet.nextRecord ()
+        result [key.lower ()] = rec.getField ('gnue_id')
 
-    return result
+        rec  = resultSet.nextRecord ()
 
+      return result
 
+    finally:
+      resultSet.close ()
+
+
   # ---------------------------------------------------------------------------
   # Create a new datasource for a given class
   # ---------------------------------------------------------------------------
@@ -562,20 +627,24 @@
     # Load and update all labels. To identify a label without gnue_id, use
     # 'gnue_language', 'gnue_property' and 'gnue_procedure'.
     rSet = src.createResultSet ()
-    cond = ['gnue_language', 'gnue_property', 'gnue_procedure']
-    stat = self.__processResultSet (rSet, self.labels, cond)
+    try:
+      cond = ['gnue_language', 'gnue_property', 'gnue_procedure']
+      stat = self.__processResultSet (rSet, self.labels, cond)
 
-    if stat [0] + stat [1]:
-      self._connections.commitAll ()
+      if stat [0] + stat [1]:
+        self._connections.commitAll ()
 
-    msg = u_("  Labels  : %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-             "unchanged.") \
-          % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]}
+      msg = u_("  Labels  : %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
+               "unchanged.") \
+            % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]}
 
-    gDebug (1, msg)
-    print o(msg)
+      gDebug (1, msg)
+      print o(msg)
 
+    finally:
+      rSet.close ()
 
+
   # ---------------------------------------------------------------------------
   # Update all messages in the repository
   # ---------------------------------------------------------------------------
@@ -591,20 +660,24 @@
     # Load and update all messages. To identify a message without a gnue_id
     # 'gnue_language', 'gnue_module' and 'gnue_name' will be used.
     rSet = src.createResultSet ()
-    cond = ['gnue_language', 'gnue_module', 'gnue_name']
-    stat = self.__processResultSet (rSet, self.messages, cond)
+    try:
+      cond = ['gnue_language', 'gnue_module', 'gnue_name']
+      stat = self.__processResultSet (rSet, self.messages, cond)
 
-    if stat [0] + stat [1]:
-      self._connections.commitAll ()
+      if stat [0] + stat [1]:
+        self._connections.commitAll ()
 
-    msg = u_("  Messages: %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
-                "unchanged.") \
-          % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]}
+      msg = u_("  Messages: %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
+                  "unchanged.") \
+            % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]}
 
-    gDebug (1, msg)
-    print o(msg)
+      gDebug (1, msg)
+      print o(msg)
 
+    finally:
+      rSet.close ()
 
+
   # ---------------------------------------------------------------------------
   # Update a given resultset using a dictionary of records
   # ---------------------------------------------------------------------------

Added: trunk/gnue-appserver/src/repository.py
===================================================================
--- trunk/gnue-appserver/src/repository.py      2005-03-13 10:03:11 UTC (rev 
7193)
+++ trunk/gnue-appserver/src/repository.py      2005-03-13 10:41:15 UTC (rev 
7194)
@@ -0,0 +1,1069 @@
+# GNU Enterprise Application Server - Class Repository
+#
+# Copyright 2001-2005 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+from gnue.common.apps import errors
+from gnue.common.utils.CaselessDict import CaselessDict
+
+from gnue.appserver import data
+from gnue.appserver.language import Session
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class ModuleNotFoundError (errors.ApplicationError):
+  def __init__ (self, module):
+    msg = u_("Module '%s' not found in class repository") % module
+    errors.ApplicationError.__init__ (self, msg)
+
+class ClassNotFoundError (errors.ApplicationError):
+  def __init__ (self, classname):
+    msg = u_("Class '%s' not found in class repository") % classname
+    errors.ApplicationError.__init__ (self, msg)
+
+class FilterNotFoundError (errors.ApplicationError):
+  def __init__ (self, classname):
+    msg = u_("Filter '%s' not found in class repository") % classname
+    errors.ApplicationError.__init__ (self, msg)
+
+class PropertyNotFoundError (errors.ApplicationError):
+  def __init__ (self, name, classname):
+    msg = u_("Class '%(classname)s' has no property '%(property)s'") \
+          % {"classname": classname, "property": name}
+    errors.ApplicationError.__init__ (self, msg)
+
+class ProcedureNotFoundError (errors.ApplicationError):
+  def __init__ (self, name, classname):
+    msg = u_("Class '%(classname)s' has no procedure '%(procedure)s'") \
+          % {"classname": classname, "procedure": name}
+    errors.ApplicationError.__init__ (self, msg)
+
+class ParameterNotFoundError (errors.ApplicationError):
+  def __init__ (self, parameter, procedure):
+    msg = u_("Procedure '%(procedure)s' has no parameter '%(parameter)s'") \
+          % {"procedure": procedure, "parameter": parameter}
+    errors.ApplicationError.__init__ (self, msg)
+
+class MissingFilterClassError (errors.ApplicationError):
+  def __init__ (self, classname, filterid):
+    msg = u_("Filter '%(filter)s' defined in class '%(classname)s' not found "
+             "in class repository") \
+          % {'classname': classname, 'filter': filterid}
+    errors.ApplicationError.__init__ (self, msg)
+
+class ValidationError (errors.ApplicationError):
+  pass
+
+class TypeNameError (ValidationError):
+  def __init__ (self, typename):
+    msg = u_("'%s' is not a valid type") % typename
+    ValidationError.__init__ (self, msg)
+
+class TypeFormatError (ValidationError):
+  pass
+
+class ParameterValidationError (ValidationError):
+  def __init__ (self, procedure, parameter, error):
+    msg = u_("Error validating parameter '%(parameter)s' of procedure "
+             "'%(procedure)s': %(errors)s") \
+          % {'procedure': procedure, 'parameter': parameter, 'error': error}
+    ValidationError.__init__ (self, msg)
+
+class InvalidNameError (errors.ApplicationError):
+  def __init__ (self, name):
+    msg = u_("'%s' is not a valid, fully qualified identifier") % name
+    errors.ApplicationError.__init__ (self, name)
+
+# =============================================================================
+# This class implements the class repository
+# =============================================================================
+
+class Repository:
+  """
+  This class provides access to the class repository of AppServer. To load the
+  repository from the backend database call the method 'load'. After this the
+  following instance variables are available:
+
+  @ivar modules: dictionary with all modules available. The dictionary has 
both,
+      the modulenames and their gnue_id's as keys.
+  @ivar classes: dictionary with all classes available. The dictionary has
+      both, the classnames and their gnue_id's as keys.
+  @ivar filters: dictionary with all filter classes available. The dictionary
+      uses the 'gnue_id' as keys.
+  """
+
+  # ---------------------------------------------------------------------------
+  # Create a new repository instance
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session):
+    """
+    @param session: geasSession instance to use for data retrieval
+    """
+
+    self._session     = session
+    self._langSession = Session.InternalSession (session.sm)
+    self._connection  = data.connection (session.connections, session.database)
+
+    self.modules = None
+    self.classes = None
+    self.filters = None
+
+
+  # ---------------------------------------------------------------------------
+  # Load the repository into modules and classes
+  # ---------------------------------------------------------------------------
+
+  def load (self):
+    """
+    This function reloads the whole class repository, which is available
+    through the properties 'modules' and 'classes'.
+    """
+
+    modules    = CaselessDict (ModuleNotFoundError)
+    classes    = CaselessDict (ClassNotFoundError)
+    filters    = CaselessDict (FilterNotFoundError)
+
+    properties = {}
+    procedures = {}
+
+    try:
+      # First load all raw data from the gnue_* tables
+      self.__loadRawData ()
+
+      # Wrap all modules
+      for (key, value) in self.__rawModules.items ():
+        module = Module (self._langSession, value)
+        modules [key] = module
+        modules [module.fullName] = module
+
+      # Wrap all classes and install them into the apropriate module
+      for (key, value) in self.__rawClasses.items ():
+        aClass = Class (self._langSession, value, self.__rawModules)
+        module = aClass.gnue_module
+        modules [module]._installClass (aClass)
+
+        classes [key]             = aClass
+        classes [aClass.fullName] = aClass
+
+        # If a class has a filter defined, we add it to the filter dictionary,
+        # which will be completed right after loading all classes
+        if aClass.gnue_filter is not None:
+          if not self.__rawClasses.has_key (aClass.gnue_filter):
+            raise MissingFilterClassError, (aClass.fullName, 
aClass.gnue_filter)
+
+          filters [aClass.gnue_filter] = None
+
+      # After all classes are loaded, complete the filter dictionary
+      for key in filters.keys ():
+        filters [key] = classes [key]
+
+      # Wrap all properties and install them into the apropriate class
+      for (key, value) in self.__rawProperties.items ():
+        aProperty = Property (self._langSession, value, self.__rawModules)
+        classes [aProperty.gnue_class]._installProperty (aProperty)
+        properties [key] = aProperty
+
+      # Wrap all procedures and link them into a lookup dictionary first
+      for (key, value) in self.__rawProcedures.items ():
+        aProcedure = Procedure (self._langSession, value, self.__rawModules)
+        procedures [key] = aProcedure
+
+      # Now create all parameters and install them to their procedures.
+      for (key, value) in self.__rawParameters.items ():
+        aParameter = Parameter (self._langSession, value)
+        procedures [aParameter.gnue_procedure]._installParameter (aParameter)
+
+      # After having all parameters installed to their procedures, we can then
+      # run their second level initialization. Here it'll be determined wether
+      # a procedure is a calculated field or not. Finally the procedures will
+      # be installed to their corresponding class.
+      for item in procedures.values ():
+        item.secondaryInit (self.__rawModules)
+        classes [item.gnue_class]._installProcedure (item)
+
+      # Now finalize and verify all properties and procedures
+      for item in properties.values ():
+        item.finalize (classes)
+
+      # The verification of procedures implicitly runs a type-check for all
+      # calculated properties.
+      map (verifyProcedure, procedures.values ())
+
+
+      # To finish the build process, all references (unicode-strings) are
+      # replaced by the corresponding wrapper instance. This way a
+      # 'someClass.gnue_module.fullName' will work.
+      for item in modules.values ():
+        item.updateLinks (modules, classes)
+
+    except:
+      raise
+
+    else:
+      # We keep referernces to the old dictionaries before replacing them, so
+      # we can release them later. This eliminates a time gap between having
+      # and old and a new repository available.
+      oldmodules = self.modules
+      oldclasses = self.classes
+      oldfilters = self.filters
+
+      self.modules = modules
+      self.classes = classes
+      self.filters = filters
+
+      # finally, if we had an old repository, release it
+      if oldmodules is not None:
+        self.release (oldmodules, oldclasses, oldfilters)
+
+
+  # ---------------------------------------------------------------------------
+  # Release resources of the repository
+  # ---------------------------------------------------------------------------
+
+  def release (self, modules = None, classes = None, filters = None):
+    """
+    Release the current repository dictionaries so garbage collection still
+    works fine.
+
+    @param modules: module dictionary to release
+    @param classes: class dictionary to release
+    @param filters: filter dictionary to release
+    """
+
+    if modules is None: modules = self.modules
+    if classes is None: classes = self.classes
+    if filters is None: filters = self.filters
+
+    for item in modules.values ():
+      item.updateLinks (None, None, True)
+
+    filters.clear ()
+    classes.clear ()
+    modules.clear ()
+
+
+  # ---------------------------------------------------------------------------
+  # Load the raw data from all repository tables
+  # ---------------------------------------------------------------------------
+
+  def __loadRawData (self):
+    """
+    This function reads all repository tables into dictionaries.
+    """
+
+    self.__rawModules = self.__loadTable (u'gnue_module', [u'gnue_name'])
+    self.__rawClasses = self.__loadTable (u'gnue_class', \
+                                [u'gnue_module', u'gnue_name', u'gnue_filter'])
+    self.__rawProperties = self.__loadTable (u'gnue_property', \
+                  [u'gnue_module', u'gnue_class', u'gnue_name', u'gnue_length',
+                   u'gnue_scale', u'gnue_nullable', u'gnue_type'])
+    self.__rawProcedures = self.__loadTable (u'gnue_procedure', \
+                [u'gnue_module', u'gnue_class', u'gnue_name', u'gnue_language',
+                 u'gnue_length', u'gnue_nullable', u'gnue_scale', 
u'gnue_type'])
+
+    self.__rawParameters = self.__loadTable (u'gnue_parameter', \
+                [u'gnue_procedure', u'gnue_name', u'gnue_type', u'gnue_length',
+                 u'gnue_scale'])
+
+
+  # ---------------------------------------------------------------------------
+  # Load fields from a given table
+  # ---------------------------------------------------------------------------
+
+  def __loadTable (self, table, fields):
+    """
+    This function reads all rows from a table into a dictionary.
+
+    @param table: name of the table to load data from.
+    @param fields: sequence of fields to load per record.
+
+    @return: dictionary with the primary key as key and another dictionary as
+        value, using the fieldnames as keys.
+    """
+
+    result    = {}
+    contents  = {None: (table, None, None, fields)}
+    resultSet = self._connection.query (contents, None, [u'gnue_id'])
+
+    try:
+      rec = resultSet.nextRecord ()
+      while rec is not None:
+        row = result.setdefault (rec.getField (u'gnue_id'), {})
+
+        for field in fields:
+          row [field] = rec.getField (field)
+
+        rec = resultSet.nextRecord ()
+
+    finally:
+      resultSet.close ()
+
+    return result
+
+
+# =============================================================================
+# Base class implementing a repository element
+# =============================================================================
+
+class BaseItem:
+
+  # ---------------------------------------------------------------------------
+  # Create a new instance of a repository item
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session, classname, predefined = None):
+    """
+    This function creates a new instance of a repository item. If a predefined
+    dictionary is given, all it's elements are copied into the instances'
+    __dict__. Access to other attributes will be delegated to the corresponding
+    language interface Object.
+
+    @param session: language interface session
+    @param classname: name of the class wrapped by this item
+    @param predefined: dictionary with predefined values
+    """
+
+    self._session  = session
+    self.__object  = None
+    self.classname = classname
+
+    if predefined is not None:
+      self.__dict__.update (predefined)
+
+
+  # ---------------------------------------------------------------------------
+  # Access to a non-prefdefined attribute
+  # ---------------------------------------------------------------------------
+
+  def __getattr__ (self, attr):
+    """
+    This function delegates property access to the bound language interface
+    object and caches the result for following access.
+
+    @param attr: name of the attribute to retrieve
+    @return: value of the attribute
+    """
+
+    if self.__object is None:
+      self.__object = self._session._get (self.classname, self.gnue_id)
+
+    # Fetch
+    result = getattr (self.__object, attr)
+    self.__dict__ [attr] = result
+
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Dictionary emulation for wrapper instances
+  # ---------------------------------------------------------------------------
+
+  def __getitem__ (self, attr):
+    """
+    This function emulates a dictionary access to the wrapper instance.
+
+    @param attr: attribute to return
+    @return: value of the attribute 'attr'
+    """
+
+    return getattr (self, attr)
+
+
+# =============================================================================
+# This class implements a wrapper for module items of the repository
+# =============================================================================
+
+class Module (BaseItem):
+
+  # ---------------------------------------------------------------------------
+  # Create a new module item of the repository
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session, predefined = None):
+    """
+    @param session: language interface session
+    @param predefined: dictionary with predefined ('builtin') values
+    """
+
+    BaseItem.__init__ (self, session, u'gnue_module', predefined)
+
+    self.classes  = CaselessDict (ClassNotFoundError)
+    self.fullName = self.gnue_name
+
+
+  # ---------------------------------------------------------------------------
+  # Install a class into the module's class list
+  # ---------------------------------------------------------------------------
+
+  def _installClass (self, aClass):
+    """
+    This function adds the given class to the modules' list of classes.
+    @param aClass: Class instance to be added
+    """
+
+    self.classes [aClass.gnue_id]  = aClass
+    self.classes [aClass.fullName] = aClass
+
+
+  # ---------------------------------------------------------------------------
+  # Update links of a module item
+  # ---------------------------------------------------------------------------
+
+  def updateLinks (self, modules, classes, unlink = False):
+    """
+    This class updates links of a module item by updating the links of all it's
+    classes.
+
+    @param modules: dictionary with all modules available
+    @param classes: dictionary with all classes available
+    @param unlink: if set to True, references will be cleared
+    """
+
+    for (key, item) in self.classes.items ():
+      item.updateLinks (modules, classes, unlink)
+
+
+
+# =============================================================================
+# This class implements a class item of the repository
+# =============================================================================
+
+class Class (BaseItem):
+
+  # ---------------------------------------------------------------------------
+  # Create a new class item of the repository
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session, predefined, moduleLookup):
+    """
+    @param session: language interface session
+    @param predefined: dictionary with predefined ('builtin') values
+    @param moduleLookup: (raw) lookup-dictionary with all modules available
+    """
+
+    BaseItem.__init__ (self, session, u'gnue_class', predefined)
+
+    moduleName    = moduleLookup [self.gnue_module] ['gnue_name']
+    self.fullName = createName (moduleName, self.gnue_name)
+    self.table    = self.fullName
+
+    self.properties = CaselessDict (PropertyNotFoundError, self.fullName)
+    self.procedures = CaselessDict (ProcedureNotFoundError, self.fullName)
+
+    self.OnInit     = []
+    self.OnChange   = []
+    self.OnValidate = []
+    self.OnDelete   = []
+
+
+  # ---------------------------------------------------------------------------
+  # Install a new property to the property dictionary of the class
+  # ---------------------------------------------------------------------------
+
+  def _installProperty (self, aProperty):
+    """
+    This function installs a given property to the property dictionary
+
+    @param aProperty: Property instance to be installed
+    """
+
+    self.properties [aProperty.gnue_id]  = aProperty
+    self.properties [aProperty.fullName] = aProperty
+
+
+  # ---------------------------------------------------------------------------
+  # Install a new procedure to the procedure dictionary of the class
+  # ---------------------------------------------------------------------------
+
+  def _installProcedure (self, aProcedure):
+    """
+    This function adds a procedure to the procedure dictionary. If the
+    procedure is a 'calculated property' it also adds it to the property
+    dictionary. If a procedure is a trigger it will be added to the apropriate
+    trigger sequence.
+
+    @param aProcedure: procedure to be installed
+    """
+
+    self.procedures [aProcedure.gnue_id]  = aProcedure
+    self.procedures [aProcedure.fullName] = aProcedure
+
+    if aProcedure.isCalculated:
+      aProperty = CalculatedProperty (aProcedure)
+      self._installProperty (aProperty)
+
+    # If the procedure is an OnInit trigger add it to the OnInit sequence. If 
+    # the trigger is defined by the classes' module, it will be the first
+    # trigger to fire.
+    if aProcedure.gnue_name.upper () == 'ONINIT':
+      if aProcedure.gnue_module == self.gnue_module:
+        self.OnInit.insert (0, aProcedure)
+      else:
+        self.OnInit.append (aProcedure)
+
+    # If the procedure is an OnValidate trigger add it to the trigger sequence.
+    # The OnValidate trigger defined by the classes' module will be the last
+    # one fired.
+    if aProcedure.gnue_name.upper () == 'ONVALIDATE':
+      if aProcedure.gnue_module == self.gnue_module:
+        self.OnValidate.append (aProcedure)
+      else:
+        self.OnValidate.insert (0, aProcedure)
+
+    # If the procedure is an OnChange trigger add it to the trigger sequence.
+    if aProcedure.gnue_name.upper () == 'ONCHANGE':
+      self.OnChange.append (aProcedure)
+
+    # If the procedure is an OnDelete trigger add it to the trigger sequence.
+    if aProcedure.gnue_name.upper () == 'ONDELETE':
+      self.OnDelete.append (aProcedure)
+
+
+  # ---------------------------------------------------------------------------
+  # Update all links within a class wrapper
+  # ---------------------------------------------------------------------------
+
+  def updateLinks (self, modules, classes, unlink = False):
+    """
+    This class updates links of a class item by updating the links of all it's
+    properties and procedures.
+
+    @param modules: dictionary with all modules available
+    @param unlink: if set to True, references will be cleared
+    """
+
+    if unlink:
+      self.gnue_module = None
+      self.gnue_filter = None
+
+      del self.OnInit [:]
+      del self.OnChange [:]
+      del self.OnValidate [:]
+      del self.OnDelete [:]
+
+    else:
+      if not isinstance (self.gnue_module, Module):
+        self.gnue_module = modules [self.gnue_module]
+
+      if self.gnue_filter and not isinstance (self.gnue_filter, Class):
+        self.gnue_filter = classes [self.gnue_filter]
+
+    for item in self.properties.values () + self.procedures.values ():
+      item.updateLinks (self, modules, unlink)
+
+
+
+# =============================================================================
+# This class wraps a property item of the repository
+# =============================================================================
+
+class Property (BaseItem):
+  
+  # ---------------------------------------------------------------------------
+  # Create a new property item
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session, predefined, moduleLookup):
+    """
+    @param session: language interface session
+    @param predefined: dictionary with predefined ('builtin') values
+    @param moduleLookup: (raw) lookup-dictionary with all modules available
+    """
+
+    updateTypeInfo (predefined)
+    BaseItem.__init__ (self, session, u'gnue_property', predefined)
+
+    moduleName        = moduleLookup [self.gnue_module]['gnue_name']
+    self.fullName     = createName (moduleName, self.gnue_name)
+    self.column       = self.fullName
+
+    self.isCalculated    = False
+    self.isReference     = False
+    self.referencedClass = None
+
+
+  # ---------------------------------------------------------------------------
+  # Update the links of a property item
+  # ---------------------------------------------------------------------------
+
+  def updateLinks (self, aClass, modules, unlink = False):
+    """
+    This function updates the links of a property item to it's module and
+    class. If unlink is set the references are cleared.
+
+    @param aClass: Class instance the property belongs to
+    @param modules: Module dictionary with all modules available
+    @param unlink: this boolean Flag determines wether to establish links or to
+        break them
+    """
+
+    if unlink:
+      self.gnue_module = None
+      self.gnue_class  = None
+      self.referencedClass = None
+
+    else:
+      self.gnue_class = aClass
+      if not isinstance (self.gnue_module, Module):
+        self.gnue_module = modules [self.gnue_module]
+
+
+  # ---------------------------------------------------------------------------
+  # Finalize the definition of a property
+  # ---------------------------------------------------------------------------
+
+  def finalize (self, classes):
+    """
+    This function verifies the type of the property and set's the reference
+    flags for rerference properties.
+
+    @param classes: dictionary with all classes available
+    """
+
+    r = verifyType (self.gnue_type, self.gnue_length, self.gnue_scale, classes)
+
+    self.isReference     = r is not None
+    self.referencedClass = r
+
+
+
+# =============================================================================
+# This class wraps a calculated property (= special procedures)
+# =============================================================================
+
+class CalculatedProperty (BaseItem):
+
+  # ---------------------------------------------------------------------------
+  # Create a new calculated property
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, aProcedure):
+    """
+    @param aProcedure: procedure to bind as calculated property
+    """
+
+    predefined = {
+      'gnue_id'      : aProcedure.gnue_id,
+      'gnue_name'    : aProcedure.calcName,
+      'gnue_type'    : aProcedure.gnue_type,
+      'gnue_length'  : aProcedure.gnue_length,
+      'gnue_scale'   : aProcedure.gnue_scale,
+      'gnue_module'  : aProcedure.gnue_module,
+      'gnue_class'   : aProcedure.gnue_class,
+      'gnue_nullable': aProcedure.gnue_nullable}
+    updateTypeInfo (predefined)
+
+    BaseItem.__init__ (self, aProcedure._session, u'gnue_procedure', 
predefined)
+
+    self.fullName  = aProcedure.calcFullName
+    self.column    = None
+
+    self.isReference     = False
+    self.referencedClass = None
+    self.isCalculated    = True
+    self.procedure       = aProcedure
+
+
+  # ---------------------------------------------------------------------------
+  # Update the links of a calculated property item
+  # ---------------------------------------------------------------------------
+
+  def updateLinks (self, aClass, modules, unlink = False):
+    """
+    If in unlink mode this function clears the pointer to the bound procedure.
+
+    @param aClass: Class instance the property belongs to
+    @param modules: Module dictionary with all modules available
+    @param unlink: this boolean Flag determines wether to establish links or to
+        break them
+    """
+
+    if unlink:
+      self.gnue_module = None
+      self.gnue_class  = None
+      self.procedure   = None
+
+    else:
+      self.gnue_class = aClass
+      if not isinstance (self.gnue_module, Module):
+        self.gnue_module = modules [self.gnue_module]
+
+
+
+
+# =============================================================================
+# This class wraps a procedure item of the repository
+# =============================================================================
+
+class Procedure (BaseItem):
+
+  # ---------------------------------------------------------------------------
+  # Create a new procedure wrapper
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session, predefined, moduleLookup):
+    """
+    @param session: language interface session
+    @param predefined: dictionary with predefined ('builtin') values
+    @param moduleLookup: (raw) lookup-dictionary with all modules available
+    """
+
+    BaseItem.__init__ (self, session, u'gnue_procedure', predefined)
+
+    moduleName    = moduleLookup [self.gnue_module]['gnue_name']
+    self.fullName = createName (moduleName, self.gnue_name)
+
+    self.isCalculated = False
+    self.calcFullName = None
+    self.calcName     = None
+
+    self.parameters = CaselessDict (ParameterNotFoundError)
+
+
+  # ---------------------------------------------------------------------------
+  # Second level initialization for a procedure
+  # ---------------------------------------------------------------------------
+
+  def secondaryInit (self, moduleLookup):
+    """
+    This function determines wether a procedure can be used as a calculated
+    field or not. If so the flag 'isCalcualted' will be set.
+
+    @param moduleLookup: lookup dictionary for modules
+    """
+
+    self.isCalculated = self.gnue_type is not None and \
+        not len (self.parameters) and self.gnue_name [:3].lower () == 'get'
+
+    if self.isCalculated:
+      self.calcName     = self.gnue_name [3:]
+      moduleName        = moduleLookup [self.gnue_module]['gnue_name']
+      self.calcFullName = createName (moduleName, self.calcName)
+
+
+  # ---------------------------------------------------------------------------
+  # Install a parameter to the procedures parameter dictionary
+  # ---------------------------------------------------------------------------
+
+  def _installParameter (self, aParameter):
+    """
+    This function installs the given parameter to the procedure's parameter
+    dictionary.
+
+    @param aParameter: the parameter to be installed.
+    """
+
+    self.parameters [aParameter.gnue_id]  = aParameter
+    self.parameters [aParameter.fullName] = aParameter
+
+
+  # ---------------------------------------------------------------------------
+  # Update the links of a procedure item
+  # ---------------------------------------------------------------------------
+
+  def updateLinks (self, aClass, modules, unlink = False):
+    """
+    This function updates the links of a procedure item to it's module and
+    class. If unlink is set the references are cleared.
+
+    @param aClass: Class instance the procedure belongs to
+    @param modules: Module dictionary with all modules available
+    @param unlink: this boolean Flag determines wether to establish links or to
+        break them
+    """
+
+    if unlink:
+      self.gnue_module = None
+      self.gnue_class  = None
+
+    else:
+      self.gnue_class = aClass
+      if not isinstance (self.gnue_module, Module):
+        self.gnue_module = modules [self.gnue_module]
+
+    for param in self.parameters.values ():
+      param.updateLinks (self, unlink)
+
+
+
+# =============================================================================
+# This class implements a parameter item of the repository
+# =============================================================================
+
+class Parameter (BaseItem):
+
+  # ---------------------------------------------------------------------------
+  # Create a new parameter wrapper instance
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, session, predefined):
+    """
+    @param session: language interface session
+    @param predefined: dictionary with predefined ('builtin') values
+    """
+
+    BaseItem.__init__ (self, session, u'gnue_parameter', predefined)
+    self.fullName = self.gnue_name
+
+    if NONREF_TYPES.has_key (self.gnue_type):
+      self.dbType = self.gnue_type
+    else:
+      self.dbType = REF_TYPE
+
+
+  # ---------------------------------------------------------------------------
+  # Update links
+  # ---------------------------------------------------------------------------
+
+  def updateLinks (self, aProcedure, unlink = False):
+    """
+    This functions updates the link to the owning procedure.
+
+    @param aProcedure: the owning procedure
+    @param unlink: if set to True the reference will be cleared
+    """
+
+    if unlink:
+      self.gnue_procedure = None
+
+    else:
+      self.gnue_procedure = aProcedure
+
+
+
+# =============================================================================
+# Type checking support
+# =============================================================================
+
+NONREF_TYPES = {'boolean': True, 'date'  : True, 'datetime': True,
+                'number' : True, 'string': True, 'time'    : True}
+BASE_TYPES   = {'id': True}
+BASE_TYPES.update (NONREF_TYPES)
+
+NOLS_TYPES   = {'id': 1, 'date': 1, 'time': 1, 'datetime': 1, 'boolean': 1}
+
+REF_TYPE     = "string"
+REF_LENGTH   = 32
+REF_SCALE    = 0
+
+
+# -----------------------------------------------------------------------------
+# Check if a combination of typename, length and scale is valid
+# -----------------------------------------------------------------------------
+
+def verifyBasetype (typename, length, scale):
+  """
+  This function verifies a given typename with length and scale. If this
+  combination makes no sense a TypeFormatError will be raised. If typename
+  is no valid base type a TypeNameError will be raised.
+
+  @param typename: name of the datatype
+  @param length: length of the datatype
+  @param scale: scale of the datatype
+  """
+
+  if not BASE_TYPES.has_key (typename):
+    raise TypeNameError, (typename)
+
+  # A string type must not have a scale
+  if typename == 'string':
+    if scale:
+      raise TypeFormatError, u_("string does not support 'scale'")
+
+  # All of the following types must not have length nor scale
+  if NOLS_TYPES.has_key (typename):
+    if length:
+      raise TypeFormatError, u_("%s does not support 'length'") % typename
+    if scale:
+      raise TypeFormatError, u_("%s does not support 'scale'") % typename
+
+  # A number must have at least a 'length'
+  if typename == 'number':
+    if not length:
+      raise TypeFormatError, u_("number without 'length'")
+
+
+# -----------------------------------------------------------------------------
+# Verify a given type
+# -----------------------------------------------------------------------------
+
+def verifyType (typename, length, scale, classes):
+  """
+  This function verifies a given type, length and scale combination, optionally
+  using the given class dictionary for lookups of references.
+
+  @param typename: name of the datatype
+  @param length: length of the datatype
+  @param scale: scale of the datatype
+  @param classes: class dictionary to check for reference types
+
+  @return: If 'typename' is a reference type this function returns the class
+      definition of this reference type, otherwise None
+  """
+
+  if classes.has_key (typename):
+    if length:
+      raise TypeFormatError, u_("Reference types must not have a 'length'")
+
+    if scale:
+      raise TypeFormatError, u_("Reference types must not have a 'scale'")
+
+    return classes [typename]
+
+  else:
+    verifyBasetype (typename, length, scale)
+    return None
+
+
+# -----------------------------------------------------------------------------
+# Verify a procedure definition
+# -----------------------------------------------------------------------------
+
+def verifyProcedure (aProc):
+  """
+  This function checks the resulttype of a procedure definition, and all
+  parameter types (if available).
+
+  @param aProc: procedure wrapper item to be checked
+  """
+
+  # If a result type is specified, check it
+  if aProc.gnue_type is not None:
+    verifyBasetype (aProc.gnue_type, aProc.gnue_length, aProc.gnue_scale)
+
+  else:
+    # otherwise there must not be anything concerning a result type
+    if aProc.gnue_length:
+      raise TypeFormatError, u_("%s: Procedure has no result, but a 'length' "
+                                "is specified.") % aProc.fullName
+    if aProc.gnue_scale:
+      raise TypeFormatError, u_("%s: Procedure has no result, but a 'scale' "
+                                "is specified.") % aProc.fullName
+
+  # verify all given parameter types
+  for pa in aProc.parameters.values ():
+    try:
+      verifyBasetype (pa.gnue_type, pa.gnue_length, pa.gnue_scale)
+
+    except ValidationError, vErr:
+      raise ParameterValidationError, \
+          (aProc.fullName, pa.fullName, vErr.message)
+
+
+# -----------------------------------------------------------------------------
+# Create a type information dictionary for a given wrapper item
+# -----------------------------------------------------------------------------
+
+def updateTypeInfo (item):
+  """
+  This function updates all type information in a given dictionary. It assumes
+  to find the keys 'gnue_type', 'gnue_length' and 'gnue_scale' in the
+  dictionary. After updating the dictionary will contain the following
+  additional keys: fullType, dbFullType, dbType, dbLength and dbScale
+
+  @param item: dictionary to update type information
+  """
+
+  gType  = dbType   = fullType = item ['gnue_type']
+  length = dbLength = item ['gnue_length']
+  scale  = dbScale  = item ['gnue_scale']
+
+  if gType in ["string", "number"]:
+    if gType == "number" and length and scale:
+      fullType = "%s(%d,%d)" % (gType, length, scale)
+
+    elif length:
+      fullType = "%s(%d)" % (gType, length)
+
+  # build database specific type information
+  if not NONREF_TYPES.has_key (gType):
+    (dbType, dbLength, dbScale) = (REF_TYPE, REF_LENGTH, REF_SCALE)
+
+  dbFullType = dbType
+  if dbType in ["string", "number"]:
+    if dbType == "number" and dbLength and dbScale:
+      dbFullType = "%s(%d,%d)" % (dbType, dbLength, dbScale)
+
+    elif dbLength:
+      dbFullType = "%s(%d)" % (dbType, dbLength)
+
+  item.update ({'fullType'  : fullType,
+                'dbFullType': dbFullType,
+                'dbType'    : dbType,
+                'dbLength'  : dbLength,
+                'dbScale'   : dbScale})
+
+
+# -----------------------------------------------------------------------------
+# Create a fully qualified name from namespace and identifier
+# -----------------------------------------------------------------------------
+
+def createName (namespace, identifier):
+  """
+  This function creates a fully qualified name from namespace and identifier.
+  If the result is not a valid name, an InvalidNameError will be raised.
+
+  @param namespace: the namespace to use
+  @param identifier: the identifier to use
+
+  @return: fully qualified name: 'namespace_idendifier'
+  """
+
+  result = "%s_%s" % (namespace, identifier)
+
+  if len (result.split ('_')) != 2:
+    raise InvalidNameError, result
+
+  return result
+
+
+# -----------------------------------------------------------------------------
+# Split a fully qualified name into namespace and identifier
+# -----------------------------------------------------------------------------
+
+def splitName (name):
+  """
+  This function splits the given name into namespace and identifier parts. If
+  name does not contain a namespace at all, it will be left empty. If the
+  resulting tuple has more than two parts an InvalidNameError will be raised.
+
+  @param name: the name to be split into namespace and identifier
+
+  @return: tuple (namespace, identifier) where namespace could be an empty
+      string if name had no namespace information at all
+  """
+
+  parts = name.split ('_')
+  items = len (parts)
+
+  if items == 1:
+    result = ('', name)
+
+  elif items == 2:
+    result = tuple (parts)
+
+  else:
+    raise InvalidNameError, name
+
+  return result


Property changes on: trunk/gnue-appserver/src/repository.py
___________________________________________________________________
Name: svn:keywords
   + Id





reply via email to

[Prev in Thread] Current Thread [Next in Thread]