made into class. added complexcontenttype.
[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 import httplib
20
21 logger = Logger
22
23 NSURL = "www.planet-lab.org"
24 xsd = "planetlab.xsd"
25
26 def getText(nodelist):
27     rc = ""
28     for node in nodelist:
29         if node.nodeType == node.TEXT_NODE:
30             rc = rc + node.data
31     return rc
32
33 # The rspec is comprised of 2 parts, and 1 reference:
34 # attributes/elements describe individual resources
35 # complexTypes are used to describe a set of attributes/elements
36 # complexTypes can include a reference to other complexTypes.
37
38
39 class Schema():
40     def __init__(self):
41         # _getSchema()
42         pass
43
44     def _getSchema(self):
45         h1 = httplib.HTTPConnection(NSURL)
46         h1.request("GET", "/" + xsd)
47         r1 = h1.read()
48         self.schemadom = minidom.parseString(r1)
49
50     def getName(self, node):
51         '''Gets name of node.  Raises NameError exception if no name'''
52         if node.attributes.has_key("name"):
53             name = node.attributes.get("name").value
54         else: raise Exception("Can't find 'name'")
55         return name 
56     
57     # complexType: a supernode comprised of attribute and/or element nodes below it.
58     def complexTypeDict(self, cmpTypeDom):
59         '''Traverse complex node.  Create a dict 
60         {name : [{attributename : {name: value,}, sequence]}'''
61         children = [] # array of dicts.  1 for each element/attribute.
62         if cmpTypeDom.hasChildNodes():
63             for child in cmpTypeDom.childNodes:
64                 # attributes have tags and values.  get {tag: value}
65                 if child.localName in ("attribute", "element"): 
66                     children.append(self.attributeDict(child))
67                 # sequence is a list of elements.  append dict to list
68                 elif child.localName == "sequence": children.append(self.sequenceList(child))
69                 elif child.localName == "simpleType":  pass #unsure what this type is used for.
70                 elif child.localName == "complexContent": 
71                 else: Exception("Unknown type: %s" % child.localName)
72         node = { self.getName(cmpTypeDom) : children}
73         return node
74
75     def complexContent(self, ccontentDom):
76         '''Traverse complexContent.  Return {extention, element}'''
77         if ccontentDom.localName == "complexContent":
78             for child in ccontentDom.childNodes: pass
79         else: raise Exception("%s is not complexContent" % contentDom.localName)
80         return node 
81
82     # Attribute.  {name : nameofattribute, {items: values})
83     def attributeDict(self, attributeDom):
84         '''Traverse single attribute node.  Create a dict {attributename : {name: value,}]}'''
85         node = {} # parsed dict
86         for attr in attributeDom.attributes.keys():
87             node[attr] = attributeDom.attributes.get(attr).value
88         attribute = {self.getName(attributeDom) : node}
89         return attribute
90
91     # Sequence. [{tag:value},]
92     def sequenceList(self, sequenceDom):
93         '''Return list of elements/attributes in sequence list'''
94         sequence = []
95         if sequenceDom.localName == "sequence": 
96             # for sanity
97             if sequenceDom.hasChildNodes:
98                 for seqitm in sequenceDom.childNodes:
99                     if seqitm.localName in ("element", "attribute"): 
100                         sequence.append(self.attributeDict(seqitm))
101                     else: print "Idunno what %s is" % seqitm.localName
102         else: raise NameError
103         return sequence 
104     
105     def schemaDict(self, document):
106         self.schema = {}
107         '''Parse the given schema and produce a dict of types'''
108         if document.hasChildNodes():
109             for i in document.childNodes:
110                 if i.localName in ('element', 'attribute'): 
111                     self.schema.update(self.attributeDict(i))
112                 elif i.localName == "complexType": 
113                     self.schema.update(self.complexTypeDict(i))                
114                 else: print "Idunno what %s is" % i.localName
115         return self.schema
116
117
118
119     
120 def main(fname):
121     pp = pprint.PrettyPrinter(indent=4)
122     dom = minidom.parse(fname)
123     print "Testing Complex Type:"
124     s = Schema()
125     pp.pprint(s.complexTypeDict(dom.childNodes[0].childNodes[21]))
126     print "Testing Whole doc:"
127     pp.pprint(s.schemaDict(dom.childNodes[0]))
128
129 if __name__ == '__main__':  
130     main(fname="planetlab.xsd")