commit-gnue
[Top][All Lists]
Advanced

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

r5753 - in trunk: gnue-appserver/samples gnue-appserver/src gnue-appserv


From: johannes
Subject: r5753 - in trunk: gnue-appserver/samples gnue-appserver/src gnue-appserver/src/classrep gnue-appserver/src/language gnue-common/src/datasources/drivers/appserver/appserver
Date: Wed, 21 Apr 2004 09:23:52 -0500 (CDT)

Author: johannes
Date: 2004-04-21 09:23:50 -0500 (Wed, 21 Apr 2004)
New Revision: 5753

Modified:
   trunk/gnue-appserver/samples/sample.gfd
   trunk/gnue-appserver/samples/sample.gsd
   trunk/gnue-appserver/src/classrep/Class.py
   trunk/gnue-appserver/src/classrep/Property.py
   trunk/gnue-appserver/src/data.py
   trunk/gnue-appserver/src/geasInstance.py
   trunk/gnue-appserver/src/geasSession.py
   trunk/gnue-appserver/src/language/Object.py
   trunk/gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py
Log:
Added calculated fields to appserver


Modified: trunk/gnue-appserver/samples/sample.gfd
===================================================================
--- trunk/gnue-appserver/samples/sample.gfd     2004-04-21 10:55:10 UTC (rev 
5752)
+++ trunk/gnue-appserver/samples/sample.gfd     2004-04-21 14:23:50 UTC (rev 
5753)
@@ -9,6 +9,9 @@
     retval = dtsPerson.call("address_show", {})
     if retval is not None:
       print "retval =", retval
+
+    newret = dtsPerson.call ("address_test", {})
+    print "New=", repr (newret)
   ]]></trigger>
   <logic>
     <block name="blkPerson" datasource="dtsPerson">
@@ -26,6 +29,8 @@
       <field name="inpMeetTime" field="address_meettime" typecast="date"/>
       <field name="inpLastMeeting" field="address_lastmeeting" 
typecast="date"/>
       <field name="inpHuman" field="address_human" max_length="1"/>
+      <field name="inpNextMeeting" field="address_nextmeeting"
+        typecast="date" readonly="Y"/>
     </block>
     <block name="blkCountry" datasource="dtsMCountry" rows="10">
       <field name="inpCCode" field="address_code" max_length="2"/>
@@ -55,8 +60,10 @@
              Char:y="9" text="Meeting Time:"/>
       <label name="lblLastMeeting" Char:height="1" Char:width="13" Char:x="1"
              Char:y="10" text="Last Meeting:"/>
+      <label name="lblNextMeeting" Char:height="1" Char:width="13" Char:x="1"
+             Char:y="11" text="Next Meeting:"/>
       <label name="lblHuman" Char:height="1" Char:width="6" Char:x="1"
-             Char:y="11" text="Human:"/>
+             Char:y="12" text="Human:"/>
       <entry name="entName" Char:height="1" Char:width="35" Char:x="14"
              Char:y="1" block="blkPerson" field="inpName"/>
       <entry name="entStreet" Char:height="1" Char:width="35" Char:x="14"
@@ -84,8 +91,11 @@
       <entry name="entLastMeeting" Char:height="1" Char:width="25" Char:x="14"
              Char:y="10" block="blkPerson" field="inpLastMeeting"
              displaymask="%x %X" inputmask="%x %X"/>
+      <entry name="entNextMeeting" Char:height="1" Char:width="25" Char:x="14"
+             Char:y="11" block="blkPerson" field="inpNextMeeting"
+             displaymask="%x %X" inputmask="%x %X" navigable="N"/>
       <entry name="entHuman" Char:height="1" Char:width="2" Char:x="14"
-             Char:y="11" block="blkPerson" field="inpHuman" style="checkbox"/>
+             Char:y="12" block="blkPerson" field="inpHuman" style="checkbox"/>
       <button name="Call" Char:height="1" Char:width="25" Char:x="14"
               Char:y="13" label="Show record">
         <trigger src="showRecord" name="Trigger1" type="ON-ACTION"/>

Modified: trunk/gnue-appserver/samples/sample.gsd
===================================================================
--- trunk/gnue-appserver/samples/sample.gsd     2004-04-21 10:55:10 UTC (rev 
5752)
+++ trunk/gnue-appserver/samples/sample.gsd     2004-04-21 14:23:50 UTC (rev 
5753)
@@ -304,6 +304,22 @@
           </value>
           <value field="gnue_comment">Simple procedure to test 
Appserver</value>
         </row>
