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