commit-gnue
[Top][All Lists]
Advanced

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

r6454 - in trunk: gnue-appserver/grpc gnue-appserver/share gnue-appserve


From: johannes
Subject: r6454 - in trunk: gnue-appserver/grpc gnue-appserver/share gnue-appserver/src gnue-appserver/src/gcd gnue-common/src/datasources/drivers/appserver/appserver
Date: Tue, 5 Oct 2004 03:14:06 -0500 (CDT)

Author: johannes
Date: 2004-10-05 03:14:04 -0500 (Tue, 05 Oct 2004)
New Revision: 6454

Added:
   trunk/gnue-appserver/src/geasFilter.py
Modified:
   trunk/gnue-appserver/grpc/appserver.grpc
   trunk/gnue-appserver/share/gnue.gsd
   trunk/gnue-appserver/src/gcd/GCParser.py
   trunk/gnue-appserver/src/gcd/readgcd.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-common/src/datasources/drivers/appserver/appserver/Connection.py
Log:
*) Added support for arbitrary filters to appserver
*) Added getFilters () RPC call to appserver
*) gnue-readgcd now supports definition of indices


Modified: trunk/gnue-appserver/grpc/appserver.grpc
===================================================================
--- trunk/gnue-appserver/grpc/appserver.grpc    2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/grpc/appserver.grpc    2004-10-05 08:14:04 UTC (rev 
6454)
@@ -56,5 +56,8 @@
       <argument name="procedurename" type="string"/>
       <argument name="parameters" type="stringlist"/>
     </method>
+    <method name="getFilters" return="struct">
+      <argument name="language" type="string"/>
+    </method>
   </service>
 </gnurpc>

Modified: trunk/gnue-appserver/share/gnue.gsd
===================================================================
--- trunk/gnue-appserver/share/gnue.gsd 2004-10-04 17:03:32 UTC (rev 6453)
+++ trunk/gnue-appserver/share/gnue.gsd 2004-10-05 08:14:04 UTC (rev 6454)
@@ -65,8 +65,8 @@
                description="Module that defined this class" />
         <field name="gnue_name" type="string" length="35" nullable="N"
                description="Classname without modulename" />
-        <field name="gnue_filter" type="string" length="35"
-               description="Master-Class of the class" />
+        <field name="gnue_filter" type="string" length="32"
+               description="Filter-Class of the class" />
       </fields>
       <indexes/>
       <constraints>
@@ -74,6 +74,10 @@
           <constraintfield name="gnue_module"/>
           <constraintref name="gnue_id" table="gnue_module"/>
         </constraint>
+        <constraint name="fk_gnue_class_gnue_filter" type="foreignkey">
+          <constraintfield name="gnue_filter"/>
+          <constraintref name="gnue_id" table="gnue_class"/>
+        </constraint>
       </constraints>
       <primarykey name="pk_gnue_class">
         <pkfield name="gnue_id"/>
@@ -264,49 +268,6 @@
       </primarykey>
     </table>
 
-    <!-- ============================================================ -->
-    <!-- Company                                                      -->
-    <!-- ============================================================ -->
-    <table name="gnue_company">
-      <fields>
-        <field name="gnue_id" type="string" length="32" nullable="N"
-               description="Object ID"/>
-        <field name="gnue_code" type="string" length="8" nullable="N" 
-               description="Code of the company"/>
-        <field name="gnue_name" type="string" length="35" nullable="N"
-               description="Name of the company"/>
-      </fields>
-      <indexes/>
-      <constraints/>
-      <primarykey name="pk_gnue_company">
-        <pkfield name="gnue_id"/>
-      </primarykey>
-    </table>
-
-    <!-- ============================================================ -->
-    <!-- Year                                                         -->
-    <!-- ============================================================ -->
-    <table name="gnue_year">
-      <fields>
-        <field name="gnue_id" type="string" length="32" nullable="N"
-               description="Object ID"/>
-        <field name="gnue_company" type="string" length="32" nullable="N" 
-               description="Company this year is assigned to"/>
-        <field name="gnue_code" type="string" length="8" nullable="N" 
-               description="Code of the year"/>
-      </fields>
-      <indexes/>
-      <constraints>
-        <constraint name="fk_gnue_year_gnue_company" type="foreignkey">
-          <constraintfield name="gnue_company"/>
-          <constraintref name="gnue_id" table="gnue_company"/>
-        </constraint>
-      </constraints>
-      <primarykey name="pk_gnue_year">
-        <pkfield name="gnue_id"/>
-      </primarykey>
-    </table>
-
   </tables>
   <data>
 
@@ -383,19 +344,6 @@
           <value field="gnue_module">00000000000000000000000000000000</value>
           <value field="gnue_name">message</value>
         </row>
-        <row>
-          <value field="gnue_comment">GNU Enterprise Company</value>
-          <value field="gnue_id">00000000000000000000000000000090</value>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_name">company</value>
-        </row>
-        <row>
-          <value field="gnue_comment">GNU Enterprise Year</value>
-          <value field="gnue_id">000000000000000000000000000000A0</value>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_name">year</value>
-          <value field="gnue_filter">gnue_company</value>
-        </row>
       </rows>
     </tabledata>
 