+        <row>
+          <value field="gnue_id">0000000000000000000000000000101G</value>
+          <value field="gnue_module">00000000000000000000000000001000</value>
+          <value field="gnue_class">00000000000000000000000000001010</value>
+          <value field="gnue_name">getnextmeeting</value>
+          <value field="gnue_language">python</value>
+          <value field="gnue_code">
+import mx.DateTime
+last = self.address_lastmeeting
+tm   = self.address_meettime
+next = last + mx.DateTime.RelativeDateTime (days=+21, hour = tm.hour, minute = 
tm.minute, second = tm.second)
+return next
+          </value>
+          <value field="gnue_comment">Calculate the next meeting date</value>
+          <value field="gnue_type">datetime</value>
+        </row>
       </rows>
     </tabledata>
     <tabledata name="sample_accounts" tablename="gnue_useraccess">

Modified: trunk/gnue-appserver/src/classrep/Class.py
===================================================================
--- trunk/gnue-appserver/src/classrep/Class.py  2004-04-21 10:55:10 UTC (rev 
5752)
+++ trunk/gnue-appserver/src/classrep/Class.py  2004-04-21 14:23:50 UTC (rev 
5753)
@@ -238,6 +238,9 @@
         gDebug (2, "%s.%s: %s: %s" % (self.fullName, p.fullName,
                                sys.exc_info () [0], sys.exc_info () [1]))
 
+    self.properties.loadCalculated (self.procedures)
+
+
   # ---------------------------------------------------------------------------
   # Replace references
   # ---------------------------------------------------------------------------

Modified: trunk/gnue-appserver/src/classrep/Property.py
===================================================================
--- trunk/gnue-appserver/src/classrep/Property.py       2004-04-21 10:55:10 UTC 
(rev 5752)
+++ trunk/gnue-appserver/src/classrep/Property.py       2004-04-21 14:23:50 UTC 
(rev 5753)
@@ -118,31 +118,42 @@
     return PropertyValidationError (self.__class.fullName, item.fullName,
                                     verr.message)
 
+  # ---------------------------------------------------------------------------
+  # update property dictionary with calculated properties from procedure dict.
+  # ---------------------------------------------------------------------------
+
+  def loadCalculated (self, procDict):
+    """
+    This function merges all 'calculated fields' from the given procedure
+    dictionary into the property dictionary
+    """
+
+    for proc in procDict.values ():
+      if proc.isCalculated:
+        newProp = CalculatedProperty (proc)
+        self._items [newProp.fullName] = newProp
+
+
 # =============================================================================
-# A Business Object Property
+# Base class for properties
 # =============================================================================
-class Property (BaseObject):
 
+class BaseProperty:
+
   _BASE_TYPES = ['boolean', 'date', 'datetime', 'number', 'string', 'time']
   _ID_TYPE    = "string"
   _ID_LENGTH  = 32
   _ID_SCALE   = 0
 
   # ---------------------------------------------------------------------------
-  # Construct a new property from module, class and business object
+  # Create the proper type information
   # ---------------------------------------------------------------------------
-  def __init__ (self, session, module, object, pDefs = None):
-    BaseObject.__init__ (self, session, 'gnue_property', object, pDefs)
 
-    self.module   = module
-    self.fullName = createName (self.module.gnue_name, self.gnue_name)
-    self.column   = self.fullName
-
-    self.isValidated     = False
-    self.isReference     = False
-    self.referencedClass = None
-
-    # build appserver specific type information
+  def _updateTypeInfo (self):
+    """
+    This function updates the properties 'fullType', 'dbType', 'dbLength' and
+    'dbScale' based on 'gnue_type', 'gnue_length' and 'gnue_scale'
+    """
     if self.gnue_type in ["string", "number"]:
       if self.gnue_type == "number" and self.gnue_length and self.gnue_scale:
         self.fullType = "%s(%d.%d)" % (self.gnue_type, self.gnue_length,
@@ -177,7 +188,32 @@
       self.dbFullType = self.dbType
 
 
+# =============================================================================
+# A Business Object Property
+# =============================================================================
+class Property (BaseProperty, BaseObject):
+
   # ---------------------------------------------------------------------------
+  # Construct a new property from module, class and business object
+  # ---------------------------------------------------------------------------
+  def __init__ (self, session, module, object, pDefs = None):
+    BaseObject.__init__ (self, session, 'gnue_property', object, pDefs)
+
+    self.module   = module
+    self.fullName = createName (self.module.gnue_name, self.gnue_name)
+    self.column   = self.fullName
+
+    self.isValidated     = False
+    self.isReference     = False
+    self.referencedClass = None
+    self.isCalculated    = False
+    self.procedure       = None
+
+    # build appserver specific type information
+    self._updateTypeInfo ()
+
+
+  # ---------------------------------------------------------------------------
   # Validate a given property definition
   # ---------------------------------------------------------------------------
   def validate (self):
@@ -194,3 +230,39 @@
     self.isValidated     = True
 
 
+# =============================================================================
+# Class for calculated properties
+# =============================================================================
+
+class CalculatedProperty (BaseProperty):
+
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, aProcedure):
+    self.classname = '<calculated>'
+    self._session  = aProcedure._session
+
+    self.module    = aProcedure.module
+    self.fullName  = aProcedure.calcFullName
+    self.column    = None
+
+    self.isValidated     = True
+    self.isReference     = False
+    self.referencedClass = None
+    self.isCalculated    = True
+    self.procedure       = aProcedure
+
+    self.gnue_type     = aProcedure.gnue_type
+    self.gnue_length   = aProcedure.gnue_length
+    self.gnue_scale    = aProcedure.gnue_scale
+
+    self._updateTypeInfo ()
+
+
+  # ---------------------------------------------------------------------------
+  # Validate a calculated property
+  # ---------------------------------------------------------------------------
+  def validate (self):
+    pass

