summaryrefslogtreecommitdiffstats
path: root/tools/class2dot.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/class2dot.py')
-rw-r--r--tools/class2dot.py181
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()
+