[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r5863 - in trunk: gnue-appserver gnue-appserver/doc gnue-appserver/sampl
From: |
johannes |
Subject: |
r5863 - in trunk: gnue-appserver gnue-appserver/doc gnue-appserver/samples gnue-appserver/scripts gnue-appserver/src gnue-appserver/src/gcd gnue-common/scripts |
Date: |
Mon, 7 Jun 2004 10:12:32 -0500 (CDT) |
Author: johannes
Date: 2004-06-07 10:12:31 -0500 (Mon, 07 Jun 2004)
New Revision: 5863
Added:
trunk/gnue-appserver/doc/gcd.dtd
trunk/gnue-appserver/scripts/gnue-gcd2sql
trunk/gnue-appserver/src/gcd/
trunk/gnue-appserver/src/gcd/GCParser.py
trunk/gnue-appserver/src/gcd/__init__.py
trunk/gnue-appserver/src/gcd/gcd2sql.py
Modified:
trunk/gnue-appserver/BUGS
trunk/gnue-appserver/samples/sample.gfd
trunk/gnue-appserver/setup.cvs
trunk/gnue-common/scripts/gnuedtd
Log:
Implemented gcd2sql, a tool to transform GNUe Class Definitions into sql files
Modified: trunk/gnue-appserver/BUGS
===================================================================
--- trunk/gnue-appserver/BUGS 2004-06-07 14:08:55 UTC (rev 5862)
+++ trunk/gnue-appserver/BUGS 2004-06-07 15:12:31 UTC (rev 5863)
@@ -3,3 +3,7 @@
* Time fields are broken in some dbdrivers. Depending on the driver, it's
possible that the "Meeting Time" field in the sample doesn't work.
+* gcd2sql: extending classes of other modules won't work because the gnue_id of
+ the foreign module (module of the class to be extended) is not known. This
+ will change as soon as all stuff runs into a connection directly, without
+ creating a intermediate sql file.
Added: trunk/gnue-appserver/doc/gcd.dtd
===================================================================
--- trunk/gnue-appserver/doc/gcd.dtd 2004-06-07 14:08:55 UTC (rev 5862)
+++ trunk/gnue-appserver/doc/gcd.dtd 2004-06-07 15:12:31 UTC (rev 5863)
@@ -0,0 +1,99 @@
+<!-- GNUe Class Definitions DTD (Version 0.0.7.99) -->
+
+<!--
+ 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.
+-->
+
+<!-- Entities for characters/symbols -->
+<!ENTITY % lt "&#60;">
+<!ENTITY % gt ">">
+<!ENTITY % amp "&#38;">
+
+<!-- ================================================= -->
+<!-- Datatype entities to make DTD more human readable -->
+<!-- ================================================= -->
+
+<!ENTITY % text "CDATA">
+
+<!ENTITY % true "Y">
+<!ENTITY % false "N">
+<!ENTITY % boolean "(%true;|%false;) #IMPLIED">
+
+<!ENTITY % integer "NMTOKEN">
+<!-- [-]?[0-9]+ -->
+
+<!ENTITY % name "NMTOKEN">
+<!-- [A-Za-z]([A-Z][a-z][0-9][#$_-])* -->
+
+
+
+<!-- ================= -->
+<!-- Top level element -->
+<!-- ================= -->
+<!ELEMENT module (class*)>
+<!ATTLIST module name ID #REQUIRED>
+<!ATTLIST module comment %text; #IMPLIED>
+
+
+<!-- ======================== -->
+<!-- Child elements of module -->
+<!-- ======================== -->
+<!ELEMENT class (procedure*, property*)>
+<!ATTLIST class name ID #REQUIRED>
+<!ATTLIST class comment %text; #IMPLIED>
+<!ATTLIST class module %name; #IMPLIED>
+
+
+<!-- ======================= -->
+<!-- Child elements of class -->
+<!-- ======================= -->
+<!ELEMENT procedure (parameter*, #PCDATA)>
+<!ATTLIST procedure name ID #REQUIRED>
+<!ATTLIST procedure comment %text; #IMPLIED>
+<!ATTLIST procedure language %name; "python">
+<!ATTLIST procedure length %integer; #IMPLIED>
+<!ATTLIST procedure nullable %boolean;>
+<!ATTLIST procedure scale %integer; #IMPLIED>
+<!ATTLIST procedure type %text; #IMPLIED>
+
+<!ELEMENT property EMPTY>
+<!ATTLIST property name ID #REQUIRED>
+<!ATTLIST property type %text; #REQUIRED>
+<!ATTLIST property comment %text; #IMPLIED>
+<!ATTLIST property language %name; "python">
+<!ATTLIST property length %integer; #IMPLIED>
+<!ATTLIST property nullable %boolean;>
+<!ATTLIST property scale %integer; #IMPLIED>
+
+
+<!-- =========================== -->
+<!-- Child elements of procedure -->
+<!-- =========================== -->
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter name ID #REQUIRED>
+<!ATTLIST parameter type %text; #REQUIRED>
+<!ATTLIST parameter comment %text; #IMPLIED>
+<!ATTLIST parameter length %integer; #IMPLIED>
+<!ATTLIST parameter scale %integer; #IMPLIED>
+
+
+<!-- This DTD was created by gnuedtd
+ Updated: 2004-06-07 16:57:35 -->
+
Modified: trunk/gnue-appserver/samples/sample.gfd
===================================================================
--- trunk/gnue-appserver/samples/sample.gfd 2004-06-07 14:08:55 UTC (rev
5862)
+++ trunk/gnue-appserver/samples/sample.gfd 2004-06-07 15:12:31 UTC (rev
5863)
@@ -49,11 +49,9 @@
<datasource name="dtsMCountry" connection="appserver"
table="address_country"/>
<trigger name="showRecord" type="NAMED"><![CDATA[
- setParameter('next', blkPerson.inpHuman.get ())
- dtsPerson.createResultSet ()
- # retval = dtsPerson.call("address_show", {})
- # if retval is not None:
- # print "retval =", retval
+ retval = dtsPerson.call("address_show", {})
+ if retval is not None:
+ print "retval =", retval
]]></trigger>
<logic>
<block name="blkPerson" datasource="dtsPerson">
Added: trunk/gnue-appserver/scripts/gnue-gcd2sql
===================================================================
--- trunk/gnue-appserver/scripts/gnue-gcd2sql 2004-06-07 14:08:55 UTC (rev
5862)
+++ trunk/gnue-appserver/scripts/gnue-gcd2sql 2004-06-07 15:12:31 UTC (rev
5863)
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+# Copyright 2001-2004 Free Software Foundation
+#
+# $Id: $
+
+import os, sys
+
+if hasattr(sys, 'frozen'):
+ sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0])))
+
+from gnue.appserver.gcd import gcd2sql
+
+if __name__ == '__main__':
+ gcd2sql = gcd2sql.gcdConverter ()
+ gcd2sql.run ();
Property changes on: trunk/gnue-appserver/scripts/gnue-gcd2sql
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/gnue-appserver/setup.cvs
===================================================================
--- trunk/gnue-appserver/setup.cvs 2004-06-07 14:08:55 UTC (rev 5862)
+++ trunk/gnue-appserver/setup.cvs 2004-06-07 15:12:31 UTC (rev 5863)
@@ -33,6 +33,7 @@
# Create our shell script..
createShell ('gacvs', 'gnue-appserver')
createShell ('ggcvs', 'gnue-gsdgen')
+createShell ('gcdcvs', 'gnue-gcd2sql')
# Add our GNUe RPC resource files to the config directory...
createLink ('grpc/appserver.grpc','%s/share/gnue/grpc/appserver.grpc' %
CONFDIR, overwrite=1)
Property changes on: trunk/gnue-appserver/src/gcd
___________________________________________________________________
Name: ignore
+ *.pyc
Added: trunk/gnue-appserver/src/gcd/GCParser.py
===================================================================
--- trunk/gnue-appserver/src/gcd/GCParser.py 2004-06-07 14:08:55 UTC (rev
5862)
+++ trunk/gnue-appserver/src/gcd/GCParser.py 2004-06-07 15:12:31 UTC (rev
5863)
@@ -0,0 +1,424 @@
+#
+# 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.
+#
+# Copyright 2001-2004 Free Software Foundation
+#
+# $Id: $
+
+import re
+
+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
+
+
+xmlElements = None
+_LENGTH_SCALE = re.compile ('^\w+\s*\(\s*(\d*)\s*[\,]{0,1}\s*(\d*)\s*\)\s*')
+
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class Error (gException):
+ pass
+
+class NoModuleError (Error):
+ def __init__ (self, classname):
+ msg = u_("Class '%s' has no module") % classname
+ Error.__init__ (self, msg)
+
+class DuplicateDefinitionError (Error):
+ def __init__ (self, name, asLength):
+ if asLength:
+ msg = u_("'%s' has a length in type and an extra length attribute") %
name
+ else:
+ msg = u_("'%s' has a scale in type and an extra scale attribute") % name
+ Error.__init__ (self, msg)
+
+class ModuleMismatchError (Error):
+ def __init__ (self, classname, module):
+ msg = u_("The class '%(class)s' mismatches the given module attribute "
+ "'%(module)s'") % {'class': classname, 'module': module}
+ Error.__init__ (self, msg)
+
+class InvalidCalculatedError (Error):
+ def __init__ (self, classname, propName):
+ msg = u_("Calculated property '%(class)s.%(property)s' has parameters") \
+ % {'class': classname, 'property': propName}
+ Error.__init__ (self, msg)
+
+# =============================================================================
+# load an XML object tree from a given stream and return it's root object
+# =============================================================================
+
+def loadFile (stream, initialize = True):
+ return GParser.loadXMLObject (stream, xmlSchemaHandler, 'GCModule',
+ 'module', initialize)
+
+
+# =============================================================================
+# Build a dictionary tree with all available XML elements
+# =============================================================================
+
+def getXMLelements ():
+ global xmlElements
+
+ if xmlElements is None:
+ xmlElements = {
+ 'module': {
+ 'BaseClass' : GCModule,
+ 'Required' : True,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'comment': {
+ 'Typecast': GTypecast.text}
+ },
+ 'ParentTags': (None)
+ },
+
+ 'class': {
+ 'BaseClass': GCClass,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'module': {
+ 'Typecast': GTypecast.name},
+ 'comment': {
+ 'Typecast': GTypecast.text}
+ },
+ 'ParentTags': ('module',)
+ },
+
+ 'property': {
+ 'BaseClass': GCProperty,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'type': {
+ 'Required': True,
+ 'Typecast': GTypecast.text},
+ 'nullable': {
+ 'Default' : True,
+ 'Typecast': GTypecast.boolean},
+ 'comment': {
+ 'Typecast': GTypecast.text},
+ 'length': {
+ 'Typecast': GTypecast.integer},
+ 'scale': {
+ 'Typecast': GTypecast.integer},
+ 'language': {
+ 'Default' : 'python',
+ 'Typecast': GTypecast.name}
+ },
+ 'MixedContent' : True,
+ 'KeepWhitespace': True,
+ 'ParentTags' : ('class',)
+ },
+
+ 'procedure': {
+ 'BaseClass' : GCProcedure,
+ 'Attributes' : {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'type': {
+ 'Typecast': GTypecast.text},
+ 'nullable': {
+ 'Default' : True,
+ 'Typecast': GTypecast.boolean},
+ 'comment': {
+ 'Typecast': GTypecast.text},
+ 'length': {
+ 'Typecast': GTypecast.integer},
+ 'scale': {
+ 'Typecast': GTypecast.integer},
+ 'language': {
+ 'Default' : 'python',
+ 'Typecast': GTypecast.name}
+ },
+ 'MixedContent' : True,
+ 'KeepWhitespace': True,
+ 'ParentTags' : ('class',)
+ },
+
+ 'parameter': {
+ 'BaseClass': GCParameter,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'type': {
+ 'Required': True,
+ 'Typecast': GTypecast.text},
+ 'comment': {
+ 'Typecast': GTypecast.text},
+ 'length': {
+ 'Typecast': GTypecast.integer},
+ 'scale': {
+ 'Typecast': GTypecast.integer}
+ },
+ 'ParentTags': ('procedure',)
+ }
+ }
+
+ return GParser.buildImportableTags ('module', xmlElements)
+
+
+# =============================================================================
+# Class called by the XML parser to process the XML file
+# =============================================================================
+
+class xmlSchemaHandler (GParser.xmlHandler):
+ def __init__ (self):
+ GParser.xmlHandler.__init__ (self)
+ self.xmlElements = getXMLelements ()
+
+
+# =============================================================================
+# Base class for all GNUe Class Definition classes
+# =============================================================================
+
+class GCObject (GObjects.GObj):
+ pass
+
+
+# =============================================================================
+# Base class for all objects with a type-attribute
+# =============================================================================
+
+class GCTypeDefinition (GCObject):
+ def __init__ (self, parent = None, objType = None):
+ GCObject.__init__ (self, parent, type = objType)
+
+ self.datatype = None
+ self.length = None
+ self.scale = None
+ self.isReference = False
+
+ self._inits.extend ([None, self._validate])
+
+
+ # ---------------------------------------------------------------------------
+ # If an instance has a type attribute, verify it
+ # ---------------------------------------------------------------------------
+
+ def _validate (self):
+
+ if hasattr (self, 'type'):
+ fieldType = self.type.lower ().strip ()
+ tpMatch = re.compile ('^(\w+)').match (fieldType)
+ if tpMatch is None:
+ raise helpers.TypeNameError, (fieldType)
+
+ typename = tpMatch.groups () [0]
+ if not typename in helpers.BASE_TYPES and len (typename.split ('_')) !=
2:
+ raise helpers.TypeNameError, (fieldType)
+
+ flength = 0
+ fscale = 0
+
+ # try to extract length and scale from fieldType
+ lsMatch = _LENGTH_SCALE.match (fieldType)
+ if lsMatch is not None:
+ (lstr, sstr) = lsMatch.groups ()
+
+ if len (lstr):
+ if self.length is not None:
+ raise DuplicateDefinitionError, (self.name, True)
+ self.length = int (lstr)
+
+ if len (sstr):
+ if self.scale is not None:
+ raise DuplicateDefinitionError, (self.name, False)
+ self.scale = int (sstr)
+
+ if typename in helpers.BASE_TYPES:
+ helpers.verifyBasetype (typename, self.length, self.scale)
+ else:
+ self.isReference = True
+
+ if self.length:
+ raise helpers.TypeFormatError, \
+ u_("Reference type '%s' must not have a length") % typename
+ if self.scale:
+ raise helpers.TypeFormatError, \
+ u_("Reference type '%s' must not have a scale") % typename
+
+ typename = 'string'
+ self.length = 32
+
+ self.datatype = typename
+
+
+# =============================================================================
+# The module object, root object of a GCD tree
+# =============================================================================
+
+class GCModule (GRootObj.GRootObj, GCObject):
+ def __init__ (self, parent = None):
+ GRootObj.GRootObj.__init__ (self, 'module', getXMLelements,
self.__module__)
+ GCObject.__init__ (self, parent, type = 'GCModule')
+
+
+# =============================================================================
+# The class object
+# =============================================================================
+
+class GCClass (GCObject):
+ def __init__ (self, parent):
+ GCObject.__init__ (self, parent, type = 'GCClass')
+ self.fullName = None
+ self.action = 'create'
+ self._inits.extend ([None, self._validate, self._complete])
+
+ # ---------------------------------------------------------------------------
+ # Validate a class definition
+ # ---------------------------------------------------------------------------
+
+ def _validate (self):
+ if not isinstance (self._parent, GCModule):
+ raise NoModuleError, self.name
+
+ nameParts = self.name.split ('_')
+ if len (nameParts) > 1:
+ if hasattr (self, 'module') and self.module != nameParts [0]:
+ raise ModuleMismatchError, (self.name, self.module)
+
+ (self.module, self.name) = nameParts [:2]
+
+ if not hasattr (self, 'module'):
+ self.module = self._parent.name
+
+ # if this class is not defined by the top level module, this is just a
+ # definition for a class extension
+ if self.module != self._parent.name:
+ self.action = 'extend'
+
+ self.fullName = Namespace.createName (self.module, self.name)
+
+
+ # ---------------------------------------------------------------------------
+ # Complete a class definition if neccessary
+ # ---------------------------------------------------------------------------
+
+ def _complete (self):
+ # check if there's a gnue_id in new classes
+ if self.action == 'create':
+ items = [c.fullName for c in self.findChildrenOfType ('GCProperty')]
+ if not 'gnue_id' in items:
+ gnueId = GCProperty (self)
+ gnueId.name = 'id'
+ gnueId.type = 'string'
+ gnueId.length = 32
+ gnueId.comment = 'Object ID'
+ gnueId.nullable = False
+
+ gnueId._validate ()
+ gnueId.module = 'gnue'
+ gnueId.fullName= 'gnue_id'
+
+ # transform all 'calculated properties' into procedures
+ for prop in self.findChildrenOfType ('GCProperty') [:]:
+ if True in [isinstance (c, GContent) for c in prop._children]:
+ if prop.findChildOfType ('GCParameter'):
+ raise InvalidCalculatedError, (self.fullName, prop.fullName)
+
+ proc = GCProcedure (self)
+ proc.name = 'get%s' % prop.name
+ proc.type = prop.type
+ proc.length = prop.length
+ proc.scale = prop.scale
+ proc.nullable = prop.nullable
+ proc.language = prop.language
+ if hasattr (prop, 'comment'):
+ proc.comment = prop.comment
+
+ proc._children = prop._children
+
+ for child in proc._children:
+ child._parent = proc
+
+ proc._validate ()
+
+ self._children.remove (prop)
+
+
+
+
+
+# =============================================================================
+# The property object
+# =============================================================================
+
+class GCProperty (GCTypeDefinition):
+ def __init__ (self, parent):
+ GCTypeDefinition.__init__ (self, parent, objType = 'GCProperty')
+ self.module = None
+ self.fullName = None
+
+
+ # ---------------------------------------------------------------------------
+ # Validate a property definition
+ # ---------------------------------------------------------------------------
+
+ def _validate (self):
+ GCTypeDefinition._validate (self)
+ self.module = self.findParentOfType ('GCModule').name
+ self.fullName = Namespace.createName (self.module, self.name)
+
+
+# =============================================================================
+# The procedure object
+# =============================================================================
+
+class GCProcedure (GCTypeDefinition):
+ def __init__ (self, parent):
+ GCTypeDefinition.__init__ (self, parent, objType = 'GCProcedure')
+ self.module = None
+ self.fullName = None
+
+
+ # ---------------------------------------------------------------------------
+ # Validate a procedure definition
+ # ---------------------------------------------------------------------------
+
+ def _validate (self):
+ GCTypeDefinition._validate (self)
+ self.module = self.findParentOfType ('GCModule').name
+ self.fullName = Namespace.createName (self.module, self.name)
+
+
+# =============================================================================
+# The parameter object
+# =============================================================================
+
+class GCParameter (GCTypeDefinition):
+ def __init__ (self, parent):
+ GCTypeDefinition.__init__ (self, parent, objType = 'GCParameter')
+
Property changes on: trunk/gnue-appserver/src/gcd/GCParser.py
___________________________________________________________________
Name: svn:keywords
+ +Id
Added: trunk/gnue-appserver/src/gcd/__init__.py
===================================================================
Added: trunk/gnue-appserver/src/gcd/gcd2sql.py
===================================================================
--- trunk/gnue-appserver/src/gcd/gcd2sql.py 2004-06-07 14:08:55 UTC (rev
5862)
+++ trunk/gnue-appserver/src/gcd/gcd2sql.py 2004-06-07 15:12:31 UTC (rev
5863)
@@ -0,0 +1,397 @@
+# GNU Enterprise Application Server - Gnue Schema Definition Generator
+#
+# 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: $
+
+import sys
+import os
+import whrandom
+
+from gnue.common.apps import i18n
+from gnue.common.apps.GClientApp import *
+from gnue.common.utils.FileUtils import openResource, dyn_import
+
+from gnue.appserver import VERSION
+from gnue.appserver.gcd import GCParser
+
+from gnue.common.schema.scripter.processors import vendors as VENDORS
+from gnue.common.schema.scripter import Definition
+from gnue.common.schema import Objects
+from gnue.common.definitions.GParserHelpers import GContent
+
+
+# =============================================================================
+# Generate SQL from GNUe Class Definition files
+# =============================================================================
+
+class gcdConverter (GClientApp):
+
+ NAME = "gcd2sql"
+ VERSION = VERSION
+ COMMAND = "gcd2sql"
+ USAGE = "%s %s" % (GClientApp.USAGE, " [OPTIONS] file")
+ SUMMARY = _(
+"""A tool to create a SQL script from a GNUe Class Definition (gcd) file""")
+
+ _PROC_PATH = "gnue.common.schema.scripter.processors.%s"
+ _GNUE_MODULE_ID = '0' * 32
+
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, connections = None):
+
+ self.addCommandOption ('vendor', 'v', default = 'all', argument = 'vendor',
+ help = _("The vendor to create a script for. If <vendor> is 'all',
then"
+ " scripts for all supported vendors will be created. <vendor>
"
+ "can also be a comma-separated list."))
+
+ self.addCommandOption('encoding', 'e', default='UTF-8', \
+ argument = _('encoding'),
+ help = _("The generated SQL script will be encoded using <encoding>. "
+ "Default encoding is UTF-8") )
+
+ self.addCommandOption ('output', 'o', argument = 'dest',
+ help = _("to be added later"))
+
+ ConfigOptions = {}
+
+ GClientApp.__init__ (self, connections, 'gcd2sql', ConfigOptions)
+
+
+ # ---------------------------------------------------------------------------
+ # Print a message to stdout, if output is sent to a file
+ # ---------------------------------------------------------------------------
+ def __message (self, text):
+ if self.__filename:
+ print text
+
+
+ # ---------------------------------------------------------------------------
+ # Verify the given commandline options
+ # ---------------------------------------------------------------------------
+
+ def __check_options (self):
+ self._args = [unicode (a, i18n.encoding) for a in self.ARGUMENTS]
+
+ # do we have an accessible input file
+ if not len (self._args):
+ self.handleStartupError (_("No input file specified."))
+
+ if len (self._args) > 1:
+ self.handleStartupError (_("Too much input files specified."))
+
+ try:
+ self._input = openResource (self._args [0])
+
+ except IOError:
+ self.handleStartupError (u_("Unable to open input file %s") % \
+ self._args [0])
+
+ # check the specified vendors
+ self._vendors = []
+ if self.OPTIONS ['vendor'].lower () == 'all':
+ self._vendors.extend (VENDORS)
+ else:
+ self._vendors.extend (self.OPTIONS ['vendor'].split (','))
+
+ self._output = self.OPTIONS ['output']
+ if len (self._vendors) > 1 and self._output is not None:
+ if not os.path.isdir (self._output):
+ self.handleStartupError (_("If multiple vendors are specified "
+ "--output must be a directory or\n left empty."))
+
+ # ---------------------------------------------------------------------------
+ # Main program
+ # ---------------------------------------------------------------------------
+
+ def run (self):
+ self.__check_options ()
+
+ try:
+ self.schema = GCParser.loadFile (self._input)
+
+ except:
+ print sys.exc_info () [1]
+ sys.exit (1)
+
+ for vendor in self._vendors:
+ self._transform (vendor)
+
+
+ # ---------------------------------------------------------------------------
+ # Transform the GCD tree to a given vendors' SQL
+ # ---------------------------------------------------------------------------
+
+ def _transform (self, vendor):
+ aModule = dyn_import (self._PROC_PATH % vendor)
+
+ if not self._output:
+ filename = "%s.sql" % aModule.name
+
+ elif os.path.isdir (self._output):
+ filename = os.path.join (self._output, "%s.sql" % aModule.name)
+
+ else:
+ filename = self._output
+
+ try:
+ self.destination = open (filename, 'w')
+
+ except IOError:
+ sys.stderr.write (u_("Unable to create output file %s" % filename))
+ sys.stderr.write (sys.exc_info () [1])
+ sys.exit (1)
+
+ self.processor = aModule.Processor (self.destination, self._args [0])
+
+ print u_("Writing schema to %s ...") % filename
+
+ try:
+ self.tables = {}
+ self.data = {}
+ self.module = None
+
+ self.processor.startDump ()
+ self.processor.client_encoding (self.OPTIONS ['encoding'])
+
+ self.schema.walk (self.__iterateObjects)
+
+ maxPhase = 0
+ for table in self.tables.values ():
+ maxPhase = max (maxPhase, max (table.phases.keys ()))
+
+ for phase in range (0, maxPhase + 1):
+ for table in self.tables.values ():
+ self.processor.writePhase (table, phase)
+
+ for table in ['gnue_module', 'gnue_class', 'gnue_property', \
+ 'gnue_procedure', 'gnue_parameter']:
+ if self.data.has_key (table):
+ self.processor.writeData (self.data [table])
+
+ self.processor.finishDump ()
+
+ self.destination.close ()
+
+ except:
+ os.unlink (filename)
+ raise
+
+
+ # ---------------------------------------------------------------------------
+ # Iterate over all top level elements
+ # ---------------------------------------------------------------------------
+
+ def __iterateObjects (self, sObject):
+ if sObject._type == 'GCModule':
+ self.__translateModule (sObject)
+
+ elif sObject._type == 'GCClass':
+ self.__translateClass (sObject)
+
+
+
+ # ---------------------------------------------------------------------------
+ # A module translates to a gnue_module data entry only
+ # ---------------------------------------------------------------------------
+
+ def __translateModule (self, aModule):
+ self.module = aModule
+ aModule.gnue_id = self.__generateId ()
+
+ data = [('gnue_id', 'string', aModule.gnue_id),
+ ('gnue_name', 'string', aModule.name)]
+
+ if hasattr (aModule, 'comment'):
+ data.append (('gnue_comment', 'string', aModule.comment))
+
+ self.__addData ('gnue_module', data)
+
+
+ # ---------------------------------------------------------------------------
+ # A class translation needs a table creation/modification and a data entry
+ # ---------------------------------------------------------------------------
+
+ def __translateClass (self, aClass):
+ aTable = Definition.TableDefinition (aClass.fullName, aClass.action)
+ self.tables [aTable.name] = aTable
+
+ if aClass.action == 'create':
+ # New classes get a primary key for the gnue_id column
+ primaryKey = aTable.addPrimaryKey ('gnue_id_pk_%s' % aClass.fullName)
+ pkField = Objects.GSPKField (None)
+ pkField.name = 'gnue_id'
+ primaryKey.fields.append (pkField)
+
+ # Add this new class to the data dictionary
+ aClass.gnue_id = self.__generateId ()
+
+ data = [('gnue_id' , 'string', aClass.gnue_id),
+ ('gnue_module', 'string', self.module.gnue_id),
+ ('gnue_name' , 'string', aClass.name)]
+
+ if hasattr (aClass, 'comment'):
+ data.append (('gnue_comment', 'string', aClass.comment))
+
+ self.__addData ('gnue_class', data)
+ else:
+ aClass.gnue_id = '---unknown---'
+
+ # After processing the class definition, iterate over all it's items
+ aClass.walk (self.__iterateClassObjects, cClass = aClass, tableDef =
aTable)
+
+ self.processor.translateTableDefinition (aTable)
+
+
+ # ---------------------------------------------------------------------------
+ # Iterate over all elements of a class definition
+ # ---------------------------------------------------------------------------
+
+ def __iterateClassObjects (self, sObject, cClass, tableDef):
+ if sObject._type == 'GCProperty':
+ # Add a field to the table definition
+ item = Objects.GSField (None)
+ item.name = sObject.fullName
+ item.type = sObject.datatype
+ item.length = sObject.length or 0
+ item.precision = sObject.scale or 0
+ item.nullable = sObject.nullable
+ item.defaultwith = 'constant'
+ if hasattr (sObject, 'comment'):
+ item.description = sObject.comment
+
+ tableDef.fields.append (item)
+
+ # Create a foreign key constraint for class references
+ if sObject.isReference:
+ cName = "%s_%s_fk" % (cClass.fullName, sObject.type)
+ constraint = tableDef.newConstraint (cName, 'foreignkey')
+ constraint.reftable = sObject.type
+ constraint.fields.append (item)
+ ref = Objects.GSField (None)
+ ref.name = 'gnue_id'
+ constraint.reffields.append (ref)
+
+ # Create an entry for the gnue_property table
+ if sObject.fullName == 'gnue_id':
+ moduleId = self._GNUE_MODULE_ID
+ else:
+ moduleId = self.module.gnue_id
+
+ data = [('gnue_id' , 'string' , self.__generateId ()),
+ ('gnue_module' , 'string' , moduleId),
+ ('gnue_class' , 'string' , cClass.gnue_id),
+ ('gnue_name' , 'string' , sObject.name),
+ ('gnue_type' , 'string' , sObject.datatype),
+ ('gnue_nullable', 'boolean', sObject.nullable)]
+
+ if hasattr (sObject, 'comment'):
+ data.append (('gnue_comment', 'string', sObject.comment))
+ if sObject.length:
+ data.append (('gnue_length', 'number', sObject.length))
+ if sObject.scale:
+ data.append (('gnue_scale', 'number', sObject.scale))
+
+ self.__addData ('gnue_property', data)
+
+
+ elif sObject._type == 'GCProcedure':
+ # Create an entry for the gnue_procedure table
+ sObject.gnue_id = self.__generateId ()
+ data = [('gnue_id' , 'string' , sObject.gnue_id),
+ ('gnue_module' , 'string' , self.module.gnue_id),
+ ('gnue_class' , 'string' , cClass.gnue_id),
+ ('gnue_name' , 'string' , sObject.name),
+ ('gnue_nullable', 'boolean', sObject.nullable),
+ ('gnue_code' , 'string' , sObject.getChildrenAsContent ()),
+ ('gnue_language', 'string' , sObject.language)]
+
+
+ if sObject.datatype is not None:
+ data.append (('gnue_type' , 'string' , sObject.datatype))
+
+ if hasattr (sObject, 'comment'):
+ data.append (('gnue_comment', 'string', sObject.comment))
+
+ if sObject.length:
+ data.append (('gnue_length', 'number', sObject.length))
+ if sObject.scale:
+ data.append (('gnue_scale', 'number', sObject.scale))
+
+ self.__addData ('gnue_procedure', data)
+
+ sObject.walk (self.__iterateProcObjects, cProc = sObject)
+
+ def __iterateProcObjects (self, sObject, cProc):
+ if sObject._type == 'GCParameter':
+ sObject.gnue_id = self.__generateId ()
+
+ data = [('gnue_id' , 'string', sObject.gnue_id),
+ ('gnue_procedure', 'string', cProc.gnue_id),
+ ('gnue_name' , 'string', sObject.name)]
+
+ if hasattr (sObject, 'comment'):
+ data.append (('gnue_comment', 'string', sObject.comment))
+ if sObject.datatype:
+ data.append (('gnue_type', 'string', sObject.datatype))
+ if sObject.length:
+ data.append (('gnue_length', 'number', sObject.length))
+ if sObject.scale:
+ data.append (('gnue_scale', 'number', sObject.scale))
+
+ self.__addData ('gnue_parameter', data)
+
+ # ---------------------------------------------------------------------------
+ # Add a fields-tuple to the data-dictionary
+ # ---------------------------------------------------------------------------
+
+ def __addData (self, table, fields):
+ if not self.data.has_key (table):
+ self.data [table] = Definition.DataDefinition (table)
+
+ row = self.data [table].addRow ()
+ for (name, datatype, value) in fields:
+ item = Objects.GSValue (None)
+ item.dataType = datatype
+ item.value = value
+
+ row.columns.append (name)
+ row.values.append (item)
+
+
+ # ---------------------------------------------------------------------------
+ # Generate a new object id
+ # ---------------------------------------------------------------------------
+
+ def __generateId (self):
+
+ # TODO: need a better algorithm here
+ result = u''
+ for i in range (0, 32):
+ result = result + str (int (whrandom.random () * 10))
+ return result
+
+
+if __name__ == "__main__":
+ gcdConverter ().run ()
Property changes on: trunk/gnue-appserver/src/gcd/gcd2sql.py
___________________________________________________________________
Name: svn:keywords
+ +Id
Modified: trunk/gnue-common/scripts/gnuedtd
===================================================================
--- trunk/gnue-common/scripts/gnuedtd 2004-06-07 14:08:55 UTC (rev 5862)
+++ trunk/gnue-common/scripts/gnuedtd 2004-06-07 15:12:31 UTC (rev 5863)
@@ -77,8 +77,17 @@
name = 'GNURPC'
from gnue.common import VERSION as version
+ elif tool == 'gcd':
+ from gnue.appserver.gcd import GCParser
+ from gnue.appserver import VERSION
+ xmlElements = GCParser.getXMLelements ()
+ topLevelElement = 'module'
+ name = 'GNUe Class Definitions'
+ version = VERSION
+
else:
- print "\nSyntax: gnuedtd <forms|reports|schema|navigator|gnurpc>
[outfile.dtd]\n"
+ print "\nSyntax: gnuedtd <forms|reports|schema|navigator|gnurpc|gcd>" +\
+ "[outfile.dtd]\n"
sys.exit()
self.parentMappings = {}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r5863 - in trunk: gnue-appserver gnue-appserver/doc gnue-appserver/samples gnue-appserver/scripts gnue-appserver/src gnue-appserver/src/gcd gnue-common/scripts,
johannes <=