Package occi :: Package protocol :: Module html_rendering
[hide private]
[frames] | no frames]

Source Code for Module occi.protocol.html_rendering

  1  # coding=utf-8 
  2  # 
  3  # Copyright (C) 2010-2012 Platform Computing 
  4  # 
  5  # This library is free software; you can redistribute it and/or 
  6  # modify it under the terms of the GNU Lesser General Public 
  7  # License as published by the Free Software Foundation; either 
  8  # version 2.1 of the License, or (at your option) any later version. 
  9  # 
 10  # This library is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 13  # Lesser General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU Lesser General Public 
 16  # License along with this library; if not, write to the Free Software 
 17  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA 
 18  # 
 19  ''' 
 20  Non OCCI specific rendering for HTML. 
 21   
 22  Created on Jul 15, 2011 
 23   
 24  @author: tmetsch 
 25  ''' 
 26   
 27  # disabling 'Method is abstract' pylint check (HTML only support simple ops!) 
 28  # pylint: disable=W0223 
 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   
36 -class HTMLRendering(Rendering):
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
126 - def from_entity(self, entity):
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 # FUTURE_IMPROVEMENT: string links 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 &amp; Target</h2><ul>' 147 tmp += '<li><strong>Source: </strong>' 148 tmp += '<a href="' + entity.source.identifier + '">' 149 tmp += entity.source.identifier + '</a></li>' 150 # FUTURE_IMPROVEMENT: string links 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
175 - def _from_entity_head_html(self, entity):
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 # header 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 # breadcrumb 191 tmp += '\t\t<div id="breadcrumb"><a href="/">&raquo;</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 # body 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
217 - def from_entities(self, entities, key):
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 # header 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 # breadcrumb 229 tmp += '\t\t<div id="breadcrumb"><a href="/">&raquo;</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 # body 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
247 - def from_categories(self, categories):
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 # header 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 # breadcrumb 259 tmp += '\t\t<div id="breadcrumb"><a href="/">&raquo;</a> /</div>\n' 260 261 # body 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
307 - def to_action(self, headers, body, extras):
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