"""Specific views for schema related entities:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"fromitertoolsimportcyclefromlogilab.mtconverterimporthtml_escapefromyamsimportschema2dotass2dfromcubicweb.selectorsimportimplements,yesfromcubicweb.schemaviewerimportSchemaViewerfromcubicweb.viewimportEntityView,StartupViewfromcubicweb.common.uilibimportureport_as_htmlfromcubicweb.web.actionimportActionfromcubicweb.web.viewsimportbaseviewsfromcubicweb.web.viewsimportTmpFileViewMixinfromcubicweb.web.views.editformimportAutomaticEntityFormfromcubicweb.web.views.boxesimportEditBoxAutomaticEntityForm.rcategories.set_rtag('primary','require_group','subject','EPermission')AutomaticEntityForm.rcategories.set_rtag('generated','final','subject','EEtype')AutomaticEntityForm.rcategories.set_rtag('generated','final','subject','ERtype')AutomaticEntityForm.rinlined.set_rtag(True,'relation_type','subject','ENFRDef')AutomaticEntityForm.rinlined.set_rtag(True,'from_entity','subject','ENFRDef')AutomaticEntityForm.rinlined.set_rtag(True,'to_entity','subject','ENFRDef')AutomaticEntityForm.rwidgets.set_rtag('StringWidget','expression','subject','RQLExpression')EditBox.rmode.set_rtag('create','state_of','object','EEType')EditBox.rmode.set_rtag('create','transition_of','object','EEType')EditBox.rmode.set_rtag('create','relation_type','object','ERType')EditBox.rmode.set_rtag('link','from_entity','object','EEType')EditBox.rmode.set_rtag('link','to_entity','object','EEType')classViewSchemaAction(Action):id='schema'__select__=yes()title=_("site schema")category='siteactions'order=30defurl(self):returnself.build_url(self.id)# schema entity types views ###################################################class_SchemaEntityPrimaryView(baseviews.PrimaryView):show_attr_label=Falsecache_max_age=60*60*2# stay in http cache for 2 hours by default defcontent_title(self,entity):returnhtml_escape(entity.dc_long_title())classEETypePrimaryView(_SchemaEntityPrimaryView):__select__=implements('EEType')skip_attrs=_SchemaEntityPrimaryView.skip_attrs+('name','meta','final')classERTypePrimaryView(_SchemaEntityPrimaryView):__select__=implements('ERType')skip_attrs=_SchemaEntityPrimaryView.skip_attrs+('name','meta','final','symetric','inlined')classErdefPrimaryView(_SchemaEntityPrimaryView):__select__=implements('EFRDef','ENFRDef')show_attr_label=TrueclassEETypeOneLineView(baseviews.OneLineView):__select__=implements('EEType')defcell_call(self,row,col,**kwargs):entity=self.entity(row,col)final=entity.finaliffinal:self.w(u'<em class="finalentity">')super(EETypeOneLineView,self).cell_call(row,col,**kwargs)iffinal:self.w(u'</em>')# in memory schema views (yams class instances) ###############################classEETypeSchemaView(EETypePrimaryView):id='eschema'title=_('in memory entity schema')main_related_section=Falseskip_rels=('is','is_instance_of','identity','created_by','owned_by','has_text',)defrender_entity_attributes(self,entity,siderelations):super(EETypeSchemaView,self).render_entity_attributes(entity,siderelations)eschema=self.vreg.schema.eschema(entity.name)viewer=SchemaViewer(self.req)layout=viewer.visit_entityschema(eschema,skiprels=self.skip_rels)self.w(ureport_as_html(layout))ifnoteschema.is_final():self.w(u'<img src="%s" alt="%s"/>'%(html_escape(entity.absolute_url(vid='eschemagraph')),html_escape(self.req._('graphical schema for %s')%entity.name)))classERTypeSchemaView(ERTypePrimaryView):id='eschema'title=_('in memory relation schema')main_related_section=Falsedefrender_entity_attributes(self,entity,siderelations):super(ERTypeSchemaView,self).render_entity_attributes(entity,siderelations)rschema=self.vreg.schema.rschema(entity.name)viewer=SchemaViewer(self.req)layout=viewer.visit_relationschema(rschema)self.w(ureport_as_html(layout))ifnotrschema.is_final():self.w(u'<img src="%s" alt="%s"/>'%(html_escape(entity.absolute_url(vid='eschemagraph')),html_escape(self.req._('graphical schema for %s')%entity.name)))# schema images ###############################################################classImageView(EntityView):__select__=implements('EEType')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=('owned_by','created_by','identity','is','is_instance_of')def_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))classEETypeSchemaImageView(TmpFileViewMixin,EntityView):id='eschemagraph'content_type='image/png'__select__=implements('EEType')skip_rels=('owned_by','created_by','identity','is','is_instance_of')def_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))classERTypeSchemaImageView(EETypeSchemaImageView):__select__=implements('ERType')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))