summaryrefslogtreecommitdiff
path: root/cpp/managementgen
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-11-23 13:37:42 +0000
committerAlan Conway <aconway@apache.org>2007-11-23 13:37:42 +0000
commita3aaa263858f07d37e5860136300f76fab8d7ecd (patch)
treef188402580f36e06113a92c3c74575d13040c1d0 /cpp/managementgen
parentcb070d9813e4232b4ec8409ca555b529ee5cee4b (diff)
downloadqpid-python-a3aaa263858f07d37e5860136300f76fab8d7ecd.tar.gz
QPID-689 from tross@redhat.com.
This patch introduces formal schema specification for management and code generation for management classes. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@597662 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/managementgen')
-rwxr-xr-xcpp/managementgen/generate.py229
-rwxr-xr-xcpp/managementgen/main.py54
-rwxr-xr-xcpp/managementgen/schema.py748
-rw-r--r--cpp/managementgen/templates/Args.h39
-rw-r--r--cpp/managementgen/templates/Class.cpp108
-rw-r--r--cpp/managementgen/templates/Class.h69
6 files changed, 1247 insertions, 0 deletions
diff --git a/cpp/managementgen/generate.py b/cpp/managementgen/generate.py
new file mode 100755
index 0000000000..1d0987e685
--- /dev/null
+++ b/cpp/managementgen/generate.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from xml.dom.minidom import parse, parseString, Node
+from cStringIO import StringIO
+from stat import *
+from errno import *
+import os
+import os.path
+import filecmp
+
+#=====================================================================================
+#
+#=====================================================================================
+class Template:
+ def __init__ (self, filename, handler):
+ self.filename = filename
+ self.handler = handler
+
+ def expandLine (self, line, stream, object):
+ cursor = 0
+ while 1:
+ sub = line.find ("/*MGEN:", cursor)
+ if sub == -1:
+ stream.write (line[cursor:len (line)])
+ return
+
+ subend = line.find("*/", sub)
+ stream.write (line[cursor:sub])
+ cursor = subend + 2
+
+ tag = line[sub:subend]
+ dotPos = tag.find (".")
+ if dotPos == -1:
+ raise ValueError ("Invalid tag: %s" % tag)
+ tagObject = tag[7:dotPos]
+ tagName = tag[dotPos + 1:len (tag)]
+
+ self.handler (object, stream, tagObject, tagName)
+
+ def expand (self, object):
+ fd = open (self.filename)
+ stream = StringIO ()
+
+ for line in fd:
+ self.expandLine (line, stream, object)
+ fd.close ()
+
+ return stream
+
+#=====================================================================================
+#
+#=====================================================================================
+class Generator:
+ def createPath (self, path):
+ exists = True
+ try:
+ mode = os.stat (path)[ST_MODE]
+ except OSError, (err,text):
+ if err == ENOENT:
+ exists = False
+ else:
+ raise
+ if exists and not S_ISDIR (mode):
+ raise ValueError ("path is not directory: %s" % path)
+ if not exists:
+ pair = os.path.split (path)
+ self.createPath (pair[0])
+ os.mkdir (path)
+
+ def normalize (self, path):
+ newpath = os.path.normcase (os.path.normpath (path))
+ self.createPath (newpath)
+ return newpath + "/"
+
+ def __init__ (self, destDir, templateDir):
+ self.dest = self.normalize (destDir)
+ self.input = self.normalize (templateDir)
+ self.filelists = {}
+ self.filelists["h"] = []
+ self.filelists["cpp"] = []
+ self.filelists["mk"] = []
+ self.templateFiles = []
+
+ def genDisclaimer (self, stream):
+ stream.write ("// This source file was created by a code generator.\n")
+ stream.write ("// Please do not edit.")
+
+ def fileExt (self, path):
+ dot = path.rfind (".")
+ if dot == -1:
+ return ""
+ return path[dot + 1:]
+
+ def writeIfChanged (self, stream, target, force=False):
+ ext = self.fileExt (target)
+ self.filelists[ext].append (target)
+ tempFile = self.dest + "gen.tmp"
+ fd = open (tempFile, "w")
+ fd.write (stream.getvalue ())
+ fd.close ()
+
+ try:
+ if not force and filecmp.cmp (target, tempFile):
+ os.remove (tempFile)
+ return
+ except:
+ pass
+
+ try:
+ os.remove (target)
+ except:
+ pass
+
+ os.rename (tempFile, target)
+ print "Generated:", target
+
+ def targetClassFile (self, _class, templateFile):
+ dot = templateFile.find(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:len (templateFile)]
+ path = self.dest + _class.getName ().capitalize () + extension
+ return path
+
+ def targetMethodFile (self, method, templateFile):
+ """ Return the file name for a method file """
+ dot = templateFile.rfind(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:]
+ path = self.dest + "Args" + method.getFullName () + extension
+ return path
+
+ def substHandler (self, object, stream, tagObject, tag):
+ if tagObject == "Root":
+ obj = "self"
+ else:
+ obj = "object" # MUST be the same as the 2nd formal parameter
+
+ call = obj + ".gen" + tag + "(stream)"
+ eval (call)
+
+ def makeClassFiles (self, templateFile, schema):
+ """ Generate an expanded template per schema class """
+ classes = schema.getClasses ()
+ template = Template (self.input + templateFile, self.substHandler)
+ self.templateFiles.append (templateFile)
+ for _class in classes:
+ target = self.targetClassFile (_class, templateFile)
+ stream = template.expand (_class)
+ self.writeIfChanged (stream, target)
+
+ def makeMethodFiles (self, templateFile, schema):
+ """ Generate an expanded template per method-with-arguments """
+ classes = schema.getClasses ()
+ template = Template (self.input + templateFile, self.substHandler)
+ self.templateFiles.append (templateFile)
+ for _class in classes:
+ methods = _class.getMethods ()
+ for method in methods:
+ if method.getArgCount () > 0:
+ target = self.targetMethodFile (method, templateFile)
+ stream = template.expand (method)
+ self.writeIfChanged (stream, target)
+
+ def makeMakeFile (self, target):
+ stream = StringIO ()
+ stream.write ("# Generated makefile fragment.\n\n")
+ stream.write ("mgen_generator=$(mgen_dir)/main.py \\\n")
+ stream.write (" $(mgen_dir)/generate.py \\\n")
+ stream.write (" $(mgen_dir)/schema.py \\\n")
+ stream.write (" $(top_srcdir)/../specs/management-types.xml \\\n")
+ stream.write (" $(top_srcdir)/../specs/management-schema.xml \\\n ")
+ first = 1
+ for template in self.templateFiles:
+ if first == 1:
+ first = 0
+ else:
+ stream.write (" \\\n ")
+ stream.write ("$(mgen_dir)/templates/" + template)
+
+ stream.write ("\n\nmgen_broker_cpp=")
+ first = 1
+ for file in self.filelists["cpp"]:
+ if first == 1:
+ first = 0
+ else:
+ stream.write (" \\\n ")
+ stream.write (file.replace ("../src", "."))
+ stream.write ("\n\n")
+
+ stream.write ("# Header file install rules.\n")
+ stream.write ("qpid_managementdir = $(includedir)/qpid/management\n")
+ stream.write ("dist_qpid_management_HEADERS = ")
+ first = 1
+ for file in self.filelists["h"]:
+ if first == 1:
+ first = 0
+ else:
+ stream.write (" \\\n ")
+ stream.write (file.replace ("../src", "."))
+ stream.write ("\n\n")
+
+ stream.write ("if GENERATE\n")
+ stream.write ("$(srcdir)/managementgen.mk: $(mgen_generator)\n")
+ stream.write ("\t$(mgen_cmd)\n")
+ stream.write ("\n$(mgen_generator):\n")
+ stream.write ("endif\n")
+
+ self.writeIfChanged (stream, target, force=True)
diff --git a/cpp/managementgen/main.py b/cpp/managementgen/main.py
new file mode 100755
index 0000000000..2f70639482
--- /dev/null
+++ b/cpp/managementgen/main.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from schema import PackageSchema, SchemaClass
+from generate import Generator
+from optparse import OptionParser
+
+# Set command line options
+parser = OptionParser ()
+parser.add_option ("-o", "--outDir", dest="outdir", metavar="DIR",
+ help="Destination directory for generated files")
+parser.add_option ("-t", "--typeFile", dest="typefile", metavar="FILE",
+ help="Schema type document (XML file)")
+parser.add_option ("-s", "--schemaFile", dest="schemafile", metavar="FILE",
+ help="Schema defintion document (XML file)")
+parser.add_option ("-i", "--templateDir", dest="templatedir", metavar="DIR",
+ help="Directory where template files can be found")
+parser.add_option ("-m", "--makefile", dest="makefile", metavar="FILE",
+ help="Makefile fragment")
+
+(opts, args) = parser.parse_args ()
+
+if opts.outdir == None or \
+ opts.typefile == None or \
+ opts.schemafile == None or \
+ opts.templatedir == None or \
+ opts.makefile == None:
+ parser.error ("Incorrect options, see --help for help")
+
+gen = Generator (opts.outdir, opts.templatedir)
+schema = PackageSchema (opts.typefile, opts.schemafile)
+
+gen.makeClassFiles ("Class.h", schema)
+gen.makeClassFiles ("Class.cpp", schema)
+gen.makeMethodFiles ("Args.h", schema)
+gen.makeMakeFile (opts.makefile)
diff --git a/cpp/managementgen/schema.py b/cpp/managementgen/schema.py
new file mode 100755
index 0000000000..c3db4eaf53
--- /dev/null
+++ b/cpp/managementgen/schema.py
@@ -0,0 +1,748 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from xml.dom.minidom import parse, parseString, Node
+from cStringIO import StringIO
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaType:
+ def __init__ (self, node):
+ self.name = None
+ self.base = None
+ self.cpp = None
+ self.encode = None
+ self.decode = None
+ self.style = "normal"
+ self.accessor = None
+ self.init = "0"
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'base':
+ self.base = val
+
+ elif key == 'cpp':
+ self.cpp = val
+
+ elif key == 'encode':
+ self.encode = val
+
+ elif key == 'decode':
+ self.decode = val
+
+ elif key == 'style':
+ self.style = val
+
+ elif key == 'accessor':
+ self.accessor = val
+
+ elif key == 'init':
+ self.init = val
+
+ else:
+ raise ValueError ("Unknown attribute in type '%s'" % key)
+
+ if self.name == None or self.base == None or self.cpp == None or \
+ self.encode == None or self.decode == None:
+ raise ValueError ("Missing required attribute(s) in type")
+
+ def getName (self):
+ return self.name
+
+ def genAccessor (self, stream, varName, changeFlag = None):
+ if self.accessor == "direct":
+ stream.write (" inline void set_" + varName + " (" + self.cpp + " val){\n");
+ stream.write (" " + varName + " = val;\n");
+ if self.style == "wm":
+ stream.write (" if (" + varName + "Low > val)\n")
+ stream.write (" " + varName + "Low = val;\n");
+ stream.write (" if (" + varName + "High < val)\n")
+ stream.write (" " + varName + "High = val;\n");
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n");
+ elif self.accessor == "counter":
+ stream.write (" inline void inc_" + varName + " (" + self.cpp + " by = 1){\n");
+ stream.write (" " + varName + " += by;\n")
+ if self.style == "wm":
+ stream.write (" if (" + varName + "High < " + varName + ")\n")
+ stream.write (" " + varName + "High = " + varName + ";\n")
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n");
+ stream.write (" inline void dec_" + varName + " (" + self.cpp + " by = 1){\n");
+ stream.write (" " + varName + " -= by;\n")
+ if self.style == "wm":
+ stream.write (" if (" + varName + "Low > " + varName + ")\n")
+ stream.write (" " + varName + "Low = " + varName + ";\n")
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n");
+
+ def genHiLoStatResets (self, stream, varName):
+ if self.style == "wm":
+ stream.write (" " + varName + "High = " + varName + ";\n")
+ stream.write (" " + varName + "Low = " + varName + ";\n")
+
+ def genWrite (self, stream, varName):
+ stream.write (" " + self.encode.replace ("@", "buf").replace ("#", varName) + ";\n")
+ if self.style == "wm":
+ stream.write (" " + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "High") + ";\n")
+ stream.write (" " + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "Low") + ";\n")
+
+ def getReadCode (self, varName, bufName):
+ result = self.decode.replace ("@", bufName).replace ("#", varName)
+ return result
+
+ def getWriteCode (self, varName, bufName):
+ result = self.encode.replace ("@", bufName).replace ("#", varName)
+ return result
+
+#=====================================================================================
+#
+#=====================================================================================
+class TypeSpec:
+ def __init__ (self, file):
+ self.types = {}
+ dom = parse (file)
+ document = dom.documentElement
+ if document.tagName != 'schema-types':
+ raise ValueError ("Expected 'schema-types' in type file")
+
+ for child in document.childNodes:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'type':
+ stype = SchemaType (child)
+ self.types[stype.getName ()] = stype
+ else:
+ raise ValueError ("Unknown type tag '%s'" % child.nodeName)
+
+ def getType (self, name):
+ return self.types[name]
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class Type:
+ def __init__ (self, name, typespec):
+ self.type = typespec.getType (name)
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaConfig:
+ def __init__ (self, node, typespec):
+ self.name = None
+ self.type = None
+ self.access = "RO"
+ self.isIndex = 0
+ self.isParentRef = 0
+ self.unit = None
+ self.min = None
+ self.max = None
+ self.maxLen = None
+ self.desc = None
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'type':
+ self.type = Type (val, typespec)
+
+ elif key == 'access':
+ self.access = val
+
+ elif key == 'index':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in index attribute")
+ self.isIndex = 1
+
+ elif key == 'parentRef':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in parentRef attribute")
+ self.isParentRef = 1
+
+ elif key == 'unit':
+ self.unit = val
+
+ elif key == 'min':
+ self.min = val
+
+ elif key == 'max':
+ self.max = val
+
+ elif key == 'maxlen':
+ self.maxLen = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ else:
+ raise ValueError ("Unknown attribute in configElement '%s'" % key)
+
+ if self.name == None:
+ raise ValueError ("Missing 'name' attribute in configElement")
+ if self.type == None:
+ raise ValueError ("Missing 'type' attribute in configElement")
+
+ def getName (self):
+ return self.name
+
+ def isConstructorArg (self):
+ if self.access == "RC" and self.isParentRef == 0:
+ return 1
+ return 0
+
+ def genDeclaration (self, stream):
+ stream.write (" " + self.type.type.cpp + " " + self.name + ";\n")
+
+ def genFormalParam (self, stream):
+ stream.write (self.type.type.cpp + " _" + self.name)
+
+ def genAccessor (self, stream):
+ self.type.type.genAccessor (stream, self.name, "configChanged")
+
+ def genSchema (self, stream):
+ stream.write (" ft = FieldTable ();\n")
+ stream.write (" ft.setString (NAME, \"" + self.name + "\");\n")
+ stream.write (" ft.setInt (TYPE, TYPE_" + self.type.type.base +");\n")
+ stream.write (" ft.setInt (ACCESS, ACCESS_" + self.access + ");\n")
+ stream.write (" ft.setInt (INDEX, " + str (self.isIndex) + ");\n")
+ if self.unit != None:
+ stream.write (" ft.setString (UNIT, \"" + self.unit + "\");\n")
+ if self.min != None:
+ stream.write (" ft.setInt (MIN, " + self.min + ");\n")
+ if self.max != None:
+ stream.write (" ft.setInt (MAX, " + self.max + ");\n")
+ if self.maxLen != None:
+ stream.write (" ft.setInt (MAXLEN, " + self.maxLen + ");\n")
+ if self.desc != None:
+ stream.write (" ft.setString (DESC, \"" + self.desc + "\");\n")
+ stream.write (" buf.put (ft);\n\n")
+
+ def genWrite (self, stream):
+ self.type.type.genWrite (stream, self.name)
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaInst:
+ def __init__ (self, node, typespec):
+ self.name = None
+ self.type = None
+ self.unit = None
+ self.desc = None
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'type':
+ self.type = Type (val, typespec)
+
+ elif key == 'unit':
+ self.unit = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ else:
+ raise ValueError ("Unknown attribute in instElement '%s'" % key)
+
+ if self.name == None:
+ raise ValueError ("Missing 'name' attribute in instElement")
+ if self.type == None:
+ raise ValueError ("Missing 'type' attribute in instElement")
+
+ def getName (self):
+ return self.name
+
+ def genDeclaration (self, stream):
+ stream.write (" " + self.type.type.cpp + " " + self.name + ";\n")
+ if self.type.type.style == 'wm':
+ stream.write (" " + self.type.type.cpp + " " + self.name + "High;\n")
+ stream.write (" " + self.type.type.cpp + " " + self.name + "Low;\n")
+
+ def genAccessor (self, stream):
+ self.type.type.genAccessor (stream, self.name, "instChanged")
+
+ def genHiLoStatResets (self, stream):
+ self.type.type.genHiLoStatResets (stream, self.name)
+
+ def genSchemaText (self, stream, name, desc):
+ stream.write (" ft = FieldTable ();\n")
+ stream.write (" ft.setString (NAME, \"" + name + "\");\n")
+ stream.write (" ft.setInt (TYPE, TYPE_" + self.type.type.base +");\n")
+ if self.unit != None:
+ stream.write (" ft.setString (UNIT, \"" + self.unit + "\");\n")
+ if desc != None:
+ stream.write (" ft.setString (DESC, \"" + desc + "\");\n")
+ stream.write (" buf.put (ft);\n\n")
+
+ def genSchema (self, stream):
+ self.genSchemaText (stream, self.name, self.desc)
+ if self.type.type.style == "wm":
+ descHigh = self.desc
+ descLow = self.desc
+ if self.desc != None:
+ descHigh = descHigh + " (High)"
+ descLow = descLow + " (Low)"
+ self.genSchemaText (stream, self.name + "High", descHigh)
+ self.genSchemaText (stream, self.name + "Low", descLow)
+
+ def genWrite (self, stream):
+ self.type.type.genWrite (stream, self.name)
+
+ def genInitialize (self, stream):
+ val = self.type.type.init
+ stream.write (" " + self.name + " = " + val + ";\n")
+ if self.type.type.style == "wm":
+ stream.write (" " + self.name + "High = " + val + ";\n")
+ stream.write (" " + self.name + "Low = " + val + ";\n")
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaArg:
+ def __init__ (self, node, typespec):
+ self.name = None
+ self.type = None
+ self.unit = None
+ self.dir = "I"
+ self.min = None
+ self.max = None
+ self.maxLen = None
+ self.desc = None
+ self.default = None
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'type':
+ self.type = Type (val, typespec)
+
+ elif key == 'unit':
+ self.unit = val
+
+ elif key == 'dir':
+ self.dir = val.upper ()
+
+ elif key == 'min':
+ self.min = val
+
+ elif key == 'max':
+ self.max = val
+
+ elif key == 'maxlen':
+ self.maxLen = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ elif key == 'default':
+ self.default = val
+
+ else:
+ raise ValueError ("Unknown attribute in arg '%s'" % key)
+
+ if self.name == None:
+ raise ValueError ("Missing 'name' attribute in arg")
+ if self.type == None:
+ raise ValueError ("Missing 'type' attribute in arg")
+
+ def getName (self):
+ return self.name
+
+ def getDir (self):
+ return self.dir
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaMethod:
+ def __init__ (self, parent, node, typespec):
+ self.parent = parent
+ self.name = None
+ self.desc = None
+ self.args = []
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ else:
+ raise ValueError ("Unknown attribute in method '%s'" % key)
+
+ for child in node.childNodes:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'arg':
+ arg = SchemaArg (child, typespec)
+ self.args.append (arg)
+ else:
+ raise ValueError ("Unknown method tag '%s'" % child.nodeName)
+
+ def getName (self):
+ return self.name
+
+ def getFullName (self):
+ return self.parent.getName().capitalize() + self.name[0:1].upper() +\
+ self.name[1:]
+
+ def getArgCount (self):
+ return len (self.args)
+
+ #===================================================================================
+ # Code Generation Functions. The names of these functions (minus the leading "gen")
+ # match the substitution keywords in the template files.
+ #===================================================================================
+ def genNameUpper (self, stream):
+ stream.write (self.getFullName ().upper ())
+
+ def genNameCamel (self, stream):
+ stream.write (self.getFullName ())
+
+ def genArguments (self, stream):
+ for arg in self.args:
+ ctype = arg.type.type.cpp
+ dirTag = arg.dir.lower() + "_"
+ stream.write (" " + ctype + " " + dirTag + arg.getName () + ";\n")
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaEvent:
+ def __init__ (self, parent, node, typespec):
+ self.parent = parent
+ self.name = None
+ self.desc = None
+ self.args = []
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ else:
+ raise ValueError ("Unknown attribute in event '%s'" % key)
+
+ for child in node.childNodes:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'arg':
+ arg = SchemaArg (child, typespec)
+ self.args.append (arg)
+ else:
+ raise ValueError ("Unknown event tag '%s'" % child.nodeName)
+
+ def getName (self):
+ return self.name
+
+ def getFullName (self):
+ return self.parent.getName ().capitalize() + self.name.capitalize ()
+
+ def getArgCount (self):
+ return len (self.args)
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaClass:
+ def __init__ (self, node, typespec):
+ self.configElements = []
+ self.instElements = []
+ self.methods = []
+ self.events = []
+
+ attrs = node.attributes
+ self.name = attrs['name'].nodeValue
+
+ children = node.childNodes
+ for child in children:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'configElement':
+ sub = SchemaConfig (child, typespec)
+ self.configElements.append (sub)
+
+ elif child.nodeName == 'instElement':
+ sub = SchemaInst (child, typespec)
+ self.instElements.append (sub)
+
+ elif child.nodeName == 'method':
+ sub = SchemaMethod (self, child, typespec)
+ self.methods.append (sub)
+
+ elif child.nodeName == 'event':
+ sub = SchemaEvent (self, child, typespec)
+ self.events.append (sub)
+
+ else:
+ raise ValueError ("Unknown class tag '%s'" % child.nodeName)
+
+ def getName (self):
+ return self.name
+
+ def getMethods (self):
+ return self.methods
+
+ def getEvents (self):
+ return self.events
+
+ #===================================================================================
+ # Code Generation Functions. The names of these functions (minus the leading "gen")
+ # match the substitution keywords in the template files.
+ #===================================================================================
+ def genAccessorMethods (self, stream):
+ for config in self.configElements:
+ if config.access != "RC":
+ config.genAccessor (stream)
+ for inst in self.instElements:
+ inst.genAccessor (stream)
+
+ def genArgDeclaration (self, stream):
+ argsFound = 0
+ for method in self.methods:
+ argsFound = argsFound + len (method.args)
+ for event in self.events:
+ argsFound = argsFound + len (event.args)
+ if argsFound > 0:
+ stream.write ("FieldTable arg;");
+
+ def genConfigCount (self, stream):
+ stream.write ("%d" % len (self.configElements))
+
+ def genConfigDeclarations (self, stream):
+ for element in self.configElements:
+ element.genDeclaration (stream)
+
+ def genConfigElementSchema (self, stream):
+ for config in self.configElements:
+ config.genSchema (stream)
+
+ def genConstructorArgs (self, stream):
+ # Constructor args are config elements with read-create access
+ result = ""
+ first = 1
+ for element in self.configElements:
+ if element.isConstructorArg ():
+ if first == 1:
+ first = 0
+ else:
+ stream.write (", ")
+ element.genFormalParam (stream)
+
+ def genConstructorInits (self, stream):
+ for element in self.configElements:
+ if element.isConstructorArg ():
+ stream.write ("," + element.getName () + "(_" + element.getName () + ")")
+
+ def genDoMethodArgs (self, stream):
+ methodCount = 0
+ inArgCount = 0
+ for method in self.methods:
+ methodCount = methodCount + 1
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ inArgCount = inArgCount + 1
+
+ if methodCount == 0:
+ stream.write ("string, Buffer&, Buffer& outBuf")
+ else:
+ if inArgCount == 0:
+ stream.write ("string methodName, Buffer&, Buffer& outBuf")
+ else:
+ stream.write ("string methodName, Buffer& inBuf, Buffer& outBuf")
+
+ def genEventCount (self, stream):
+ stream.write ("%d" % len (self.events))
+
+ def genEventSchema (self, stream):
+ pass ###########################################################################
+
+ def genHiLoStatResets (self, stream):
+ for inst in self.instElements:
+ inst.genHiLoStatResets (stream)
+
+ def genInitializeElements (self, stream):
+ for inst in self.instElements:
+ inst.genInitialize (stream)
+
+ def genInstChangedStub (self, stream):
+ if len (self.instElements) == 0:
+ stream.write (" // Stub for getInstChanged. There are no inst elements\n")
+ stream.write (" bool getInstChanged (void) { return false; }\n")
+
+ def genInstCount (self, stream):
+ count = 0
+ for inst in self.instElements:
+ count = count + 1
+ if inst.type.type.style == "wm":
+ count = count + 2
+ stream.write ("%d" % count)
+
+ def genInstDeclarations (self, stream):
+ for element in self.instElements:
+ element.genDeclaration (stream)
+
+ def genInstElementSchema (self, stream):
+ for inst in self.instElements:
+ inst.genSchema (stream)
+
+ def genMethodArgIncludes (self, stream):
+ for method in self.methods:
+ if method.getArgCount () > 0:
+ stream.write ("#include \"qpid/management/Args" +\
+ method.getFullName () + ".h\"\n")
+
+ def genMethodCount (self, stream):
+ stream.write ("%d" % len (self.methods))
+
+ def genMethodHandlers (self, stream):
+ for method in self.methods:
+ stream.write ("\n if (methodName == \"" + method.getName () + "\")\n {\n")
+ if method.getArgCount () == 0:
+ stream.write (" ArgsNone ioArgs;\n")
+ else:
+ stream.write (" Args" + method.getFullName () + " ioArgs;\n")
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ stream.write (" " +\
+ arg.type.type.getReadCode ("ioArgs." +\
+ arg.dir.lower () + "_" +\
+ arg.name, "inBuf") + ";\n")
+
+ stream.write (" status = coreObject->ManagementMethod (METHOD_" +\
+ method.getName().upper() + ", ioArgs);\n")
+ stream.write (" outBuf.putLong (status);\n")
+ stream.write (" outBuf.putShortString (Manageable::StatusText (status));\n")
+ for arg in method.args:
+ if arg.getDir () == "O" or arg.getDir () == "IO":
+ stream.write (" " +\
+ arg.type.type.getWriteCode ("ioArgs." +\
+ arg.dir.lower () + "_" +\
+ arg.name, "outBuf") + ";\n")
+ stream.write (" return;\n }\n")
+
+
+ def genMethodIdDeclarations (self, stream):
+ number = 1
+ for method in self.methods:
+ stream.write (" static const uint32_t METHOD_" + method.getName().upper() +\
+ " = %d;\n" % number)
+ number = number + 1
+
+ def genMethodSchema (self, stream):
+ pass ###########################################################################
+
+ def genNameCap (self, stream):
+ stream.write (self.name.capitalize ())
+
+ def genNameLower (self, stream):
+ stream.write (self.name.lower ())
+
+ def genNameUpper (self, stream):
+ stream.write (self.name.upper ())
+
+ def genParentArg (self, stream):
+ for config in self.configElements:
+ if config.isParentRef == 1:
+ stream.write (" _parent")
+ return
+
+ def genParentRefAssignment (self, stream):
+ for config in self.configElements:
+ if config.isParentRef == 1:
+ stream.write (config.getName () + \
+ " = _parent->GetManagementObject ()->getObjectId ();")
+ return
+
+ def genWriteConfig (self, stream):
+ for config in self.configElements:
+ config.genWrite (stream);
+
+ def genWriteInst (self, stream):
+ for inst in self.instElements:
+ inst.genWrite (stream);
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class PackageSchema:
+ def __init__ (self, typefile, schemafile):
+
+ self.classes = []
+ self.typespec = TypeSpec (typefile)
+
+ dom = parse (schemafile)
+ document = dom.documentElement
+ if document.tagName != 'schema':
+ raise ValueError ("Expected 'schema' node")
+ attrs = document.attributes
+ self.packageName = attrs['package'].nodeValue
+
+ children = document.childNodes
+ for child in children:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'class':
+ cls = SchemaClass (child, self.typespec)
+ self.classes.append (cls)
+ else:
+ raise ValueError ("Unknown schema tag '%s'" % child.nodeName)
+
+ def getPackageName (self):
+ return self.packageName
+
+ def getClasses (self):
+ return self.classes
diff --git a/cpp/managementgen/templates/Args.h b/cpp/managementgen/templates/Args.h
new file mode 100644
index 0000000000..4a6413ddc9
--- /dev/null
+++ b/cpp/managementgen/templates/Args.h
@@ -0,0 +1,39 @@
+#ifndef _ARGS_/*MGEN:Method.NameUpper*/_
+#define _ARGS_/*MGEN:Method.NameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/Args.h"
+#include <string>
+
+namespace qpid {
+namespace management {
+
+class Args/*MGEN:Method.NameCamel*/ : public Args
+{
+ public:
+/*MGEN:Method.Arguments*/
+};
+
+}}
+
+#endif /*!_ARGS_/*MGEN:Method.NameUpper*/_*/
diff --git a/cpp/managementgen/templates/Class.cpp b/cpp/managementgen/templates/Class.cpp
new file mode 100644
index 0000000000..70077d495c
--- /dev/null
+++ b/cpp/managementgen/templates/Class.cpp
@@ -0,0 +1,108 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/log/Statement.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/management/Manageable.h"
+#include "/*MGEN:Class.NameCap*/.h"
+/*MGEN:Class.MethodArgIncludes*/
+
+using namespace qpid::management;
+using namespace qpid::sys;
+using namespace qpid::framing;
+using std::string;
+
+bool /*MGEN:Class.NameCap*/::schemaNeeded = true;
+
+/*MGEN:Class.NameCap*/::/*MGEN:Class.NameCap*/ (Manageable* _core, Manageable*/*MGEN:Class.ParentArg*/,
+ /*MGEN:Class.ConstructorArgs*/) :
+ ManagementObject(_core, "/*MGEN:Class.NameLower*/")
+ /*MGEN:Class.ConstructorInits*/
+{
+ /*MGEN:Class.ParentRefAssignment*/
+/*MGEN:Class.InitializeElements*/
+}
+
+/*MGEN:Class.NameCap*/::~/*MGEN:Class.NameCap*/ () {}
+
+namespace {
+ const string NAME("name");
+ const string TYPE("type");
+ const string ACCESS("access");
+ const string INDEX("index");
+ const string UNIT("unit");
+ const string MIN("min");
+ const string MAX("max");
+ const string MAXLEN("maxlen");
+ const string DESC("desc");
+}
+
+void /*MGEN:Class.NameCap*/::writeSchema (Buffer& buf)
+{
+ FieldTable ft;
+ /*MGEN:Class.ArgDeclaration*/
+
+ schemaNeeded = false;
+
+ // Schema class header:
+ buf.putShortString (className); // Class Name
+ buf.putShort (/*MGEN:Class.ConfigCount*/); // Config Element Count
+ buf.putShort (/*MGEN:Class.InstCount*/); // Inst Element Count
+ buf.putShort (/*MGEN:Class.MethodCount*/); // Method Count
+ buf.putShort (/*MGEN:Class.EventCount*/); // Event Count
+
+ // Config Elements
+/*MGEN:Class.ConfigElementSchema*/
+ // Inst Elements
+/*MGEN:Class.InstElementSchema*/
+ // Methods
+/*MGEN:Class.MethodSchema*/
+ // Events
+/*MGEN:Class.EventSchema*/
+}
+
+void /*MGEN:Class.NameCap*/::writeConfig (Buffer& buf)
+{
+ configChanged = false;
+
+ writeTimestamps (buf);
+/*MGEN:Class.WriteConfig*/
+}
+
+void /*MGEN:Class.NameCap*/::writeInstrumentation (Buffer& buf)
+{
+ instChanged = false;
+
+ writeTimestamps (buf);
+/*MGEN:Class.WriteInst*/
+
+ // Maintenance of hi-lo statistics
+/*MGEN:Class.HiLoStatResets*/
+}
+
+void /*MGEN:Class.NameCap*/::doMethod (/*MGEN:Class.DoMethodArgs*/)
+{
+ Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD;
+/*MGEN:Class.MethodHandlers*/
+ outBuf.putLong (status);
+ outBuf.putShortString (Manageable::StatusText (status));
+}
+
diff --git a/cpp/managementgen/templates/Class.h b/cpp/managementgen/templates/Class.h
new file mode 100644
index 0000000000..cff915412e
--- /dev/null
+++ b/cpp/managementgen/templates/Class.h
@@ -0,0 +1,69 @@
+#ifndef _MANAGEMENT_/*MGEN:Class.NameUpper*/_
+#define _MANAGEMENT_/*MGEN:Class.NameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/ManagementObject.h"
+
+namespace qpid {
+namespace management {
+
+class /*MGEN:Class.NameCap*/ : public ManagementObject
+{
+ private:
+
+ static bool schemaNeeded;
+
+ // Configuration Elements
+/*MGEN:Class.ConfigDeclarations*/
+ // Instrumentation Elements
+/*MGEN:Class.InstDeclarations*/
+ // Private Methods
+ std::string getObjectName (void) { return "/*MGEN:Class.NameLower*/"; }
+ void writeSchema (qpid::framing::Buffer& buf);
+ void writeConfig (qpid::framing::Buffer& buf);
+ void writeInstrumentation (qpid::framing::Buffer& buf);
+ bool getSchemaNeeded (void) { return schemaNeeded; }
+ void setSchemaNeeded (void) { schemaNeeded = true; }
+ void doMethod (std::string methodName,
+ qpid::framing::Buffer& inBuf,
+ qpid::framing::Buffer& outBuf);
+
+/*MGEN:Class.InstChangedStub*/
+ public:
+
+ typedef boost::shared_ptr</*MGEN:Class.NameCap*/> shared_ptr;
+
+ /*MGEN:Class.NameCap*/ (Manageable* coreObject, Manageable* parentObject,
+ /*MGEN:Class.ConstructorArgs*/);
+ ~/*MGEN:Class.NameCap*/ (void);
+
+ // Method IDs
+/*MGEN:Class.MethodIdDeclarations*/
+ // Accessor Methods
+/*MGEN:Class.AccessorMethods*/
+};
+
+}}
+
+
+#endif /*!_MANAGEMENT_/*MGEN:Class.NameUpper*/_*/