@@ -495,11 +443,10 @@
           <value field="gnue_module">00000000000000000000000000000000</value>
           <value field="gnue_class">00000000000000000000000000000020</value>
           <value field="gnue_id">00000000000000000000000000000025</value>
-          <value field="gnue_comment">Master-Class of the class</value>
-          <value field="gnue_length">35</value>
+          <value field="gnue_comment">Filter-Class of the class</value>
           <value field="gnue_name">filter</value>
           <value field="gnue_nullable">TRUE</value>
-          <value field="gnue_type">string</value>
+          <value field="gnue_type">gnue_class</value>
         </row>
 
         <!-- ============================================================ -->
@@ -915,70 +862,6 @@
           <value field="gnue_nullable">TRUE</value>
         </row>
 
-        <!-- ============================================================ -->
-        <!-- Properties of gnue_company                                   -->
-        <!-- ============================================================ -->
-        <row>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_class">00000000000000000000000000000090</value>
-          <value field="gnue_id">00000000000000000000000000000091</value>
-          <value field="gnue_comment">Object ID</value>
-          <value field="gnue_name">id</value>
-          <value field="gnue_nullable">FALSE</value>
-          <value field="gnue_type">id</value>
-        </row>
-        <row>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_class">00000000000000000000000000000090</value>
-          <value field="gnue_id">00000000000000000000000000000092</value>
-          <value field="gnue_comment">Code of the company</value>
-          <value field="gnue_name">code</value>
-          <value field="gnue_nullable">FALSE</value>
-          <value field="gnue_type">string</value>
-          <value field="gnue_length">8</value>
-        </row>
-        <row>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_class">00000000000000000000000000000090</value>
-          <value field="gnue_id">00000000000000000000000000000093</value>
-          <value field="gnue_comment">Name of the company</value>
-          <value field="gnue_name">name</value>
-          <value field="gnue_nullable">FALSE</value>
-          <value field="gnue_type">string</value>
-          <value field="gnue_length">35</value>
-        </row>
-
-        <!-- ============================================================ -->
-        <!-- Properties of gnue_year                                      -->
-        <!-- ============================================================ -->
-        <row>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_class">000000000000000000000000000000A0</value>
-          <value field="gnue_id">000000000000000000000000000000A1</value>
-          <value field="gnue_comment">Object ID</value>
-          <value field="gnue_name">id</value>
-          <value field="gnue_nullable">FALSE</value>
-          <value field="gnue_type">id</value>
-        </row>
-        <row>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_class">000000000000000000000000000000A0</value>
-          <value field="gnue_id">000000000000000000000000000000A2</value>
-          <value field="gnue_comment">Code of the year</value>
-          <value field="gnue_name">code</value>
-          <value field="gnue_nullable">FALSE</value>
-          <value field="gnue_type">string</value>
-          <value field="gnue_length">8</value>
-        </row>
-        <row>
-          <value field="gnue_module">00000000000000000000000000000000</value>
-          <value field="gnue_class">000000000000000000000000000000A0</value>
-          <value field="gnue_id">000000000000000000000000000000A3</value>
-          <value field="gnue_comment">Company this year is assigned to</value>
-          <value field="gnue_name">company</value>
-          <value field="gnue_nullable">FALSE</value>
-          <value field="gnue_type">gnue_company</value>
-        </row>
       </rows>
     </tabledata>
 

Modified: trunk/gnue-appserver/src/gcd/GCParser.py
===================================================================
--- trunk/gnue-appserver/src/gcd/GCParser.py    2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/src/gcd/GCParser.py    2004-10-05 08:14:04 UTC (rev 
6454)
@@ -190,6 +190,30 @@
         },
         'ParentTags': ('procedure',)
       },
+
+      'index': {
+        'BaseClass': GCIndex,
+        'Attributes': {
+          'name': {
+            'Required': True,
+            'Unique'  : True,
+            'Typecase': GTypecast.name},
+          'unique': {
+            'Typecast': GTypecast.boolean,
+            'Default': True},
+          },
+        'ParentTags': ('class',),
+      },
+      'indexfield': {
+        'BaseClass': GCIndexField,
+        'Attributes': {
+          'name': {
+            'Required': True,
+            'Unique': True,
+            'Typecase': GTypecast.name},
+        },
+        'Parenttags': ('index',)
+      },
     }
 
   return GParser.buildImportableTags ('module', xmlElements)
@@ -463,3 +487,29 @@
 class GCParameter (GCTypeDefinition):
   def __init__ (self, parent):
     GCTypeDefinition.__init__ (self, parent, objType = 'GCParameter')
+
+
+# =============================================================================
+# The Index object
+# =============================================================================
+
+class GCIndex (GCObject):
+  def __init__ (self, parent):
+    GCObject.__init__ (self, parent, type = 'GCIndex')
+    self.fields   = []
+    self.fullName = None
+    self.module   = None
+    self._inits.extend ([None, self._complete])
+
+  def _complete (self):
+    self.module   = self.findParentOfType ('GCModule').name
+    self.fullName = "ix_%s" % Namespace.createName (self.module, self.name)
+    self.fields   = self.findChildrenOfType ('GCIndexField')
+
+# =============================================================================
+# The index field object
+# =============================================================================
+
+class GCIndexField (GCObject):
+  def __init__ (self, parent):
+    GCObject.__init__ (self, parent, type = 'GCIndexField')

