[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r5615 - trunk/gnue-appserver/src/classrep
From: |
johannes |
Subject: |
r5615 - trunk/gnue-appserver/src/classrep |
Date: |
Fri, 2 Apr 2004 05:11:22 -0600 (CST) |
Author: johannes
Date: 2004-04-02 05:11:21 -0600 (Fri, 02 Apr 2004)
New Revision: 5615
Modified:
trunk/gnue-appserver/src/classrep/SchemaSupport.py
Log:
Added create/extend support; improved code
Modified: trunk/gnue-appserver/src/classrep/SchemaSupport.py
===================================================================
--- trunk/gnue-appserver/src/classrep/SchemaSupport.py 2004-04-02 10:53:54 UTC
(rev 5614)
+++ trunk/gnue-appserver/src/classrep/SchemaSupport.py 2004-04-02 11:11:21 UTC
(rev 5615)
@@ -1,7 +1,4 @@
-# GNU Enterprise Application Server - GNUe Schema Support
#
-# Copyright 2003-2004 Free Software Foundation
-#
# This file is part of GNU Enterprise.
#
# GNU Enterprise is free software; you can redistribute it
@@ -19,287 +16,371 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
+# Copyright 2001-2004 Free Software Foundation
+#
# $Id$
-from types import *
-
import sys
+import types
import mx.DateTime.ISO
-import re
-from gnue.common.schema.Objects import *
-from gnue.common.definitions.GParserHelpers import GContent
+from gnue.common.schema import Objects
+from gnue.common.definitions import GParserHelpers
from gnue.appserver.classrep import Namespace
# =============================================================================
-# Exceptions: Base exception class
+# Exceptions
# =============================================================================
+# -----------------------------------------------------------------------------
+# Base exception
+# -----------------------------------------------------------------------------
+
class SchemaSupportError (gException):
- """
- Base class for all exceptions of SchemaSupport
- """
- def __init__ (self, text):
- gException.__init__ (self, text)
+ pass
+# -----------------------------------------------------------------------------
+# Invalid export type
+# -----------------------------------------------------------------------------
-class InvalidTypeError (SchemaSupportError):
- def __init__ (self, typename):
- msg = _("Invalid export type: '%s'") % typename
+class ExportTypeError (SchemaSupportError):
+ def __init__ (self, exportType):
+ msg = _("Invalid export type: '%s'") % exportType
SchemaSupportError.__init__ (self, msg)
+# -----------------------------------------------------------------------------
+# Invalid value for given type of
+# -----------------------------------------------------------------------------
-class InvalidValueError (SchemaSupportError):
- """
- This exception is raised if a value doesn't match it's datatype.
- """
- def __init__ (self, text):
- SchemaSupportError.__init__ (self, text)
+class ValueError (SchemaSupportError):
+ pass
# =============================================================================
-# SchemaSupport
+#
# =============================================================================
+
class SchemaSupport:
- SCHEMA_STORE = ["schema", "data", "both"]
-
# ---------------------------------------------------------------------------
# Constructor
# ---------------------------------------------------------------------------
- def __init__(self, modules, classes):
+
+ def __init__ (self, modules, classes):
self.__modules = modules
self.__classes = classes
+ self.__exportModules = {}
+ self.__exportClasses = {}
+ self.__schema = None
+ self.__tables = None
+ self.__data = None
+ self.__dataRows = {}
+
+
# ---------------------------------------------------------------------------
- # Write a Schema to a file. If filename is omitted stdout is used.
+ # Write the requested items to a GNUe Schema Definition
# ---------------------------------------------------------------------------
- def writeSchemaToFile (self, filename = None, items = None, wtype = None):
- if wtype is None:
- wtype = "both"
- elif wtype.lower () not in self.SCHEMA_STORE:
- raise InvalidTypeError (wtype.lower ())
+ def writeSchemaToFile (self, filename = None, items = None, wType = None):
+ """
+ This function creates an XML object tree for all the requested @items,
+ containing a tabledefinition and a datadefinition as given by @wType, and
+ dumps this XML object tree to filename. If filename is omitted sys.stdout
+ will be used.
+ """
+ checktype (filename, [types.NoneType, types.StringType, types.UnicodeType])
+ checktype (items, [types.NoneType, types.ListType])
+ checktype (wType, [types.NoneType, types.StringType, types.UnicodeType])
- # If no specific items are requested, we will use classes
+ # do we have a usable export type given
+ if wType is None:
+ wType = 'both'
+
+ elif wType.lower () not in ['schema', 'data', 'both']:
+ raise ExportTypeError, wType.lower ()
+
+ # build a todo-list: if no specific item is reqested, we will use all
+ # classes. Requested items are separated into modules and classes
+ self.__exportModules = {}
+ self.__exportClasses = {}
+
if items is None or len (items) == 0:
- classdefs = self.__classes.values ()
+ items = [aClass.fullName for aClass in self.__classes.values ()]
- # otherwise check all items and create the classlist
- else:
- classdefs = []
+ for item in items:
+ # item is a module
+ if Namespace.getNamespaceId (item) == Namespace.NSID_MODULE:
+ aModule = self.__modules [item]
+ self.__exportModules [aModule.fullName] = aModule
- for item in items:
- # if item is a module add all it's classes to the list
- if Namespace.getNamespaceId (item) == Namespace.NSID_MODULE:
- classdefs.extend (self.__modules [item].classes.values ())
+ # or a class
+ elif Namespace.getNamespaceId (item) == Namespace.NSID_CLASS:
+ aClass = self.__classes [item]
+ self.__exportClasses [aClass.fullName] = aClass
- # if item is a class add it to the list
- elif Namespace.getNamespaceId (item) == Namespace.NSID_CLASS:
- classdefs.append (self.__classes [item])
+ else:
+ # or invalid
+ raise Namespace.InvalidNameError, item
- # otherwise item is of no use to us
- else:
- raise Namespace.InvalidNameError (item)
+ # create the top-level objects of the XML tree
+ self.__schema = Objects.GSSchema ()
+ self.__schema.title = 'Appserver Schema Dump'
+ self.__schema.author = 'Appserver SchemaSupport'
+ self.__schema.version = '1.0'
- schema = GSSchema()
- schema.title = "Appserver Schema Dump"
- schema.author = "Appserver SchemaSupport"
- schema.version = "1.0"
+ self.__tables = None
+ self.__data = None
- gsTables = GSTables (schema)
+ if wType.lower () in ['both', 'schema']:
+ self.__tables = Objects.GSTables (self.__schema)
+ if wType.lower () in ['both', 'data']:
+ self.__data = Objects.GSData (self.__schema)
- # Schema-Definition
- if wtype.lower () in ["both", "schema"]:
- for classdef in classdefs:
- self.__createTableDef (gsTables, classdef)
+ # if there is a list of requested modules, add them to the gnue_module_dump
+ # before class dumps
+ if self.__data is not None and len (self.__exportModules.keys ()):
+ self.__addModuleDump ()
- # Data
- if wtype.lower () in ["both", "data"]:
- gsData = GSData (schema)
- self.__createDataList (gsData, classdefs)
+ # iterate over all available classes in the repository
+ for aClass in self.__classes.values ():
- if filename is None:
- dest = sys.stdout
+ # class is requested explicitly, so do a 'full create export'
+ if self.__exportClasses.has_key (aClass.fullName):
+ self.__export (aClass, True)
+
+ # if the module of a class is requested, export all stuff of this module
+ # plus gnue_*-things (using create action)
+ elif self.__exportModules.has_key (aClass.gnue_module.gnue_name):
+ self.__export (aClass, True, self.__exportModules.keys () + ['gnue'])
+
+ else:
+ # if aClass has a property or procedure of a requested module, export
+ # all stuff of the requested modules (using an extend action)
+ xModules = [p.module.fullName for p in aClass.properties.values () + \
+ aClass.procedures.values ()]
+ for module in xModules:
+ if module == 'gnue':
+ continue
+ if self.__exportModules.has_key (module):
+ self.__export (aClass, False, self.__exportModules.keys ())
+ break
+
+
+ # The XML object tree is complete now, so we're going to dump it
+ if filename is not None:
+ destination = open (filename, 'w')
else:
- dest = open (filename, 'w')
+ destination = sys.stdout
- dest.write ('<?xml version="1.0" encoding="UTF-8"?>\n')
- dest.write ('<!-- Schema definition created by GNUe Appserver\'s ' + \
- 'Schema Support. -->\n')
- dest.write ("<!-- run this file through gnue-schema to create SQL " + \
- "scripts -->\n")
- dest.write (schema.dumpXML ().encode ('utf-8'))
- dest.close ()
+ header = """<?xml version="1.0" encoding="UTF-8"?>
+<!-- Schema definition created by GNUe Appserver's Schema Support.
+ Run this file through gnue-schema to create SQL scripts -->
+"""
+ destination.write (header)
+ destination.write (self.__schema.dumpXML ().encode ('utf-8'))
+ destination.close ()
+
# ---------------------------------------------------------------------------
- # Create the tabledefinition for classname
+ # Export a given class (schema and data)
# ---------------------------------------------------------------------------
- def __createTableDef (self, gsTables, classdef):
- table = GSTable (gsTables)
- table.name = classdef.table
+ def __export (self, aClass, create, modules = None):
+ """
+ This function exports schema- and data-definition of a given class. If
+ @create is True, the schema-definition is given as 'create'-action,
+ otherwise an 'extend'-action will be used. @modules is a list of
+ modulenames, whose properties and procedures should be exported. If no list
+ is given, all properties and procedures will be exported.
+ """
+ if self.__tables is not None:
+ self.__exportSchema (aClass, create, modules)
- # add fields listing (required)
- fields = GSFields (table)
- GSConstraints (table)
- GSIndexes (table)
+ if self.__data is not None:
+ self.__exportData (aClass, create, modules)
- for cProp in classdef.properties.values ():
- field = GSField (fields)
+
+
+ # ---------------------------------------------------------------------------
+ # Add a class to the table-definition tree
+ # ---------------------------------------------------------------------------
+
+ def __exportSchema (self, aClass, create, modules = None):
+ """
+ This function adds a classes schema to the XML object tree.
+ """
+
+ schema = Objects.GSTable (self.__tables)
+ schema.name = aClass.table
+ if not create:
+ schema.action = "extend"
+
+ fields = Objects.GSFields (schema)
+ indexes = Objects.GSIndexes (schema)
+ constraints = Objects.GSConstraints (schema)
+
+ # populate the fields-collection
+ for cProp in self.__filterByModules (aClass.properties.values (), modules):
+ field = Objects.GSField (fields)
field.name = cProp.column
field.description = cProp.gnue_comment
field.type = cProp.dbType
- if cProp.dbLength: field.length = cProp.dbLength
- if cProp.dbScale : field.precision = cProp.dbScale
+ if cProp.dbLength:
+ field.length = cProp.dbLength
+ if cProp.dbScale:
+ field.scale = cProp.dbScale
if not cProp.gnue_nullable is None and not cProp.gnue_nullable:
- field.nullable = False
+ field.nullable = False
- # If there is a property 'gnue_id' of type 'id' in a class use it for the
- # primary key
- if classdef.properties.has_key ("gnue_id"):
- if classdef.properties ["gnue_id"].gnue_type == "id":
- pk = GSPrimaryKey (table)
- pk.name = "gnue_id_pk_%s" % classdef.table
+ # if a type has an underscore we assume it's a reference-type, which
+ # means to create a foreign key reference to the gnue_id of that class
+ if "_" in cProp.gnue_type:
+ constraint = Objects.GSConstraint (constraints)
+ constraint.name = "%s_%s_fk" % (aClass.table, cProp.column)
+ constraint.type = "foreignkey"
- pkf = GSPKField (pk)
- pkf.name = 'gnue_id'
+ constField = Objects.GSConstraintField (constraint)
+ constField.name = cProp.fullName
+ constRef = Objects.GSConstraintRef (constraint)
+ constRef.name = "gnue_id"
+ constRef.table = cProp.gnue_type
+ # in create-mode look if a primary key could be constructed
+ if create and aClass.properties.has_key ('gnue_id'):
+ if aClass.properties ['gnue_id'].gnue_type == 'id':
+ primarykey = Objects.GSPrimaryKey (schema)
+ primarykey.name = "gnue_id_pk_%s" % aClass.table
+
+ pkField = Objects.GSPKField (primarykey)
+ pkField.name = 'gnue_id'
+
+
+
# ---------------------------------------------------------------------------
- # Dump all tabledata from a given tablelist
+ # Add a class to the data definition
# ---------------------------------------------------------------------------
- def __createDataList (self, gsData, classdefs):
- # first we need a list of all modules used in classdefs
- modules = {}
- for classdef in classdefs:
- modules [classdef.module.fullName] = classdef.module
- # dump one row from gnue_module for all items in modules
- moddata = GSTableData (gsData)
- moddata.name = 'gnue_module_dump'
- moddata.tablename = 'gnue_module'
- self.__addColumnDefinition (moddata, 'gnue_module')
- modrows = GSRows (moddata)
+ def __exportData (self, aClass, create, modules = None):
+ """
+ This function adds @aClass to several gnue-table rows.
+ """
+ if create:
+ self.__dumpObject (aClass, 'gnue_class')
- for moduledef in modules.values ():
- mProp = self.__classes ["gnue_module"].properties
- row = GSRow (modrows)
+ for prop in self.__filterByModules (aClass.properties.values (), modules):
+ self.__dumpObject (prop, 'gnue_property')
- self.__buildValue (row, mProp [u"gnue_id"] , moduledef.gnue_id)
- self.__buildValue (row, mProp [u"gnue_name"] , moduledef.gnue_name)
- self.__buildValue (row, mProp [u"gnue_comment"], moduledef.gnue_comment)
+ for proc in self.__filterByModules (aClass.procedures.values (), modules):
+ self.__dumpObject (proc, 'gnue_procedure')
- # dump all gnue_class rows for the requested tables
- tabledata = GSTableData (gsData)
- tabledata.name = 'gnue_class_dump'
- tabledata.tablename = 'gnue_class'
- tableDef = self.__addColumnDefinition (tabledata, 'gnue_class')
- tablerows = GSRows (tabledata)
+ for param in proc.parameters.values ():
+ self.__dumpObject (param, 'gnue_parameter')
- # and all their properties
- propdata = GSTableData (gsData)
- propdata.name = 'gnue_property_dump'
- propdata.tablename = 'gnue_property'
- tableDef = self.__addColumnDefinition (propdata, 'gnue_property')
- proprows = GSRows (propdata)
- # and all their procedures
- procdata = GSTableData (gsData)
- procdata.name = 'gnue_procedure_dump'
- procdata.tablename = 'gnue_procedure'
- tableDef = self.__addColumnDefinition (procdata, 'gnue_procedure')
- procrows = GSRows (procdata)
+ # ---------------------------------------------------------------------------
+ # Dump an object to the given table
+ # ---------------------------------------------------------------------------
- # and all the procedures parameters
- paramdata = GSTableData (gsData)
- paramdata.name = 'gnue_parameter_dump'
- paramdata.tablename = 'gnue_parameter'
- tableDef = self.__addColumnDefinition (paramdata, 'gnue_parameter')
- paramrows = GSRows (paramdata)
+ def __dumpObject (self, aClass, table):
+ """
+ This function creates a new row of @table, and adds all values from @aClass
+ according to the classdefinition of @table to it.
+ """
+ row = Objects.GSRow (self.__getRows (table))
+
+ for cProp in self.__classes [table].properties.values ():
+ value = getattr (aClass, cProp.fullName)
+
+ # resolve reference-properties
+ if "_" in cProp.fullType:
+ value = value.gnue_id
- for classdef in classdefs:
- cProp = self.__classes ["gnue_class"].properties
+ self.__buildValue (row, cProp, value)
- # save tabledata
- row = GSRow (tablerows)
- self.__buildValue (row, cProp ["gnue_id"] , classdef.gnue_id)
- self.__buildValue (row, cProp ["gnue_module"] , classdef.gnue_module)
- self.__buildValue (row, cProp ["gnue_name"] , classdef.gnue_name)
- self.__buildValue (row, cProp ["gnue_comment"], classdef.gnue_comment)
+ # ---------------------------------------------------------------------------
+ # Get the rows object of an tabledata-object
+ # ---------------------------------------------------------------------------
- for propdef in classdef.properties.values ():
+ def __getRows (self, classname):
+ """
+ This function returns the rows-collection of a given table. If it does not
+ exist already it will be created (with a column definition included).
+ """
- pProp = self.__classes ["gnue_property"].properties
- row = GSRow (proprows)
+ if not self.__dataRows.has_key (classname):
+ table = Objects.GSTableData (self.__data)
+ table.name = "%s_dump" % classname
+ table.tablename = classname
- self.__buildValue (row, pProp ["gnue_id"] , propdef.gnue_id)
- self.__buildValue (row, pProp ["gnue_module"] , propdef.gnue_module)
- self.__buildValue (row, pProp ["gnue_class"] , propdef.gnue_class)
- self.__buildValue (row, pProp ["gnue_name"] , propdef.gnue_name)
- self.__buildValue (row, pProp ["gnue_type"] , propdef.gnue_type)
- self.__buildValue (row, pProp ["gnue_length"] , propdef.gnue_length)
- self.__buildValue (row, pProp ["gnue_scale"] , propdef.gnue_scale)
- self.__buildValue (row, pProp ["gnue_comment"] , propdef.gnue_comment)
- self.__buildValue (row, pProp ["gnue_nullable"], propdef.gnue_nullable)
+ columns = Objects.GSDefinition (table)
- for procdef in classdef.procedures.values ():
+ for prop in self.__classes [classname].properties.values ():
+ column = Objects.GSColumn (columns)
+ column.field = prop.column
+ column.type = prop.dbFullType
- pProp = self.__classes ["gnue_procedure"].properties
- row = GSRow (procrows)
+ self.__dataRows [classname] = Objects.GSRows (table)
- self.__buildValue (row, pProp ["gnue_id"], procdef.gnue_id)
- self.__buildValue (row, pProp ["gnue_module"], procdef.gnue_module)
- self.__buildValue (row, pProp ["gnue_class"], procdef.gnue_class)
- self.__buildValue (row, pProp ["gnue_name"], procdef.gnue_name)
- self.__buildValue (row, pProp ["gnue_language"], procdef.gnue_language)
- self.__buildValue (row, pProp ["gnue_code"], procdef.gnue_code)
- self.__buildValue (row, pProp ["gnue_comment"], procdef.gnue_comment)
+ return self.__dataRows [classname]
- for paramDef in procdef.parameters.values ():
- pProp = self.__classes ["gnue_parameter"].properties
- row = GSRow (paramrows)
- self.__buildValue (row, pProp ["gnue_id"], paramDef.gnue_id)
- self.__buildValue (row, pProp ["gnue_procedure"],
- paramDef.gnue_procedure)
- self.__buildValue (row, pProp ["gnue_name"], paramDef.gnue_name)
- self.__buildValue (row, pProp ["gnue_type"], paramDef.gnue_type)
- self.__buildValue (row, pProp ["gnue_length"], paramDef.gnue_length)
- self.__buildValue (row, pProp ["gnue_scale"], paramDef.gnue_scale)
- self.__buildValue (row, pProp ["gnue_comment"],
paramDef.gnue_comment)
-
-
# ---------------------------------------------------------------------------
- # Create a new field in a row and populate it with a value
+ # Create a GContents XML object for a data value in a row
# ---------------------------------------------------------------------------
+
def __buildValue (self, row, prop, data):
+ """
+ If @data is not None this function adds a GContents object with the
+ normalized value of @data to the @row, where @prop specifies the datatype
+ for normalization.
+ """
if data is not None:
- value = GSValue (row)
+ value = Objects.GSValue (row)
value.field = prop.column
- GContent (value, self.__nativeToString (data, prop.fullType))
+ GParserHelpers.GContent (value, \
+ self.__nativeToString (data, prop.dbFullType))
# ---------------------------------------------------------------------------
- # Add a column definition section to the given tabledata for classname
+ # Get a subsequence of items matching a modulelist
# ---------------------------------------------------------------------------
- def __addColumnDefinition (self, tableData, classname):
- tableDef = GSDefinition (tableData)
+ def __filterByModules (self, items, modules):
+ """
+ This function returns a sub-sequence of all @items which match the given
+ module list (@modules). If this list is None, all @items are returned.
+ """
+ result = []
+ for element in items:
+ if modules is not None and not element.module.fullName in modules:
+ continue
- classdef = self.__classes [classname]
- for prop in classdef.properties.values ():
- column = GSColumn (tableDef)
- column.field = prop.column
- column.type = prop.dbFullType
+ result.append (element)
- return tableDef
+ return result
+
# ---------------------------------------------------------------------------
+ # add all requested modules to the module dump
+ # ---------------------------------------------------------------------------
+
+ def __addModuleDump (self):
+ """
+ This function creates a dump of the gnue_module table, by adding all
+ requested modules.
+ """
+ for module in self.__exportModules.values ():
+ self.__dumpObject (module, 'gnue_module')
+
+
+
+ # ---------------------------------------------------------------------------
# Convert a native python object to a string according to datatype
# ---------------------------------------------------------------------------
@@ -310,12 +391,12 @@
'datatype'.
"""
if datatype [:6] == "string" or datatype == "id":
- checktype (native, [NoneType, UnicodeType])
+ checktype (native, [types.NoneType, types.UnicodeType])
if native is None:
return u''
- if isinstance (native, UnicodeType):
+ if isinstance (native, types.UnicodeType):
return native
elif datatype [:6] == "number":
@@ -337,8 +418,7 @@
return native.date
else:
- raise InvalidValueError ( \
- _("%s is not a valid date object") % repr (native))
+ raise ValueError (_("%s is not a valid date object") % repr (native))
elif datatype == "time":
@@ -349,8 +429,7 @@
return str (native)
else:
- raise InvalidValueError ( \
- _("%s is not a valid time object") % repr (native))
+ raise ValueError (_("%s is not a valid time object") % repr (native))
elif datatype == "datetime":
@@ -358,24 +437,9 @@
return str (native)
else:
- raise InvalidValueError (_("%s is not a valid datetime object") % \
+ raise ValueError (_("%s is not a valid datetime object") % \
repr (native))
else:
# must be reference property
return native.gnue_id
-
-
-# =============================================================================
-# test program
-# =============================================================================
-
-if __name__ == '__main__':
- from gnue.appserver.test import testApp
-
- app = testApp()
- sm = app.getSessionManager ()
-
- gsdSupp = SchemaSupport (sm.modules, sm.classes)
-
- gsdSupp.writeSchemaToFile ('AS_Schema.gsd')
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r5615 - trunk/gnue-appserver/src/classrep,
johannes <=