update for hostnames etc
[sfa.git] / rspec / rspecvalidate.py
1 #!/usr/bin/python
2
3 # $HeadURL$
4 # $Id$
5
6 #
7 # Validate RSPEC hiearchy, values, types, and names using supplied xsd.
8 #
9 # Faiyaz Ahmed <faiyaza at cs dot princeton dot edu>
10 #
11 # Copyright 2009 Princeton University
12 # http://www.planet-lab.org
13 #
14
15 import sys
16 import pprint
17 from xml.dom import minidom
18 from logging import Logger
19
20 logger = Logger
21
22 # The rspec is comprised of 2 parts, and 1 reference:
23 # attributes/elements describe individual resources
24 # complexTypes are used to describe a set of attributes/elements
25 # complexTypes can include a reference to other complexTypes.
26
27 def getText(nodelist):
28     rc = ""
29     for node in nodelist:
30         if node.nodeType == node.TEXT_NODE:
31             rc = rc + node.data
32     return rc
33
34 def getName(node):
35     '''Gets name of node.  Raises NameError exception if no name'''
36     if node.attributes.has_key("name"):
37         name = node.attributes.get("name").value
38     else: raise Exception("Can't find 'name'")
39     return name 
40
41 # complexType: a supernode comprised of attribute and/or element nodes below it.
42 def complexTypeDict(cmpTypeDom):
43     '''Traverse complex node.  Create a dict {name : [{attributename : {name: value,}, sequence]}'''
44     children = [] # array of dicts.  1 for each element/attribute.
45     if cmpTypeDom.hasChildNodes():
46         for child in cmpTypeDom.childNodes:
47             # attributes have tags and values.  get {tag: value}
48             if child.localName in ("attribute", "element"): children.append(attributeDict(child))
49             # sequence is a list of elements.  append dict to list
50             elif child.localName == "sequence": children.append(sequenceList(child))
51             elif child.localName == "simpleType":  pass #unsure what this type is used for.
52             else: Exception("Unknown type: %s" % child.localName)
53     node = { getName(cmpTypeDom) : children}
54     return node
55
56 # Attribute.  {name : nameofattribute, {items: values})
57 def attributeDict(attributeDom):
58     '''Traverse single attribute node.  Create a dict {attributename : {name: value,}]}'''
59     node = {} # parsed dict
60     for attr in attributeDom.attributes.keys():
61         node[attr] = attributeDom.attributes.get(attr).value
62     attribute = {getName(attributeDom) : node}
63     return attribute
64
65 def sequenceList(sequenceDom):
66     '''Return list of elements/attributes in sequence list'''
67     sequence = []
68     if sequenceDom.localName == "sequence": 
69         # for sanity
70         if sequenceDom.hasChildNodes:
71             for seqitm in sequenceDom.childNodes:
72                 if seqitm.localName in ("element", "attribute"): 
73                     sequence.append(attributeDict(seqitm))
74                 else: print "Idunno what %s is" % seqitm.localName
75         else: raise NameError
76     return sequence 
77
78 def schemaDict(document):
79     schema = {}
80     '''Parse the given schema and produce a dict of types'''
81     if document.hasChildNodes():
82         for i in document.childNodes:
83             if i.localName in ('element', 'attribute'): 
84                 schema.update(attributeDict(i))
85             elif i.localName == "complexType": 
86                 schema.update(complexTypeDict(i))                
87             else: print "Idunno what %s is" % i.localName
88     return schema
89
90 def main(fname):
91     pp = pprint.PrettyPrinter(indent=4)
92     dom = minidom.parse(fname)
93     print "Testing Complex Type:"
94     pp.pprint(complexTypeDict(dom.childNodes[0].childNodes[15]))
95     print "Testing Whole doc:"
96     pp.pprint(schemaDict(dom.childNodes[0]))
97
98 if __name__ == '__main__':  
99     main(fname="planetlab.xsd")