Modified: trunk/gnue-appserver/src/data.py
===================================================================
--- trunk/gnue-appserver/src/data.py    2004-04-21 10:55:10 UTC (rev 5752)
+++ trunk/gnue-appserver/src/data.py    2004-04-21 14:23:50 UTC (rev 5753)
@@ -473,7 +473,8 @@
     checktype (table, UnicodeType)
     checktype (row, UnicodeType)
     checktype (fields, ListType)
-    for fields_element in fields: checktype (fields_element, UnicodeType)
+    for fields_element in fields: 
+      checktype (fields_element, UnicodeType)
 
     uncachedFields = []
     for field in fields:

Modified: trunk/gnue-appserver/src/geasInstance.py
===================================================================
--- trunk/gnue-appserver/src/geasInstance.py    2004-04-21 10:55:10 UTC (rev 
5752)
+++ trunk/gnue-appserver/src/geasInstance.py    2004-04-21 14:23:50 UTC (rev 
5753)
@@ -27,6 +27,7 @@
 import mx.DateTime.ISO
 from gnue.appserver.language import Object, Session
 from gnue.common.logic.language import getLanguageAdapter
+from gnue.appserver.classrep import Namespace
 
 # =============================================================================
 # Exceptions
@@ -63,6 +64,11 @@
                 "resulttype": type (result).__name__}
     gException.__init__ (self, msg)
 
+class PropertyAccessError (gException):
+  def __init__ (self, classname, propertyname):
+    msg = u_("Calculated field '%(property)s' is a read-only field") \
+          % {"property": "%s.%s" % (classname, propertyname)}
+    gException.__init__ (self, msg)
 
 # =============================================================================
 # Instance class
@@ -196,9 +202,11 @@
       record = self.__connection.findRecord (classdef.table, key, [])
 
     propertydef = classdef.properties [elements [-1]]
+    if propertydef.isCalculated:
+      value = self.call (propertydef.procedure, None)
+    else:
+      value = record.getField (propertydef.column)
 
-    value = record.getField (propertydef.column)
-
     return self.__convert (value, propertydef, DbValueError)
 
   # ---------------------------------------------------------------------------
@@ -206,7 +214,6 @@
   # ---------------------------------------------------------------------------
 
   def get (self, propertylist):
-
     return [self.__getValue (aProperty) for aProperty in propertylist]
 
   # ---------------------------------------------------------------------------
@@ -216,6 +223,8 @@
   def __putValue (self, propertyname, value):
 
     propertydef = self.__classdef.properties [propertyname]
+    if propertydef.isCalculated:
+      raise PropertyAccessError, (self.__classdef.fullName, propertyname)
 
     __value = self.__convert (value, propertydef, PropertyValueError)
 
@@ -234,7 +243,7 @@
   # Call a procedure
   # ---------------------------------------------------------------------------
 
-  def call (self, procedurename, params):
+  def call (self, proceduredef, params):
 
     # TODO: This should run in a separate process so that a segfaulting
     # procedure doesn't kill appserver.
@@ -247,9 +256,6 @@
     obj = Object.Object (sess, self.__classdef.fullName, 
                          self.__getValue (u'gnue_id'))
 
-    # fetch the procedure definition
-    proceduredef = self.__classdef.procedures [procedurename]
-
     # check the parameters
     if params is not None:
       for parameter in params.keys ():
@@ -264,7 +270,7 @@
     cx = engine.createNewContext ()
 
     # describe the context
-    cx.shortname   = '%s.%s' % (self.__classdef.fullName, procedurename)
+    cx.shortname   = '%s.%s' % (self.__classdef.fullName, 
proceduredef.fullName)
     cx.description = proceduredef.gnue_comment
 
     # the object itself