Modified: trunk/gnue-appserver/src/gcd/readgcd.py
===================================================================
--- trunk/gnue-appserver/src/gcd/readgcd.py     2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/src/gcd/readgcd.py     2004-10-05 08:14:04 UTC (rev 
6454)
@@ -32,6 +32,7 @@
 
 from gnue.appserver import VERSION
 from gnue.appserver.gcd import GCParser
+from gnue.appserver.classrep import Namespace
 
 
 # =============================================================================
@@ -303,7 +304,14 @@
 
       sObject.walk (self.__iterateProcedure)
 
+    elif sObject._type == 'GCIndex':
+      if not defs.has_key ('indices'):
+        defs ['indices'] = []
 
+      defs ['indices'].append ({'name'  : sObject.fullName,
+                                'unique': sObject.unique,
+                                'fields': [f.name for f in sObject.fields]})
+
   # ---------------------------------------------------------------------------
   # Iterate over all child elements of a procedure
   # ---------------------------------------------------------------------------
@@ -400,22 +408,27 @@
 
 
   # ---------------------------------------------------------------------------
+  # Create a new datasource for a given class
+  # ---------------------------------------------------------------------------
+
+  def __openSource (self, classname, fieldList):
+    return GDataSource.DataSourceWrapper (connections = self.connections,
+        attributes = {'name': "dts_%s" % classname,
+                      'database': self.OPTIONS ['connection'],
+                      'table': classname},
+        fields = fieldList, unicodeMode = True)
+
+
+  # ---------------------------------------------------------------------------
   # Update/add modules to the class repository
   # ---------------------------------------------------------------------------
 
   def _updateModules (self):
     """
     """
-    attributes = {'name'    : "dts_gnueModule",
-                  'database': self.OPTIONS ['connection'],
-                  'table'   : 'gnue_module'}
-    fieldList = ['gnue_id', 'gnue_name', 'gnue_comment']
 
-    self._dtsModules = GDataSource.DataSourceWrapper (
-                          connections = self.connections,
-                          attributes  = attributes,
-                          fields      = fieldList,
-                          unicodeMode = True)
+    self._dtsModules = self.__openSource ('gnue_module', ['gnue_id',
+        'gnue_name', 'gnue_comment'])
 
     stat = [0, 0, 0]      # inserted, updated, unchanged
 
@@ -452,26 +465,20 @@
   def _updateClasses (self):
     """
     """
-    attributes = {'name'    : "dts_gnueClass",
-                  'database': self.OPTIONS ['connection'],
-                  'table'   : 'gnue_class'}
-    fieldList = ['gnue_id', 'gnue_name', 'gnue_module', 'gnue_comment',
-                 'gnue_filter']
 
-    datasource = GDataSource.DataSourceWrapper (
-          connections = self.connections,
-          attributes  = attributes,
-          fields      = fieldList,
-          unicodeMode = True)
+    self._dtsClass = self.__openSource ('gnue_class', ['gnue_id', 'gnue_name',
+        'gnue_module', 'gnue_comment', 'gnue_filter'])
 
     stat = [0, 0, 0]      # inserted, updated, unchanged
 
-    for klass in self.classes.values ():
+    filterStack = []
+
+    for (fullName, klass) in self.classes.items ():
       moduleId = self.__findModule (klass ['gnue_module'])
       cond = GConditions.buildConditionFromDict ( \
           {'gnue_name': klass ['gnue_name'],
            'gnue_module': moduleId})
-      resultSet = datasource.createResultSet (cond)
+      resultSet = self._dtsClass.createResultSet (cond)
 
       if resultSet.firstRecord () is None:
         resultSet.insertRecord ()
@@ -484,12 +491,36 @@
       # replace the module's name by it's gnue_id
       klass ['gnue_module'] = moduleId
 
+      if klass.has_key ('gnue_filter'):
+        filterId = self.__findClass (klass ['gnue_filter'])
+
+        # The filter class is defined but has no gnue_id yet. So we defer
+        # updating the filter-reference
+        if filterId is None:
+          filterStack.append ((klass ['gnue_id'], klass ['gnue_filter'],
+                              fullName))
+          del klass ['gnue_filter']
+        else:
+          klass ['gnue_filter'] = filterId
+
       if not self.doUpdate (resultSet, klass):
         modifier += 1
 
       stat [modifier] += 1
+      doCommit = (stat [0] + stat [1]) > 0
 
