fix formatting
[sfa.git] / geni / util / rspec.py
1 import sys
2 import pprint
3 import os
4 from xml.dom import minidom
5 from types import StringTypes
6
7 class Spec(dict):
8
9     fields = {}
10     plcFields = {}
11     type = None
12         
13     def __init__(self, spec_dict):
14         sdict = self.plcToSpec(spec_dict)
15         dict.__init__(self, sdict)
16
17     def plcToSpec(self, spec_dict):
18         spec = {}
19         for field in self.fields:
20             plc_field = plc_fields[field]
21             
22             if spec_dict.has_key(field):
23                 spec[field] = spec_dict(field)
24         
25         return {self.type: spec}
26     
27
28 class IfSpec(Spec):
29     pass
30
31
32
33 class Rspec():
34
35     def __init__(self, xml = None, xsd = None):
36         self.xsd = xsd # schema
37         self.rootNode = None # root of the dom
38         self.dict = {} # dict of the rspec.
39         if xml: 
40             if type(xml) == file:
41                 self.parseFile(xml)
42             if type(xml) == str:
43                 self.parseString(xml)
44             self.dict = self.toDict() 
45   
46     def _getText(self, nodelist):
47         rc = ""
48         for node in nodelist:
49             if node.nodeType == node.TEXT_NODE:
50                 rc = rc + node.data
51         return rc
52   
53     # The rspec is comprised of 2 parts, and 1 reference:
54     # attributes/elements describe individual resources
55     # complexTypes are used to describe a set of attributes/elements
56     # complexTypes can include a reference to other complexTypes.
57   
58   
59     def _getName(self, node):
60         '''Gets name of node. If tag has no name, then return tag's localName'''
61         name = None
62         if not node.nodeName.startswith("#"):
63             if node.localName:
64                 name = node.localName
65             elif node.attributes.has_key("name"):
66                 name = node.attributes.get("name").value
67         return name     
68  
69  
70     # Attribute.  {name : nameofattribute, {items: values})
71     def _attributeDict(self, attributeDom):
72         '''Traverse single attribute node.  Create a dict {attributename : {name: value,}]}'''
73         node = {} # parsed dict
74         for attr in attributeDom.attributes.keys():
75             node[attr] = attributeDom.attributes.get(attr).value
76         return node
77   
78  
79     def toDict(self, nodeDom = None):
80         """
81         convert this rspec to a dict and return it.
82         """
83         node = {}
84         if not nodeDom:
85              nodeDom = self.rootNode
86   
87         elementName = nodeDom.nodeName
88         if elementName and not elementName.startswith("#"):
89             # attributes have tags and values.  get {tag: value}, else {type: value}
90             node[elementName] = self._attributeDict(nodeDom)
91             #node.update(self._attributeDict(nodeDom))
92             # resolve the child nodes.
93             if nodeDom.hasChildNodes():
94                 for child in nodeDom.childNodes:
95                     childName = self._getName(child)
96                     if not childName:
97                         continue
98                     if not node[elementName].has_key(childName):
99                         node[elementName][childName] = []       
100                         #node[childName] = []
101                     childdict = self.toDict(child)
102                     for value in childdict.values():
103                         node[elementName][childName].append(value)
104                     #node[childName].append(self.toDict(child))
105         return node
106
107   
108     def toxml(self):
109         """
110         convert this rspec to an xml string and return it.
111         """
112         return self.rootNode.toxml()
113
114   
115     def toprettyxml(self):
116         """
117         print this rspec in xml in a pretty format.
118         """
119         return self.rootNode.toprettyxml()
120
121   
122     def parseFile(self, filename):
123         """
124         read a local xml file and store it as a dom object.
125         """
126         dom = minidom.parse(filename)
127         self.rootNode = dom.childNodes[0]
128   
129   
130     def parseString(self, xml):
131         """
132         read an xml string and store it as a dom object.
133         """
134         xml = xml.replace('\n', '').replace('\t', '').strip()
135         dom = minidom.parseString(xml)
136         self.rootNode = dom.childNodes[0]
137
138  
139     def dict2dom(self, rdict, include_doc = False):
140         """
141         convert a dict object into a dom object.
142         """
143      
144         def elementNode(tagname, rd):
145             element = minidom.Element(tagname)   
146             for key in rd.keys():
147                 if isinstance(rd[key], StringTypes):
148                     element.setAttribute(key, rd[key])
149                 elif isinstance(rd[key], dict):
150                     child = elementNode(key, rd[key])
151                     element.appendChild(child)
152                 elif isinstance(rd[key], list):
153                     for item in rd[key]:
154                         child = elementNode(key, item)
155                         element.appendChild(child)
156             return element
157                      
158         node = elementNode(rdict.keys()[0], rdict.values()[0])
159         if include_doc:
160             rootNode = minidom.Document()
161             rootNode.appendChild(node)
162         else:
163             rootNode = node
164         return rootNode
165
166  
167     def parseDict(self, rdict, include_doc = True):
168         """
169         Convert a dictionary into a dom object and store it.
170         """
171         self.rootNode = self.dict2dom(rdict, include_doc)
172  
173  
174     def getDictsByTagName(self, tagname, dom = None):
175         """
176         Search the dom for all elements with the specified tagname
177         and return them as a list of dicts
178         """
179         if not dom:
180             dom = self.rootNode
181         dicts = []
182         doms = dom.getElementsByTagName(tagname)
183         dictlist = [self.toDict(d) for d in doms]
184         for item in dictlist:
185             for value in item.values():
186                 dicts.append(value)
187         return dicts
188
189 # vim:ts=4:expandtab