"""Specific views for schema related entities:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"fromitertoolsimportcyclefromlogilab.mtconverterimporthtml_escapefromyamsimportschema2dotass2dfromcubicweb.selectorsimportimplements,yesfromcubicweb.schemaviewerimportSchemaViewerfromcubicweb.viewimportEntityView,StartupViewfromcubicweb.commonimporttags,uilibfromcubicweb.webimportactionfromcubicweb.web.viewsimportTmpFileViewMixin,primary,baseviewsclassViewSchemaAction(action.Action):id='schema'__select__=yes()title=_("site schema")category='siteactions'order=30defurl(self):returnself.build_url(self.id)# schema entity types views ###################################################classCWRDEFPrimaryView(primary.PrimaryView):__select__=implements('CWAttribute','CWRelation')cache_max_age=60*60*2# stay in http cache for 2 hours by defaultdefrender_entity_title(self,entity):self.w(u'<h1><span class="etype">%s</span> %s</h1>'%(entity.dc_type().capitalize(),html_escape(entity.dc_long_title())))classCWETypeOneLineView(baseviews.OneLineView):__select__=implements('CWEType')defcell_call(self,row,col,**kwargs):entity=self.entity(row,col)final=entity.finaliffinal:self.w(u'<em class="finalentity">')super(CWETypeOneLineView,self).cell_call(row,col,**kwargs)iffinal:self.w(u'</em>')# in memory schema views (yams class instances) ###############################SKIPPED_RELS=('is','is_instance_of','identity','created_by','owned_by','has_text',)classCWETypeSchemaView(primary.PrimaryView):id='eschema'__select__=implements('CWEType')title=_('in memory entity schema')main_related_section=Falseskip_rels=SKIPPED_RELSdefrender_entity_attributes(self,entity):super(CWETypeSchemaView,self).render_entity_attributes(entity)eschema=self.vreg.schema.eschema(entity.name)viewer=SchemaViewer(self.req)layout=viewer.visit_entityschema(eschema,skiprels=self.skip_rels)self.w(uilib.ureport_as_html(layout))ifnoteschema.is_final():msg=self.req._('graphical schema for %s')%entity.nameself.w(tags.img(src=entity.absolute_url(vid='eschemagraph'),alt=msg))classCWRTypeSchemaView(primary.PrimaryView):id='eschema'__select__=implements('CWRType')title=_('in memory relation schema')main_related_section=Falsedefrender_entity_attributes(self,entity):super(CWRTypeSchemaView,self).render_entity_attributes(entity)rschema=self.vreg.schema.rschema(entity.name)viewer=SchemaViewer(self.req)layout=viewer.visit_relationschema(rschema)self.w(uilib.ureport_as_html(layout))ifnotrschema.is_final():msg=self.req._('graphical schema for %s')%entity.nameself.w(tags.img(src=entity.absolute_url(vid='eschemagraph'),alt=msg))# schema images ###############################################################classImageView(EntityView):__select__=implements('CWEType')id='image'title=_('image')defcell_call(self,row,col):entity=self.entity(row,col)url=entity.absolute_url(vid='eschemagraph')self.w(u'<img src="%s" alt="%s"/>'%(html_escape(url),html_escape(self.req._('graphical schema for %s')%entity.name)))classRestrictedSchemaDotPropsHandler(s2d.SchemaDotPropsHandler):def__init__(self,req):# FIXME: colors are arbitraryself.nextcolor=cycle(('#aa0000','#00aa00','#0000aa','#000000','#888888')).nextself.req=reqdefdisplay_attr(self,rschema):returnnotrschema.metaand(rschema.has_local_role('read')orrschema.has_perm(self.req,'read'))# XXX remove this method once yams > 0.20 is outdefnode_properties(self,eschema):"""return default DOT drawing options for an entity schema"""label=['{',eschema.type,'|']label.append(r'\l'.join(rel.typeforrelineschema.subject_relations()ifrel.finalandself.display_attr(rel)))label.append(r'\l}')# trailing \l ensure alignement of the last onereturn{'label':''.join(label),'shape':"record",'fontname':"Courier",'style':"filled"}defedge_properties(self,rschema,subjnode,objnode):kwargs=super(RestrictedSchemaDotPropsHandler,self).edge_properties(rschema,subjnode,objnode)# symetric rels are handled differently, let yams decide what's bestifnotrschema.symetric:kwargs['color']=self.nextcolor()kwargs['fontcolor']=kwargs['color']# dot label decoration is just awful (1 line underlining the label# + 1 line going to the closest edge spline point)kwargs['decorate']='false'returnkwargsclassRestrictedSchemaVisitorMiIn:def__init__(self,req,*args,**kwargs):# hack hack hackassertlen(self.__class__.__bases__)==2self.__parent=self.__class__.__bases__[1]self.__parent.__init__(self,*args,**kwargs)self.req=reqdefnodes(self):foretype,eschemainself.__parent.nodes(self):ifeschema.has_local_role('read')oreschema.has_perm(self.req,'read'):yieldeschema.type,eschemadefedges(self):forsetype,oetype,rschemainself.__parent.edges(self):ifrschema.has_local_role('read')orrschema.has_perm(self.req,'read'):yieldsetype,oetype,rschemaclassFullSchemaVisitor(RestrictedSchemaVisitorMiIn,s2d.FullSchemaVisitor):passclassOneHopESchemaVisitor(RestrictedSchemaVisitorMiIn,s2d.OneHopESchemaVisitor):passclassOneHopRSchemaVisitor(RestrictedSchemaVisitorMiIn,s2d.OneHopRSchemaVisitor):passclassSchemaImageView(TmpFileViewMixin,StartupView):id='schemagraph'content_type='image/png'skip_rels=SKIPPED_RELSdef_generate(self,tmpfile):"""display global schema information"""skipmeta=notint(self.req.form.get('withmeta',0))visitor=FullSchemaVisitor(self.req,self.schema,skiprels=self.skip_rels,skipmeta=skipmeta)s2d.schema2dot(outputfile=tmpfile,visitor=visitor,prophdlr=RestrictedSchemaDotPropsHandler(self.req))classCWETypeSchemaImageView(TmpFileViewMixin,EntityView):id='eschemagraph'__select__=implements('CWEType')content_type='image/png'skip_rels=SKIPPED_RELSdef_generate(self,tmpfile):"""display schema information for an entity"""entity=self.entity(self.row,self.col)eschema=self.vreg.schema.eschema(entity.name)visitor=OneHopESchemaVisitor(self.req,eschema,skiprels=self.skip_rels)s2d.schema2dot(outputfile=tmpfile,visitor=visitor,prophdlr=RestrictedSchemaDotPropsHandler(self.req))classCWRTypeSchemaImageView(CWETypeSchemaImageView):__select__=implements('CWRType')def_generate(self,tmpfile):"""display schema information for an entity"""entity=self.entity(self.row,self.col)rschema=self.vreg.schema.rschema(entity.name)visitor=OneHopRSchemaVisitor(self.req,rschema)s2d.schema2dot(outputfile=tmpfile,visitor=visitor,prophdlr=RestrictedSchemaDotPropsHandler(self.req))