diff options
author | Jan Safranek <jsafrane@redhat.com> | 2012-09-05 09:57:30 +0200 |
---|---|---|
committer | Jan Safranek <jsafrane@redhat.com> | 2012-09-05 09:57:30 +0200 |
commit | 9a48b63282e2f8d498e548a023c5c99cfced4232 (patch) | |
tree | 74c988ebfbf8b8faec972201249219832e3839c4 /tools/class2dot.py | |
parent | 902b1b295317a19210715f7bba210f1a2df499db (diff) | |
download | openlmi-providers-9a48b63282e2f8d498e548a023c5c99cfced4232.tar.gz openlmi-providers-9a48b63282e2f8d498e548a023c5c99cfced4232.tar.xz openlmi-providers-9a48b63282e2f8d498e548a023c5c99cfced4232.zip |
Added class2* tools.
Diffstat (limited to 'tools/class2dot.py')
-rw-r--r-- | tools/class2dot.py | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/tools/class2dot.py b/tools/class2dot.py new file mode 100644 index 0000000..71fff48 --- /dev/null +++ b/tools/class2dot.py @@ -0,0 +1,181 @@ +#!/usr/bin/python + +# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + +import os; +import pywbem; +import optparse +import re +import cgi +import sys + +class DotExporter(object): + + def __init__(self, cliconn): + self.classcache = {} + self.cliconn = cliconn + # original list of classes + self.classes = set() + self.file = sys.stdout + + def load_class(self, classname): + if classname in self.classcache: + return self.classcache[classname] + + c = self.cliconn.GetClass(classname) + self.classcache[classname] = c + return c + + def display_type(self, param): + """ + Return displayable type of given parameter. + It adds [] if it's array and class name of referenced classes. + """ + if param.reference_class: + ptype = param.reference_class + else: + ptype = param.type + if param.is_array: + ptype = ptype + "[]" + return ptype + + def print_parameters(self, params): + """ + Print table of method parametes. + """ + if not params: + print >>self.file, "None" + return + + print >>self.file, "<table class=\"parameters\">" + for p in params.values(): + direction = set() + if p.qualifiers.has_key("Out"): + direction.add("OUT") + if p.qualifiers.has_key("In"): + direction.add("IN") + if not direction: + direction.add("IN") + direction = "/".join(sorted(direction)) + + print >>self.file, "<tr>" + print >>self.file, "<td>%s</td><td>%s</td><td><b>%s</b></td>" % (direction, self.display_type(p), p.name) + print >>self.file, "<td><table class=\"qualifiers\">" + self.print_qualifiers(p.qualifiers.values()) + print >>self.file, "</table></td>" + print >>self.file, "</tr>" + print >>self.file, "</table>" + + def print_qualifiers(self, qualifiers): + """ + Print contenf of table of qualifiers. + Only Deprecated, Description, Values and ValueMap are recognized. + """ + deprecated = "" + for q in sorted(qualifiers): + if q.name == "Deprecated": + deprecated = "<div class=\"deprecated\">DEPRECATED</div> " + if q.name == "Description": + print >>self.file, "<tr><td class=\"qualifiers\" colspan=\"2\">%s%s</td></tr>" % (deprecated, self.escape(q.value)) + if q.name == "Values": + print >>self.file, "<tr><td class=\"qualifiers\"><b>Values</b></td> <td class=\"qualifiers\"><table><tr><td class=\"qualifiers\">%s</td></tr></table></td></tr>" % ("</td></tr><tr><td class=\"qualifiers\">".join(q.value)) + if q.name == "ValueMap": + print >>self.file, "<tr><td class=\"qualifiers\"><b>ValueMap</b></td> <td class=\"qualifiers\"><table><tr><td class=\"qualifiers\">%s</td></tr></table></td></tr>" % ("</td></tr><tr><td class=\"qualifiers\">".join(q.value)) + + def print_class(self, c, display_local = True): + """ + Print one class, inc. header. + """ + parent = None + if c.superclass: + parent = self.load_class(c.superclass) + + if c.superclass: + # draw arrow to parent + print >>self.file, "\"%s\"->\"%s\"" % (c.classname, c.superclass) + + local_props = [] + for name in sorted(c.properties.keys()): + if parent and parent.properties.has_key(name): + pass + else: + local_props.append(c.properties[name]) + + local_methods = [] + for name in sorted(c.methods.keys()): + if parent and parent.methods.has_key(name): + pass + else: + local_methods.append(c.methods[name]) + + self.file.write("\"%s\" [href=\"%s.html\",shape=\"record\", label=\"{%s" %(c.classname, c.classname, c.classname)) + + if display_local: + self.file.write("|") + for prop in local_props: + self.file.write("%s %s\\l" % (self.display_type(prop), prop.name)) + + self.file.write("|") + + if local_methods: + for m in local_methods: + self.file.write("%s()\l" % (m.name)) + + self.file.write("}\"];\n") + + + def add_class(self, classname): + self.classes.add(classname) + + def export(self): + """ + Print all classes and their parent. + """ + print >>self.file, """ +digraph "classes_No_Name" { +charset="utf-8" +rankdir=BT +node [shape="record"] +edge [arrowhead="empty"] +""" + while self.classes: + c = self.classes.pop() + self.print_class(self.load_class(c)) + + print >>self.file, "}" + +description = """ +Generate UML image for given classes. The tool connects to specified CIMOM +and reads class definition from there. Each class specified on command line +will be drawn as one box, containing locally defined or re-defined properties +and methods. Inheritance will be shown as arrow between a parent class and a +subclass. +""" + +parser = optparse.OptionParser(usage="usage: %prog [options] classname [classname ...]", description=description) +parser.add_option('-u', '--url', action='store', dest='addr', default='https://localhost:5989', help='URL of CIM server, default: https://localhost:5989') +parser.add_option('-U', '--user', action='store', dest='user', default=None, help='CIM user name') +parser.add_option('-P', '--password', action='store', dest='password', default=None, help='CIM password') +(options, args) = parser.parse_args() + +sys.stdout.softspace=0 + +cliconn = pywbem.WBEMConnection(options.addr, (options.user, options.password)) +exporter = DotExporter(cliconn) +for c in args: + exporter.add_class(c) +exporter.export() + |