1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 '''
20 Non OCCI specific rendering for HTML.
21
22 Created on Jul 15, 2011
23
24 @author: tmetsch
25 '''
26
27
28
29
30 from occi.core_model import Category
31 from occi.core_model import Resource, Link
32 from occi.handlers import QUERY_STRING
33 from occi.protocol.rendering import Rendering
34
35
37 '''
38 A simple HTML website rendering for monitoring the service...
39 '''
40
41 mime_type = 'text/html'
42
43 css = "body { \
44 font-family: sans-serif; \
45 font-size: 0.9em; \
46 margin: 0; \
47 padding: 0; \
48 } \
49 #header { \
50 background: #444; \
51 border-top: 5px solid #73c167; \
52 } \
53 #header ul { \
54 list-style-type: none; \
55 list-style-image: none; \
56 margin: 0; \
57 padding: 0; \
58 height: 2em; \
59 } \
60 #header li { \
61 margin: 0.2em 0.5em 0.3em 0.5em; \
62 font-weight: bold; \
63 display: inline-block; \
64 } \
65 #header li a { \
66 padding: 0.3em; \
67 text-decoration: none; \
68 color: #fff; \
69 } \
70 #header li a:hover { \
71 background: #73c167;\
72 } \
73 #breadcrumb { \
74 background: #efefea; \
75 padding: 1em; \
76 border-bottom: 1px solid #444; \
77 } \
78 td { \
79 padding: 0.2em; \
80 background: #eee; \
81 color: #444; \
82 } \
83 table { \
84 margin: 0 0 1em 1em; \
85 } \
86 table ul { \
87 margin: 0.3em; \
88 } \
89 th { \
90 background: #73c167; \
91 padding: 0.2em; \
92 color: #fff; \
93 } \
94 h2 { \
95 margin: 1em; \
96 font-size: 1.2em; \
97 color: #444; \
98 } \
99 a { \
100 color: #73c167; \
101 } \
102 a:visited { \
103 color: #444; \
104 } \
105 p {\
106 margin: 1em; \
107 } \
108 form {\
109 margin: 1em; \
110 } \
111 #entity { \
112 margin: 1em; \
113 }"
114
115 - def __init__(self, registry, css=None):
116 '''
117 Constructor for HTML rendering. Can be used to use other CSS.
118
119 registry -- Registry used in this service.
120 css -- If provided this CSS is used.
121 '''
122 Rendering.__init__(self, registry)
123 if css is not None:
124 self.css = css
125
127 tmp = self._from_entity_head_html(entity)
128
129 if 'occi.core.id' not in entity.attributes:
130 entity.attributes['occi.core.id'] = entity.identifier
131 if isinstance(entity, Resource):
132 if len(entity.links) > 0:
133 tmp += '\n\t\t\t<h2>Links</h2><table>'
134 tmp += '<tr><th>Kind</th><th>Link</th><th>Target</th></tr>'
135 for item in entity.links:
136 tmp += '<tr><td>' + item.kind.term + '</td>'
137 tmp += '<td><a href="' + item.identifier + '">'
138 tmp += item.identifier + '</a></td>'
139
140 tmp += '<td><a href="' + item.target.identifier + '">'
141 tmp += item.target.identifier + '</a></td>'
142 tmp += '</tr>'
143 tmp += '</table>\n'
144
145 elif isinstance(entity, Link):
146 tmp += '\n\t\t\t<h2>Source & Target</h2><ul>'
147 tmp += '<li><strong>Source: </strong>'
148 tmp += '<a href="' + entity.source.identifier + '">'
149 tmp += entity.source.identifier + '</a></li>'
150
151 tmp += '<li><strong>Target: </strong>'
152 tmp += '<a href="' + entity.target.identifier + '">'
153 tmp += entity.target.identifier + '</a></li></ul>\n'
154
155 if len(entity.attributes.keys()) > 0:
156 tmp += '\n\t\t\t<h2>Attributes</h2><table>'
157 for item in entity.attributes.keys():
158 tmp += '<tr><th>' + item + '</th><td>'
159 tmp += str(entity.attributes[item]) + '</td></tr>'
160 tmp += '</table>\n'
161
162 if len(entity.actions) > 0:
163 tmp += '\n\t\t\t<h2>Actions</h2>'
164 for action in entity.actions:
165 tmp += '<FORM action="' + entity.identifier + '?action='
166 tmp += str(action.term) + '?scheme=' + str(action.scheme)
167 tmp += '" method="post" />' '<INPUT type="submit" value="'
168 tmp += str(action.term) + '"/></FORM>'
169 tmp += '\n'
170
171 tmp += '\n\t\t</div>\n\t</body>\n</html>'
172
173 return {'Content-Type': self.mime_type}, tmp
174
176 '''
177 Private helper function which creates the first part of the HTML.
178
179 entity -- The entity to render.
180 '''
181 tmp = '<html>\n\t<head>\n'
182 tmp += '\t\t<title>Resource: ' + entity.identifier + '</title>\n'
183 tmp += '\t\t<style type="text/css"><!-- ' + self.css + ' --></style>\n'
184 tmp += '\t</head>\n\t<body>\n'
185
186
187 tmp += '\t\t<div id="header"><ul><li><a href="/">Home</a></li>'
188 tmp += '<li><a href="/-/">Query Interface</a></li></ul></div>\n'
189
190
191 tmp += '\t\t<div id="breadcrumb"><a href="/">»</a> /'
192 path = '/'
193 for item in entity.identifier.split('/')[1:-1]:
194 path += item + '/'
195 tmp += ' <a href="' + path + '">' + item + "</a> / "
196 tmp += '<a href="' + entity.identifier + '">'
197 tmp += entity.identifier.split('/')[-1] + '</a>'
198 tmp += '</div>\n'
199
200
201 tmp += '\t\t<div id="entity">\n\t\t\t<h2>Kind</h2><ul><li>'
202 tmp += '<a href="/-/#' + entity.kind.scheme + '-'
203 tmp += entity.kind.term + '">' + str(entity.kind) + '</a></li></ul>\n'
204 if len(entity.mixins) > 0:
205 tmp += '\t\t\t<h2>Mixins</h2><ul>'
206 for item in entity.mixins:
207 tmp += '<li><a href="/-/#' + item.scheme + '-'
208 tmp += item.term + '">' + str(item) + '</a></li>'
209 tmp += '</ul>\n'
210
211 if hasattr(entity, 'summary') and entity.summary != '':
212 tmp += '\t\t\t<h2>Summary</h2><p>' + str(entity.summary) + '</p>\n'
213 if entity.title != '':
214 tmp += '\t\t\t<h2>Title</h2><p>' + str(entity.title) + '</p>\n'
215 return tmp
216
218 tmp = '<html>\n\t<head>\n'
219 tmp += '\t\t<title>Resource listing: ' + key + '</title>\n'
220 tmp += '\t\t<style type="text/css"><!-- ' + self.css + ' --></style>\n'
221 tmp += '\t</head>\n'
222 tmp += '\t<body>\n'
223
224
225 tmp += '\t\t<div id="header"><ul><li><a href="/">Home</a></li>'
226 tmp += '<li><a href="/-/">Query Interface</a></li></ul></div>\n'
227
228
229 tmp += '\t\t<div id="breadcrumb"><a href="/">»</a> /'
230 path = '/'
231 for item in key.split('/')[1:-1]:
232 path += item + '/'
233 tmp += ' <a href="' + path + '">' + item + "</a> /"
234 tmp += '</div>\n'
235
236
237 tmp += '\t\t<div id="entity"><ul>\n'
238 if not len(entities):
239 tmp += '\t\t\t<li>No resources found</li>\n'
240 for item in entities:
241 tmp += '\t\t\t<li><a href="' + item.identifier + '">'
242 tmp += item.identifier + '</a></li>\n'
243 tmp += '\t\t</ul></div>\n'
244 tmp += '\t</body>\n</html>'
245 return {'Content-Type': self.mime_type}, tmp
246
248 tmp = '<html>\n\t<head>\n'
249 tmp += '\t\t<title>Query Interface</title>\n'
250 tmp += '\t\t<style type="text/css"><!-- ' + self.css + ' --></style>\n'
251 tmp += '\t</head>\n'
252 tmp += '\t<body>\n'
253
254
255 tmp += '\t\t<div id="header"><ul><li><a href="/">Home</a></li>'
256 tmp += '<li><a href="/-/">Query Interface</a></li></ul></div>\n'
257
258
259 tmp += '\t\t<div id="breadcrumb"><a href="/">»</a> /</div>\n'
260
261
262 tmp += '\t\t<div id="entity">\n'
263 for cat in categories:
264 tmp += '\t\t<h2><a name="' + cat.scheme + '-' + cat.term + '">'
265 tmp += repr(cat).upper() + ': ' + cat.term + '</a></h2>\n'
266 tmp += '\t\t<table>\n'
267 tmp += '\t\t\t<tr><th>Scheme</th><td>' + cat.scheme
268 tmp += '</td></tr>\n'
269 if hasattr(cat, 'title') and cat.title is not '':
270 tmp += '\t\t\t<tr><th>Title</th><td>' + cat.title
271 tmp += '</td></tr>\n'
272 if hasattr(cat, 'related') and len(cat.related) > 0:
273 rel_list = '<ul>'
274 for item in cat.related:
275 rel_list += '<li>' + str(item) + '</li>'
276 rel_list += '</ul>'
277 tmp += '\t\t\t<tr><th>Related</th><td>' + rel_list
278 tmp += '</td></tr>\n'
279 if hasattr(cat, 'location') and cat.location is not None:
280 tmp += '\t\t\t<tr><th>Location</th><td><a href="'
281 tmp += cat.location + '">' + cat.location + '</a></td></tr>\n'
282 if hasattr(cat, 'actions') and len(cat.actions) > 0:
283 acts = '<ul>'
284 for item in cat.actions:
285 acts += '<li>' + str(item) + '</li>'
286 acts += '</ul>'
287 tmp += '\t\t\t<tr><th>Actions</th><td>' + acts + '</td></tr>\n'
288 if hasattr(cat, 'attributes') and len(cat.attributes) > 0:
289 attrs = '<ul>'
290 for item in cat.attributes:
291 if cat.attributes[item] == 'required':
292 attrs += '<li>' + item
293 attrs += ' (<strong>required</strong>)</li>'
294 elif cat.attributes[item] == 'immutable':
295 attrs += '<li>' + item
296 attrs += ' (<strong>immutable</strong>)</li>'
297 else:
298 attrs += '<li>' + item + '</li>'
299 attrs += '</ul>'
300 tmp += '\t\t\t<tr><th>Attributes</th><td>' + attrs
301 tmp += '</td></tr>\n'
302 tmp += '\t\t</table>\n'
303
304 tmp += '\t\t</div>\n\t</body>\n</html>'
305 return {'Content-Type': self.mime_type}, tmp
306
308 cat_str = headers.get(QUERY_STRING)
309 scheme_index = cat_str.find('scheme=')
310 if scheme_index != -1:
311 scheme = cat_str[scheme_index + 7:]
312 else:
313 raise AttributeError('Unable to find the scheme. Broken request?.')
314
315 index = cat_str.find('action=')
316 if index != -1:
317 term = cat_str[index + 7:scheme_index - 1]
318 else:
319 raise AttributeError('Unable to find the term. Broken request?.')
320
321 tmp = Category(scheme + '#', term, '', {}, '')
322 cats = self.registry.get_categories(extras)
323 if tmp in cats:
324 for item in self.registry.get_categories(extras):
325 if tmp == item:
326 del tmp
327 return item, {}
328 else:
329 raise AttributeError('Action is not defined. Check the QI.')
330