-    if stat [0] + stat [1]:
+    for (gnue_id, filterName, fullName) in filterStack:
+      cond = GConditions.buildConditionFromDict ({'gnue_id': gnue_id})
+      resultSet = self._dtsClass.createResultSet (cond)
+      if resultSet.firstRecord () is None:
+        raise ClassNotFoundError, (fullName)
+
+      filterId = self.__findClass (filterName)
+      
+      if self.doUpdate (resultSet, {'gnue_filter': filterId}):
+        doCommit = True
+
+    if doCommit:
       self.connections.commitAll ()
 
     print o (u_("  Classes   : %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
@@ -504,18 +535,10 @@
   def _updateProperties (self):
     """
     """
-    attributes = {'name'    : "dts_gnueProperty",
-                  'database': self.OPTIONS ['connection'],
-                  'table'   : 'gnue_property'}
-    fieldList = ['gnue_id', 'gnue_module', 'gnue_class', 'gnue_name',
-                 'gnue_type', 'gnue_length', 'gnue_scale', 'gnue_nullable',
-                 'gnue_comment']
 
-    datasource = GDataSource.DataSourceWrapper (
-          connections = self.connections,
-          attributes  = attributes,
-          fields      = fieldList,
-          unicodeMode = True)
+    datasource = self.__openSource ('gnue_property', ['gnue_id', 'gnue_module',
+        'gnue_class', 'gnue_name', 'gnue_type', 'gnue_length', 'gnue_scale',
+        'gnue_nullable', 'gnue_comment'])
 
     stat = [0, 0, 0]      # inserted, updated, unchanged
 
@@ -559,18 +582,11 @@
   # ---------------------------------------------------------------------------
 
   def _updateProcedures (self):
-    attributes = {'name'    : "dts_gnueProcedure",
-                  'database': self.OPTIONS ['connection'],
-                  'table'   : 'gnue_procedure'}
-    fieldList = ['gnue_id', 'gnue_module', 'gnue_class', 'gnue_name',
-                 'gnue_type', 'gnue_length', 'gnue_scale', 'gnue_nullable',
-                 'gnue_comment', 'gnue_code', 'gnue_language']
 
-    self._dtsProcedure = GDataSource.DataSourceWrapper (
-                            connections = self.connections,
-                            attributes  = attributes,
-                            fields      = fieldList,
-                            unicodeMode = True)
+    self._dtsProcedure = 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'])
 
     stat = [0, 0, 0]      # inserted, updated, unchanged
 
@@ -612,17 +628,10 @@
   # ---------------------------------------------------------------------------
 
   def _updateParameter (self):
-    attributes = {'name'    : "dts_gnueParameter",
-                  'database': self.OPTIONS ['connection'],
-                  'table'   : 'gnue_parameter'}
-    fieldList = ['gnue_id', 'gnue_procedure', 'gnue_name', 'gnue_type',
-                 'gnue_scale', 'gnue_length', 'gnue_comment']
 
-    self._dtsParameter = GDataSource.DataSourceWrapper (
-                            connections = self.connections,
-                            attributes  = attributes,
-                            fields      = fieldList,
-                            unicodeMode = True)
+    self._dtsParameter = self.__openSource ('gnue_parameter', ['gnue_id',
+        'gnue_procedure', 'gnue_name', 'gnue_type', 'gnue_scale',
+        'gnue_length', 'gnue_comment'])
 
     stat = [0, 0, 0]      # inserted, updated, unchanged
 
@@ -707,6 +716,23 @@
 
 
   # ---------------------------------------------------------------------------
+  # Find the gnue-id of a given class
+  # ---------------------------------------------------------------------------
+
+  def __findClass (self, classname):
+    if self.classes.has_key (classname):
+      return self.classes [classname]['gnue_id']
+    else:
+      (module, name) = Namespace.splitName (classname)
+      mc = GConditions.buildConditionFromDict ( \
+          {'gnue_module': self.__findModule (module), 'gnue_name': name})
+      rs = self._dtsClass.createResultSet (mc)
+      if rs.firstRecord () is None:
+        raise ClassNotFoundError, (classname)
+
+      return rs.current.getField ('gnue_id')
+
+  # ---------------------------------------------------------------------------
   # Generate a new object id
   # ---------------------------------------------------------------------------
 

Added: trunk/gnue-appserver/src/geasFilter.py
===================================================================
--- trunk/gnue-appserver/src/geasFilter.py      2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/src/geasFilter.py      2004-10-05 08:14:04 UTC (rev 
6454)
@@ -0,0 +1,362 @@
+# GNU Enterprise Application Server - Filter Support
+#
+# Copyright 2001-2004 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 language import Session
+from classrep import Namespace
+from gnue.common.apps import errors
+
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class CircularFilterError (errors.ApplicationError):
+  def __init__ (self):
+    msg = u_("The filters have circular references")
+    errors.ApplicationError.__init__ (self, msg)
+
+
+# =============================================================================
+# This class encapsulates handling of filters
+# =============================================================================
+
+class geasFilter:
+
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, sm):
+    self.__sm      = sm
+    self.__session = Session.InternalSession (sm)
+    self.__filters = self.__loadFilters ()
+    self.__labels  = self.__fetchLabels ()
+
+
+  # ---------------------------------------------------------------------------
+  # Get a structure describing the defined filters, their labels and values
+  # ---------------------------------------------------------------------------
+
+  def getFilter (self, language):
+    """
+    This function creates a structure holding all defined filters, their labels
+    in a requested language and all their possible values. The result is a
+    sequence of tuples, where a tuple is constructed as follows:
+
+      (filter-id, labels, master, data)
+
+    filter-id: the gnue-id of the filter class
+    labels: a sequence of tuples describing the labels (label, search, field)
+    master: gnue_id of the master-filter or None if no such master is defined
+    data: dictionary describing the allowed values of the filter's fields
+
+    @return: sequence of tuples as described above.
+    """
+
+    result = []
+
+    for (fId, filterDef) in self.__labels:
+      # Create an ordered sequence of all search/info-properties as stated in
+      # the GNUe Language Definition of the filter class
+      fields = []
+
+      for (propertyId, propertyDef) in filterDef.items ():
+        field = self.__getLabel (self.__getLanguages (language), propertyDef)
+        fields.append ((field ['order'], field ['label'], field))
+
+      # order sequence by search-value or info-value
+      fields.sort ()
+
+      master = self.__sm.classes.find (fId).gnue_filter
+      if master is not None:
+        master = master.gnue_id
+
+      labels = [(f [1], f [2]['search'], f [2]['name']) for f in fields]
+      names  = [f [2]['name'] for f in fields]
+
+      data = self.__getData (fId, master, names)
+      result.append ((fId, labels, master, data))
+
+    return result
+
+
+
+  # ---------------------------------------------------------------------------
+  # Load a sorted list of all filters defined in the class repository
+  # ---------------------------------------------------------------------------
+
+  def __loadFilters (self):
+    """
+    This function creates a sequence with all filter-Ids defined in the class
+    repository. The sequence is given in such an order which respects internal
+    filter dependancies. 
+
+    @return: sequence with gnue_id's of all filter classes found in the class
+        repository.
+    """
+
+    self.__fDict = {}
+
+    # First get all filters defined in class repository
+    for klass in self.__sm.classes.values ():
+      if klass.gnue_filter is not None:
+        self.__addFilter (klass.gnue_filter)
+
+    result = []
+    add = self.__getIndependantFilters ()
+
+    while len (add):
+      result.extend (add)
+      add = self.__getIndependantFilters ()
+
+    return result
+    
+
+  # ---------------------------------------------------------------------------
+  # Add a filter class to the filter dictionary
+  # ---------------------------------------------------------------------------
+
+  def __addFilter (self, filterClass):
+    """
+    This function adds a filter to the filter dicionary. If the filter has
+    another master itself this function starts a recursion with that master.
+
+    @param filterClass: Class instance of the filter class to be added
+    """
+
+    filterId = filterClass.gnue_id
+    if not self.__fDict.has_key (filterId):
+      self.__fDict [filterId] = []
+
+    if filterClass.gnue_filter is not None:
+      refId = filterClass.gnue_filter.gnue_id
+      if not refId in self.__fDict [filterId]:
+        self.__fDict [filterId].append (refId)
+
+      self.__addFilter (filterClass.gnue_filter)
+
+
+  # ---------------------------------------------------------------------------
+  # Get all items from the filter dictionary which have no dependancies
+  # ---------------------------------------------------------------------------
+
+  def __getIndependantFilters (self):
+    """
+    This function returns a sequence of all filter-Ids without any dependancies
+    to other filters. If no such filter is found but there are still filters in
+    the dictionary a CircularFilterError will be raised.
+
+    @return: sequence holding the gnue_id's of all filters without any
+        reference to another filter.
+    """
+
+    result = []
+
+    for (filterId, references) in self.__fDict.items ():
+
+      # if a filter has no other references, we can add it to the result and
+      # remove all references in other filters to this filter.
+      if not len (references):
+        result.append (filterId)
+
+        for others in self.__fDict.values ():
+          if filterId in others:
+            others.remove (filterId)
+
+        del self.__fDict [filterId]
+
+    # If no filter was independant, but there are still filters in the
+    # dictionary, there must be a circular reference
+    if not len (result) and len (self.__fDict.keys ()):
+      raise CircularFilterError
+
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Create a sequence with all labels per filter (in all languages)
+  # ---------------------------------------------------------------------------
+
+  def __fetchLabels (self):
+    """
+    This function creates a sequence of all filters and all their labels in all
+    languages defined in the class repository. Each element of the sequence is
+    a tuple with the gnue_id of the filter class and a dictionary describing
+    the filter labels. This dicionary is constructed as follows:
+    {property-gnue_id: {language: {'order':?, 'name':?, 'label':?, 
'search':?}}}
+    
+    @return: sequence of tuples describing the filters and their labels
+    """
+
+    result = []
+
+    for filterId in self.__filters:
+      cond = ['and', ['or', ['notnull', ['field', 'gnue_search']],
+                            ['notnull', ['field', 'gnue_info']]],
+                     ['eq', ['field', 'gnue_property.gnue_class'],
+                            ['const', filterId]]]
+
+      labels = self.__session.find ('gnue_label', cond, [], ['gnue_language',
+          'gnue_label', 'gnue_search', 'gnue_info', 'gnue_id', 'gnue_property',
+          'gnue_property.gnue_class'])
+
+      entry = {}
+
+      for label in labels:
+        prop  = label.gnue_property
+        klass = self.__sm.classes.find (prop.gnue_class.gnue_id)
+
+        fullName = None
+        for p in klass.properties.values ():
+          if p.gnue_id == prop.gnue_id:
+            fullName = p.fullName
+            break
+
+        if not entry.has_key (prop.gnue_id):
+          entry [prop.gnue_id] = {}
+          
+        entry [prop.gnue_id][label.gnue_language] = \
+            {'order' : label.gnue_search or label.gnue_info,
+             'label' : label.gnue_label,
+             'name'  : fullName,
+             'search': label.gnue_search is not None}
+
+      if not len (labels):
+        filterClass = self.__sm.classes.find (filterId)
+        prop = filterClass.properties ['gnue_id']
+        entry [prop.gnue_id] = {'C': {'order' : 0,
+                                      'label' : filterClass.fullName,
+                                      'name'  : 'gnue_id',
+                                      'search': True}}
+
+      result.append ((filterId, entry))
+
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Create a sequence of languages in descending order
+  # ---------------------------------------------------------------------------
+
+  def __getLanguages (self, language):
+    """
+    This function creates a sequence of languages to be used for fetching
+    labels out of a given language. Where the starts with the most specific
+    language. The result contains at least the language 'C'.
+
+    @param language: Language to create a sequence out of, i.e. 'de_AT'
+    @return: sequence of languages to try, i.e. ['de_AT', 'de', 'C']
+    """
+
+    result = []
+
+    if '_' in language:
+      result = [language.split ('_') [0]]
+
+    if not language in result:
+      result.insert (0, language)
+
+    if not 'C' in result:
+      result.append ('C')
+
+    return result
+
+
+
+  # ---------------------------------------------------------------------------
+  # Get the first usable label for a given language
+  # ---------------------------------------------------------------------------
+
+  def __getLabel (self, languages, items):
+    """
+    This function returns a label from the given dictionary according to the
+    order given in the languages-sequence.
+
+    @param languages: sequence with languages to fetch a label for
+    @param items: dictionary with labels, where the language is the key
+    @return: dictionary describing the label
+    """
+
+    for lang in languages:
+      if items.get (lang) is not None:
+        return items.get (lang)
+
+    # if no item was found for the requested languages try an english one. If
+    # no such item is defined we use the first element defined
+    return items.get ('en', items.values () [0])
+
+
+  # ---------------------------------------------------------------------------
+  # Get a dictionary with all valid data for a given filter
+  # ---------------------------------------------------------------------------
+
+  def __getData (self, filterId, master, fields):
+    """
+    This function creates a dictionary with all allowed values for a given
+    filter. If the filter has a master assigned, the dictionary's keys will be
+    all the master's values (gnue_id), where the values of the dictionary are
+    all fields of the filter plus a gnue_id.
+
+    @param filterId: gnue_id of the filter class
+    @param master: gnue_id of the master-filter or None
+    @param fields: sequence with all fieldnames to be fetched
+
+    @return: dictionary with the possible filter values. This dictionary has
+        one key per entry in the master-filter and a sequence with all fields
+        as data values. Each entry in this sequence is a dictionary with
+        the filter's field-names and -values.
+    """
+
+    result    = {}
+    classname = self.__sm.classes.find (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
+    # filter-value
+    if master is not None:
+      mClass      = self.__sm.classes.find (master)
+      masterField = "%s.gnue_id" % mClass.fullName
+      condition   = ['like', ['field', mClass.fullName], ['const', '%']]
+      fields.append (masterField)
+
+    else:
+      masterField = None
+      condition   = []
+
+    data = self.__session.find (classname, condition, [], fields)
+
+    for row in data:
+      # use the master-id as dictionary key or None if no master available
+      key = master is not None and row [mClass.fullName].gnue_id or None
+
+      if not result.has_key (key):
+        result [key] = []
+
+      add = {'gnue_id': row.gnue_id}
+      for field in fields:
+        if field != masterField:
+          add [field] = row [field]
+
+      result [key].append (add)
+
+    return result


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

Modified: trunk/gnue-appserver/src/geasInstance.py
===================================================================
--- trunk/gnue-appserver/src/geasInstance.py    2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/src/geasInstance.py    2004-10-05 08:14:04 UTC (rev 
6454)
@@ -387,8 +387,8 @@
     (datefield, userfield) = [('gnue_modifydate', 'gnue_modifyuser'),
                               ('gnue_createdate', 'gnue_createuser')][creation]
     if self.has_key (datefield):
-      self.__putValue (datefield, mx.DateTime.now ())
+      self.__putValue (datefield, mx.DateTime.now (), False)
 
     if self.has_key (userfield) and self.__session.user is not None:
-      self.__putValue (userfield, self.__session.user)
+      self.__putValue (userfield, self.__session.user, False)
 

Modified: trunk/gnue-appserver/src/geasRpcServer.py
===================================================================
--- trunk/gnue-appserver/src/geasRpcServer.py   2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/src/geasRpcServer.py   2004-10-05 08:14:04 UTC (rev 
6454)
@@ -237,13 +237,19 @@
     print _("Step 4: Retrieving first instance ...")
     rset = sm.fetch (session,list,0,1)
 
-    print o(u_("""
+    if len (rset):
+      print o(u_("""
 These are the values of the first instance:
   Name  : %(name)s
   Street: %(street)s
   City  : %(city)s
 """) % { "name": rset[0][1], "street": rset[0][2], "city": rset[0][3] })
 
+
+    print o(u_("Step 5: Retrieving defined filters ..."))
+    res = sm.getFilters (i18n.language)
+    print "Filters:", res
+
     print _('Selftest passed!')
 
 # =============================================================================

Modified: trunk/gnue-appserver/src/geasSession.py
===================================================================
--- trunk/gnue-appserver/src/geasSession.py     2004-10-04 17:03:32 UTC (rev 
6453)
+++ trunk/gnue-appserver/src/geasSession.py     2004-10-05 08:14:04 UTC (rev 
6454)
@@ -227,32 +227,6 @@
 
 
   # ---------------------------------------------------------------------------
-  # Get the value for the given filter
-  # ---------------------------------------------------------------------------
-
-  def __getFilter (self, filterName):
-    if not self.filters.has_key (filterName):
-      filterValue = self.parameters.get (filterName, None)
-      if filterValue is None:
-        raise NoFilterParamError, (filterName)
-
-      cond = ['eq', ['field', 'gnue_code'], ['const', filterValue]]
-      fList = self.request (filterName, cond, [], ['gnue_id'])
-      idList = self.fetch (fList, 0, 5)
-
-      if not len (idList):
-        raise InvalidFilterValueError, (filterName, filterValue)
-
-      elif len (idList) > 1:
-        raise MultipleFilterValueError, (filterName, filterValue)
-
-      self.filters [filterName] = idList [0][0]
-
-    return self.filters [filterName]
-
-
-
-  # ---------------------------------------------------------------------------
   # Log into the application server
   # ---------------------------------------------------------------------------
 
@@ -429,9 +403,11 @@
 
     table    = classdef.table
     record   = self.__connection.insertRecord (table)
+
     if classdef.gnue_filter is not None:
-      fName = classdef.gnue_filter
-      record.putField (fName, self.__getFilter (fName))
+      fId   = classdef.gnue_filter.gnue_id
+      fName = self.sm.classes.find (fId).fullName
+      record.putField (fName, self.__filterValue (fId))
 
     instance = geasInstance.geasInstance (self, self.__connection, record,
                                           classdef)
@@ -594,14 +570,8 @@
     by the datasource, and another one which has to be processed by appserver.
     """
 
-    if classdef.gnue_filter is not None:
-      filterCond = GConditions.buildConditionFromDict ( \
-          {classdef.gnue_filter: self.__getFilter (classdef.gnue_filter)})
-    else:
-      filterCond = None
-
     if condition is None:
-      return (filterCond, None)
+      return (self.__filterCondition (classdef), None)
 
     if isinstance (condition, ListType):
       cTree = GConditions.buildTreeFromList (condition)
@@ -612,21 +582,24 @@
     else:
       raise ConditionDataTypeError, condition
   
-    # If filterCond is already mentioned in the condition tree, keep that one
-    if filterCond is not None:
+    if classdef.gnue_filter is not None:
+      useFilter  = True
+      filterName = self.sm.classes.find (classdef.gnue_filter.gnue_id).fullName
       cList = cTree.findChildrenOfType ('GCCField', allowAllChildren = True)
       if len (cList):
         for item in cList:
-          if classdef.gnue_filter in item.name.split ('.'):
-            filterCond = None
+          if filterName in item.name.split ('.'):
+            useFilter = False
             break
+    else:
+      useFilter = False
 
     dbTrees = []
     asTrees = []
     forest  = []
 
-    if filterCond is not None:
-      self.__splitIntoAnd (filterCond, forest)
+    if useFilter:
+      self.__splitIntoAnd (self.__filterCondition (classdef), forest)
 
     if len (cTree._children):
       # NOTE: the first element of a condition tree is a GCondition object
@@ -663,6 +636,50 @@
 
 
   # ---------------------------------------------------------------------------
+  # Create a condition tree for the current classdef representing it's filter
+  # ---------------------------------------------------------------------------
+
+  def __filterCondition (self, classdef):
+
+    if classdef.gnue_filter is not None:
+      filterId   = classdef.gnue_filter.gnue_id
+      filterName = self.sm.classes.find (filterId).fullName
+      filterCond = GConditions.buildConditionFromDict ( \
+          {filterName: self.__filterValue (filterId)})
+    else:
+      filterCond = None
+
+    return filterCond
+
+
+  # ---------------------------------------------------------------------------
+  # Get the value for the given filter
+  # ---------------------------------------------------------------------------
+
+  def __filterValue (self, filterId):
+
+    filterName = self.sm.classes.find (filterId).fullName
+    if not self.filters.has_key (filterId):
+      filterValue = self.parameters.get (filterId, None)
+      if filterValue is None:
+        raise NoFilterParamError, (filterName)
+
+      cond = ['eq', ['field', 'gnue_id'], ['const', filterValue]]
+      fList = self.request (filterName, cond, [], ['gnue_id'])
+      idList = self.fetch (fList, 0, 5)
+
+      if not len (idList):
+        raise InvalidFilterValueError, (filterName, filterValue)
+
+      elif len (idList) > 1:
+        raise MultipleFilterValueError, (filterName, filterValue)
+
+      self.filters [filterId] = idList [0][0]
+
+    return self.filters [filterId]
+
+
+  # ---------------------------------------------------------------------------
   # Split a condition tree into separate parts
   # ---------------------------------------------------------------------------
 

Modified: trunk/gnue-appserver/src/geasSessionManager.py
===================================================================
--- trunk/gnue-appserver/src/geasSessionManager.py      2004-10-04 17:03:32 UTC 
(rev 6453)
+++ trunk/gnue-appserver/src/geasSessionManager.py      2004-10-05 08:14:04 UTC 
(rev 6454)
@@ -26,6 +26,7 @@
 import geasSession
 import geasAuthentication
 import classrep
+import geasFilter
 
 from gnue import appserver
 from gnue.common.datasources import GConnections
@@ -56,6 +57,7 @@
     self._sessions    = {}
     self._buildInternalSession ()
     classrep.init (self)
+    self._filter = geasFilter.geasFilter (self)
 
     cfg = gConfigDict (section = 'appserver')
     dbauth = cfg.get ('authentication', 'False')
@@ -209,3 +211,11 @@
 
     s = self._getSession (session_id)
     return s.call (classname, obj_id_list, procedurename, parameters)
+
+
+  # ---------------------------------------------------------------------------
+  # Get a structure describing all available filters
+  # ---------------------------------------------------------------------------
+
+  def getFilters (self, language):
+    return self._filter.getFilter (language)

Modified: 
trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py 
2004-10-04 17:03:32 UTC (rev 6453)
+++ trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py 
2004-10-05 08:14:04 UTC (rev 6454)
@@ -51,6 +51,17 @@
   }
 
   # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, connections, name, parameters):
+    Base.Connection.__init__ (self, connections, name, parameters)
+    self._filters = None
+    self._server  = None
+    self._sm      = None
+    
+
+  # ---------------------------------------------------------------------------
   # Define the needed information to log in
   # ---------------------------------------------------------------------------
 
@@ -63,11 +74,18 @@
       result.extend ([['_username', _('User Name'), 0],
                       ['_password', _('Password'), 1]])
 
-    result.extend ([['gnue_company', _('Company'), 0],
-                    ['gnue_year', _('Fiscal Year'), 0]])
+    self.__getSessionManager ()
+    self._filters = self._sm.getFilters (self.parameters.get ('_language', 
'C'))
 
+    for item in self._filters:
+      filterId = item [0]
+      for (label, search, field) in item [1]:
+        result.append ([filterId, label, False])
+        break
+
     return result
 
+
   # ---------------------------------------------------------------------------
   # Open a connection
   # ---------------------------------------------------------------------------
@@ -77,17 +95,10 @@
     user   = connectData.get ('_username', None)
     passwd = connectData.get ('_password', None)
 
-    params = {'host'     : connectData ['host'],
-              'port'     : connectData ['port'],
-              'transport': connectData ['transport']}
+    self.__getSessionManager ()
 
-    self._server = client.attach (connectData ['rpctype'], params)
+    self.__updateFilters (connectData)
 
-    if connectData.has_key ('timeout'):
-      self._server.setTimeout (float (connectData ['timeout']))
-
-    self._sm = self._server.request ('Session')
-
     try:
       if connectData.has_key ('_username'):
         del connectData ['_username']
@@ -139,3 +150,58 @@
   # the Base driver
   def cursor(self):
     return None
+
+
+  # ---------------------------------------------------------------------------
+  # Create/return a connection to the appserver
+  # ---------------------------------------------------------------------------
+
+  def __getSessionManager (self):
+
+    if self._server is None:
+      params = {'host'     : self.parameters.get ('host'),
+                'port'     : self.parameters.get ('port'),
+                'transport': self.parameters.get ('transport')}
+      rpcType = self.parameters.get ('rpctype')
+      self._server = client.attach (rpcType, params)
+
+      if self.parameters.has_key ('timeout'):
+        self._server.setTimeout (float (self.parameters ['timeout']))
+
+    if self._sm is None:
+      self._sm = self._server.request ('Session')
+
+    return self._sm
+
+
+  # ---------------------------------------------------------------------------
+  # Update the given filter values
+  # ---------------------------------------------------------------------------
+
+  def __updateFilters (self, connectData):
+
+    for item in self._filters:
+      filterId = item [0]
+
+      if connectData.has_key (filterId):
+        value = connectData [filterId]
+        (label, search, field) = item [1][0]
+
+        if item [2] is None:
+          masterkey = ''
+        else:
+          masterkey = connectData [item [2]]
+
+        found = False
+        vDict = item [3][masterkey]
+        for record in vDict:
+          if record [field] == value:
+            connectData [filterId] = record ['gnue_id']
+            found = True
+            break
+
+        if not found:
+          raise Exceptions.LoginError, \
+              u_("'%(value)s' is not a valid filter-value for '%(filter)s'") \
+              % {'value': value,
+                 'filter': label}





reply via email to

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