@@ -304,8 +310,9 @@
     is raised.
     """
     for prop in self.__classdef.properties.values ():
-      if prop.gnue_nullable is not None and not prop.gnue_nullable:
-        value = self.__record.getField (prop.column)
-        if value is None:
-          raise PropertyValueError (prop.fullName, None)
+      if not prop.isCalculated:
+        if prop.gnue_nullable is not None and not prop.gnue_nullable:
+          value = self.__record.getField (prop.column)
+          if value is None:
+            raise PropertyValueError (prop.fullName, None)
     

Modified: trunk/gnue-appserver/src/geasSession.py
===================================================================
--- trunk/gnue-appserver/src/geasSession.py     2004-04-21 10:55:10 UTC (rev 
5752)
+++ trunk/gnue-appserver/src/geasSession.py     2004-04-21 14:23:50 UTC (rev 
5753)
@@ -71,11 +71,16 @@
 
     return self.sm.classes [classname]
 
+  def __getProcdef (self, classdef, procedurename):
+    # add access control to procedures here
+    return classdef.procedures [procedurename]
+
   # ---------------------------------------------------------------------------
   # Get a field name from a property name, resolving references
   # ---------------------------------------------------------------------------
 
-  def __getFieldname (self, classdef, propertyname, contentdict, add):
+  def __getFieldname (self, classdef, propertyname, contentdict, add,
+                      skipCalculated = True):
 
     elements = string.split (propertyname, '.')
 
@@ -102,6 +107,8 @@
 
     # the real (final) propertydef
     p = c.properties [elements [-1]]
+    if skipCalculated and p.isCalculated:
+      return
 
     # add new field to fieldlist
     if add:
@@ -243,9 +250,14 @@
 
     table = classdef.table
     # Only query the main table here.  geasInstance.get will do the rest.
-    fieldlist = [classdef.properties [string.split (p, '.') [0]].column
-                 for p in propertylist]
+    fieldlist = []
+    for p in propertylist:
+      pdef = classdef.properties [string.split (p, '.') [0]]
+      if not pdef.isCalculated and not pdef.column in fieldlist:
+        fieldlist.append (pdef.column)
+
     record = self.__connection.findRecord (table, object_id, fieldlist)
+
     return geasInstance.geasInstance (self, self.__connection, record,
                                       classdef)
 
@@ -322,10 +334,11 @@
   def call (self, classname, obj_id_list, procedurename, parameters):
 
     classdef = self.__getClassdef (classname)
+    procdef  = self.__getProcdef (classdef, procedurename)
 
     result = []
     for object_id in obj_id_list:
       instance = self.__findInstance (classdef, object_id, [])
-      result.append (instance.call (procedurename, parameters))
+      result.append (instance.call (procdef, parameters))
 
     return result

Modified: trunk/gnue-appserver/src/language/Object.py
===================================================================
--- trunk/gnue-appserver/src/language/Object.py 2004-04-21 10:55:10 UTC (rev 
5752)
+++ trunk/gnue-appserver/src/language/Object.py 2004-04-21 14:23:50 UTC (rev 
5753)
@@ -79,14 +79,9 @@
       sm   = self.__session.getSessionManager ()
       sid  = self.__session.getSessionId ()
 
-      try:
-        res = sm.load (sid, self.__class, [self.objectId, ''], [name])
-        (value, datatype) = (res [0][0], res [1][0])
+      res = sm.load (sid, self.__class, [self.objectId, ''], [name])
+      (value, datatype) = (res [0][0], res [1][0])
 
-      except:
-        # TODO: use a more specific exception 
-        return None
-
       # Convert reference fields to object references
       if '_' in datatype:
         return Object (self.__session, datatype, value)

Modified: 
trunk/gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py  
2004-04-21 10:55:10 UTC (rev 5752)
+++ trunk/gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py  
2004-04-21 14:23:50 UTC (rev 5753)
@@ -64,7 +64,9 @@
                                                 [None],
                                                 fields.keys (),
                                                 [fields.values ()]) [0]
+    self._updateRecord ()
 
+
   # ---------------------------------------------------------------------------
   # Update
   # ---------------------------------------------------------------------------
@@ -76,8 +78,22 @@
                      [self._fields ['gnue_id']],
                      fields.keys (),
                      [fields.values ()])
+    self._updateRecord ()
 
   # ---------------------------------------------------------------------------
+  # Update all fields of a record after update/inserts
+  # ---------------------------------------------------------------------------
+
+  def _updateRecord (self):
+    propertylist = self._fields.keys ()
+    res = self.__sm.load (self.__session_id, self.__classname,
+                          [self._fields ['gnue_id']], propertylist)
+
+    for ix in range (0, len (propertylist)):
+      self._fields [propertylist [ix]] = res [0][ix]
+
+
+  # ---------------------------------------------------------------------------
   # Call a server-side function
   # ---------------------------------------------------------------------------
 





reply via email to

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