Assignment of resources to concepts and vice versa
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1108 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
		
							parent
							
								
									fc6946be95
								
							
						
					
					
						commit
						d6b7f5bc1f
					
				
					 10 changed files with 410 additions and 47 deletions
				
			
		
							
								
								
									
										53
									
								
								README.txt
									
										
									
									
									
								
							
							
						
						
									
										53
									
								
								README.txt
									
										
									
									
									
								
							| 
						 | 
					@ -121,7 +121,7 @@ a special concept type.
 | 
				
			||||||
Concept Views
 | 
					Concept Views
 | 
				
			||||||
-------------
 | 
					-------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> from loops.browser.concept import ConceptView
 | 
					  >>> from loops.browser.concept import ConceptView, ConceptConfigureView
 | 
				
			||||||
  >>> view = ConceptView(cc1, TestRequest())
 | 
					  >>> view = ConceptView(cc1, TestRequest())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> children = list(view.children())
 | 
					  >>> children = list(view.children())
 | 
				
			||||||
| 
						 | 
					@ -136,18 +136,19 @@ of URIs to item and the predicate of the relationship:
 | 
				
			||||||
  >>> [c.token for c in children]
 | 
					  >>> [c.token for c in children]
 | 
				
			||||||
  ['.loops/concepts/cc2:.loops/concepts/standard']
 | 
					  ['.loops/concepts/cc2:.loops/concepts/standard']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The concept view allows updating the underlying context object:
 | 
					There is also a concept configuration view that allows updating the
 | 
				
			||||||
 | 
					underlying context object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> cc3 = Concept(u'loops for Zope 3')
 | 
					  >>> cc3 = Concept(u'loops for Zope 3')
 | 
				
			||||||
  >>> concepts['cc3'] = cc3
 | 
					  >>> concepts['cc3'] = cc3
 | 
				
			||||||
  >>> view = ConceptView(cc1,
 | 
					  >>> view = ConceptConfigureView(cc1,
 | 
				
			||||||
  ...           TestRequest(action='assign', tokens=['.loops/concepts/cc3']))
 | 
					  ...           TestRequest(action='assign', tokens=['.loops/concepts/cc3']))
 | 
				
			||||||
  >>> view.update()
 | 
					  >>> view.update()
 | 
				
			||||||
  True
 | 
					  True
 | 
				
			||||||
  >>> sorted(c.title for c in cc1.getChildren())
 | 
					  >>> sorted(c.title for c in cc1.getChildren())
 | 
				
			||||||
  [u'Zope 3', u'loops for Zope 3']
 | 
					  [u'Zope 3', u'loops for Zope 3']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> view = ConceptView(cc1,
 | 
					  >>> view = ConceptConfigureView(cc1,
 | 
				
			||||||
  ...           TestRequest(action='remove', qualifier='children',
 | 
					  ...           TestRequest(action='remove', qualifier='children',
 | 
				
			||||||
  ...               tokens=['.loops/concepts/cc2:.loops/concepts/standard']))
 | 
					  ...               tokens=['.loops/concepts/cc2:.loops/concepts/standard']))
 | 
				
			||||||
  >>> view.update()
 | 
					  >>> view.update()
 | 
				
			||||||
| 
						 | 
					@ -159,14 +160,14 @@ We can also create a new concept and assign it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> params = {'action': 'create', 'create.name': 'cc4',
 | 
					  >>> params = {'action': 'create', 'create.name': 'cc4',
 | 
				
			||||||
  ...           'create.title': u'New concept'}
 | 
					  ...           'create.title': u'New concept'}
 | 
				
			||||||
  >>> view = ConceptView(cc1, TestRequest(**params))
 | 
					  >>> view = ConceptConfigureView(cc1, TestRequest(**params))
 | 
				
			||||||
  >>> view.update()
 | 
					  >>> view.update()
 | 
				
			||||||
  True
 | 
					  True
 | 
				
			||||||
  >>> sorted(c.title for c in cc1.getChildren())
 | 
					  >>> sorted(c.title for c in cc1.getChildren())
 | 
				
			||||||
  [u'New concept', u'loops for Zope 3']
 | 
					  [u'New concept', u'loops for Zope 3']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The concept view provides methods for displaying concept types and
 | 
					The concept configuration view provides methods for displaying concept
 | 
				
			||||||
predicates:
 | 
					types and predicates:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> from zope.publisher.interfaces.browser import IBrowserRequest
 | 
					  >>> from zope.publisher.interfaces.browser import IBrowserRequest
 | 
				
			||||||
  >>> from loops.browser.common import LoopsTerms
 | 
					  >>> from loops.browser.common import LoopsTerms
 | 
				
			||||||
| 
						 | 
					@ -257,14 +258,32 @@ We can associate a resource with a concept by assigning it to the concept:
 | 
				
			||||||
  >>> list(res)
 | 
					  >>> list(res)
 | 
				
			||||||
  [<loops.resource.Document ...>]
 | 
					  [<loops.resource.Document ...>]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The resource also provides access to the associated concepts (or views, see
 | 
					The concept configuration view discussed above also manages the relations
 | 
				
			||||||
below) via the getClients() method:
 | 
					from concepts to resources:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> conc = doc1.getClients()
 | 
					  >>> len(cc1.getResources())
 | 
				
			||||||
  >>> len(conc)
 | 
					 | 
				
			||||||
  1
 | 
					  1
 | 
				
			||||||
  >>> conc[0] is cc1
 | 
					  >>> form = dict(action='remove', qualifier='resources',
 | 
				
			||||||
 | 
					  ...               tokens=['.loops/resources/doc1:.loops/concepts/standard'])
 | 
				
			||||||
 | 
					  >>> view = ConceptConfigureView(cc1, TestRequest(form=form))
 | 
				
			||||||
 | 
					  >>> [zapi.getName(r.context) for r in view.resources()]
 | 
				
			||||||
 | 
					  [u'doc1']
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
  True
 | 
					  True
 | 
				
			||||||
 | 
					  >>> len(cc1.getResources())
 | 
				
			||||||
 | 
					  0
 | 
				
			||||||
 | 
					  >>> form = dict(action='assign', assignAs='resource',
 | 
				
			||||||
 | 
					  ...               tokens=['.loops/resources/doc1'])
 | 
				
			||||||
 | 
					  >>> view = ConceptConfigureView(cc1, TestRequest(form=form))
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					  >>> len(cc1.getResources())
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These relations may also be managed starting from a resource using
 | 
				
			||||||
 | 
					the resource configuration view:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from loops.browser.resource import ResourceConfigureView
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
Index attributes adapter
 | 
					Index attributes adapter
 | 
				
			||||||
------------------------
 | 
					------------------------
 | 
				
			||||||
| 
						 | 
					@ -393,6 +412,16 @@ out - this is usually done through ZCML.)
 | 
				
			||||||
  >>> m111.target is cc2
 | 
					  >>> m111.target is cc2
 | 
				
			||||||
  True
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A resource provides access to the associated views/nodes via the
 | 
				
			||||||
 | 
					getClients() method:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> len(doc1.getClients())
 | 
				
			||||||
 | 
					  0
 | 
				
			||||||
 | 
					  >>> m112.target = doc1
 | 
				
			||||||
 | 
					  >>> nodes = doc1.getClients()
 | 
				
			||||||
 | 
					  >>> nodes[0] is m112
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Node Views
 | 
					Node Views
 | 
				
			||||||
----------
 | 
					----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ from zope.app.dublincore.interfaces import ICMFDublinCore
 | 
				
			||||||
from zope.app.event.objectevent import ObjectCreatedEvent
 | 
					from zope.app.event.objectevent import ObjectCreatedEvent
 | 
				
			||||||
from zope.app.form.browser.interfaces import ITerms
 | 
					from zope.app.form.browser.interfaces import ITerms
 | 
				
			||||||
from zope.cachedescriptors.property import Lazy
 | 
					from zope.cachedescriptors.property import Lazy
 | 
				
			||||||
 | 
					from zope.dottedname.resolve import resolve
 | 
				
			||||||
from zope.event import notify
 | 
					from zope.event import notify
 | 
				
			||||||
from zope.interface import implements
 | 
					from zope.interface import implements
 | 
				
			||||||
from zope.publisher.interfaces import BadRequest
 | 
					from zope.publisher.interfaces import BadRequest
 | 
				
			||||||
| 
						 | 
					@ -35,7 +36,10 @@ from zope.publisher.interfaces.browser import IBrowserRequest
 | 
				
			||||||
from zope import schema
 | 
					from zope import schema
 | 
				
			||||||
from zope.schema.interfaces import IIterableSource
 | 
					from zope.schema.interfaces import IIterableSource
 | 
				
			||||||
from zope.security.proxy import removeSecurityProxy
 | 
					from zope.security.proxy import removeSecurityProxy
 | 
				
			||||||
 | 
					from loops.interfaces import IConcept
 | 
				
			||||||
from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList
 | 
					from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList
 | 
				
			||||||
 | 
					from loops.resource import getResourceTypes, getResourceTypesForSearch
 | 
				
			||||||
 | 
					from loops.target import getTargetTypes
 | 
				
			||||||
from loops.browser.common import BaseView, LoopsTerms
 | 
					from loops.browser.common import BaseView, LoopsTerms
 | 
				
			||||||
from loops import util
 | 
					from loops import util
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +54,13 @@ class ConceptView(BaseView):
 | 
				
			||||||
        for r in self.context.getParentRelations():
 | 
					        for r in self.context.getParentRelations():
 | 
				
			||||||
            yield ConceptRelationView(r, self.request)
 | 
					            yield ConceptRelationView(r, self.request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resources(self):
 | 
				
			||||||
 | 
					        for r in self.context.getResourceRelations():
 | 
				
			||||||
 | 
					            yield ConceptResourceRelationView(r, self.request, contextIsSecond=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConceptConfigureView(ConceptView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update(self):
 | 
					    def update(self):
 | 
				
			||||||
        request = self.request
 | 
					        request = self.request
 | 
				
			||||||
        action = request.get('action')
 | 
					        action = request.get('action')
 | 
				
			||||||
| 
						 | 
					@ -75,6 +86,8 @@ class ConceptView(BaseView):
 | 
				
			||||||
                    self.context.assignChild(removeSecurityProxy(concept), predicate)
 | 
					                    self.context.assignChild(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
                elif assignAs == 'parent':
 | 
					                elif assignAs == 'parent':
 | 
				
			||||||
                    self.context.assignParent(removeSecurityProxy(concept), predicate)
 | 
					                    self.context.assignParent(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
 | 
					                elif assignAs == 'resource':
 | 
				
			||||||
 | 
					                    self.context.assignResource(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs)
 | 
					                    raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs)
 | 
				
			||||||
            elif action == 'remove':
 | 
					            elif action == 'remove':
 | 
				
			||||||
| 
						 | 
					@ -84,6 +97,8 @@ class ConceptView(BaseView):
 | 
				
			||||||
                    self.context.deassignParent(concept, [predicate])
 | 
					                    self.context.deassignParent(concept, [predicate])
 | 
				
			||||||
                elif qualifier == 'children':
 | 
					                elif qualifier == 'children':
 | 
				
			||||||
                    self.context.deassignChild(concept, [predicate])
 | 
					                    self.context.deassignChild(concept, [predicate])
 | 
				
			||||||
 | 
					                elif qualifier == 'resources':
 | 
				
			||||||
 | 
					                    self.context.deassignResource(concept, [predicate])
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    raise(BadRequest, 'Illegal qualifier: %s.' % qualifier)
 | 
					                    raise(BadRequest, 'Illegal qualifier: %s.' % qualifier)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
| 
						 | 
					@ -97,6 +112,11 @@ class ConceptView(BaseView):
 | 
				
			||||||
            raise(BadRequest, 'Empty name.')
 | 
					            raise(BadRequest, 'Empty name.')
 | 
				
			||||||
        title = request.get('create.title', u'')
 | 
					        title = request.get('create.title', u'')
 | 
				
			||||||
        conceptType = request.get('create.type')
 | 
					        conceptType = request.get('create.type')
 | 
				
			||||||
 | 
					        if conceptType and conceptType.startswith('loops.resource.'):
 | 
				
			||||||
 | 
					            factory = resolve(conceptType)
 | 
				
			||||||
 | 
					            concept = factory(title)
 | 
				
			||||||
 | 
					            container = self.loopsRoot.getResourceManager()
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
            concept = Concept(title)
 | 
					            concept = Concept(title)
 | 
				
			||||||
            container = self.loopsRoot.getConceptManager()
 | 
					            container = self.loopsRoot.getConceptManager()
 | 
				
			||||||
        container[name] = concept
 | 
					        container[name] = concept
 | 
				
			||||||
| 
						 | 
					@ -113,6 +133,8 @@ class ConceptView(BaseView):
 | 
				
			||||||
            self.context.assignChild(removeSecurityProxy(concept), predicate)
 | 
					            self.context.assignChild(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
        elif assignAs == 'parent':
 | 
					        elif assignAs == 'parent':
 | 
				
			||||||
            self.context.assignParent(removeSecurityProxy(concept), predicate)
 | 
					            self.context.assignParent(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
 | 
					        elif assignAs == 'resource':
 | 
				
			||||||
 | 
					            self.context.assignResource(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs)
 | 
					            raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,7 +175,10 @@ class ConceptView(BaseView):
 | 
				
			||||||
    def viewIterator(self, objs):
 | 
					    def viewIterator(self, objs):
 | 
				
			||||||
        request = self.request
 | 
					        request = self.request
 | 
				
			||||||
        for o in objs:
 | 
					        for o in objs:
 | 
				
			||||||
            yield ConceptView(o, request)
 | 
					            if IConcept.providedBy(o):
 | 
				
			||||||
 | 
					                yield ConceptConfigureView(o, request)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                yield BaseView(o, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def conceptTypes(self):
 | 
					    def conceptTypes(self):
 | 
				
			||||||
        types = ConceptTypeSourceList(self.context)
 | 
					        types = ConceptTypeSourceList(self.context)
 | 
				
			||||||
| 
						 | 
					@ -171,6 +196,13 @@ class ConceptView(BaseView):
 | 
				
			||||||
    def getConceptTypeTokenForSearch(self, ct):
 | 
					    def getConceptTypeTokenForSearch(self, ct):
 | 
				
			||||||
        return ct is None and 'unknown' or zapi.getName(ct)
 | 
					        return ct is None and 'unknown' or zapi.getName(ct)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resourceTypes(self):
 | 
				
			||||||
 | 
					        return util.KeywordVocabulary(getResourceTypes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resourceTypesForSearch(self):
 | 
				
			||||||
 | 
					        return util.KeywordVocabulary(getResourceTypesForSearch())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def predicates(self):
 | 
					    def predicates(self):
 | 
				
			||||||
        preds = PredicateSourceList(self.context)
 | 
					        preds = PredicateSourceList(self.context)
 | 
				
			||||||
        terms = zapi.getMultiAdapter((preds, self.request), ITerms)
 | 
					        terms = zapi.getMultiAdapter((preds, self.request), ITerms)
 | 
				
			||||||
| 
						 | 
					@ -188,7 +220,6 @@ class ConceptRelationView(object):
 | 
				
			||||||
            self.context = relation.first
 | 
					            self.context = relation.first
 | 
				
			||||||
            self.other = relation.second
 | 
					            self.other = relation.second
 | 
				
			||||||
        self.predicate = relation.predicate
 | 
					        self.predicate = relation.predicate
 | 
				
			||||||
        self.conceptType = self.context.conceptType
 | 
					 | 
				
			||||||
        self.request = request
 | 
					        self.request = request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Lazy
 | 
					    @Lazy
 | 
				
			||||||
| 
						 | 
					@ -208,6 +239,10 @@ class ConceptRelationView(object):
 | 
				
			||||||
        return ':'.join((self.loopsRoot.getLoopsUri(self.context),
 | 
					        return ':'.join((self.loopsRoot.getLoopsUri(self.context),
 | 
				
			||||||
                         self.loopsRoot.getLoopsUri(self.predicate)))
 | 
					                         self.loopsRoot.getLoopsUri(self.predicate)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    def conceptType(self):
 | 
				
			||||||
 | 
					        return self.context.conceptType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Lazy
 | 
					    @Lazy
 | 
				
			||||||
    def typeTitle(self):
 | 
					    def typeTitle(self):
 | 
				
			||||||
        return self.conceptType.title
 | 
					        return self.conceptType.title
 | 
				
			||||||
| 
						 | 
					@ -224,3 +259,23 @@ class ConceptRelationView(object):
 | 
				
			||||||
    def predicateUrl(self):
 | 
					    def predicateUrl(self):
 | 
				
			||||||
        return zapi.absoluteURL(self.predicate, self.request)
 | 
					        return zapi.absoluteURL(self.predicate, self.request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConceptResourceRelationView(ConceptRelationView):
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    def conceptType(self):
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    def typeTitle(self):
 | 
				
			||||||
 | 
					        voc = util.KeywordVocabulary(getTargetTypes())
 | 
				
			||||||
 | 
					        token = '.'.join((self.context.__module__,
 | 
				
			||||||
 | 
					                          self.context.__class__.__name__))
 | 
				
			||||||
 | 
					        term = voc.getTermByToken(token)
 | 
				
			||||||
 | 
					        return term.title
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    def typeUrl(self):
 | 
				
			||||||
 | 
					        return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										87
									
								
								browser/concept_resources.pt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								browser/concept_resources.pt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,87 @@
 | 
				
			||||||
 | 
					<tal:tag condition="view/update" />
 | 
				
			||||||
 | 
					<html metal:use-macro="context/@@standard_macros/view"
 | 
				
			||||||
 | 
					      i18n:domain="loops">
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <div metal:fill-slot="body">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <h1 tal:content="context/title">Concept Title</h1><br />
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      <div   tal:define="items view/resources;
 | 
				
			||||||
 | 
					                         action string:remove;
 | 
				
			||||||
 | 
					                         qualifier string:parents;
 | 
				
			||||||
 | 
					                         summary string:Currently assigned resources;
 | 
				
			||||||
 | 
					                         legend string:Resources;
 | 
				
			||||||
 | 
					                         showPredicate string:yes;
 | 
				
			||||||
 | 
					                         buttonText string:Remove Resources;"
 | 
				
			||||||
 | 
					             style="float:left; padding-right:20px">
 | 
				
			||||||
 | 
					          <metal:parents use-macro="views/relation_macros/listing" />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div   tal:define="legend string:Create Resource;
 | 
				
			||||||
 | 
					                         buttonText string:Create Resource"
 | 
				
			||||||
 | 
					             style="padding-right:20px; clear:left">
 | 
				
			||||||
 | 
					        <metal:create use-macro="views/relation_macros/create">
 | 
				
			||||||
 | 
					          <select name="create.type" metal:fill-slot="types">
 | 
				
			||||||
 | 
					            <tal:types repeat="type view/resourceTypes">
 | 
				
			||||||
 | 
					              <option value="loops.resource.Document"
 | 
				
			||||||
 | 
					                      i18n:translate=""
 | 
				
			||||||
 | 
					                      tal:attributes="value type/token"
 | 
				
			||||||
 | 
					                      tal:content="type/title">Document</option>
 | 
				
			||||||
 | 
					            </tal:types>
 | 
				
			||||||
 | 
					          </select>
 | 
				
			||||||
 | 
					          <metal:control fill-slot="control">
 | 
				
			||||||
 | 
					            <input class="context" type="submit" name="form.button.submit"
 | 
				
			||||||
 | 
					                   value="Create Object"
 | 
				
			||||||
 | 
					                   i18n:attributes="value"
 | 
				
			||||||
 | 
					                   tal:attributes="value buttonText" />
 | 
				
			||||||
 | 
					            <input type="hidden" name="assignAs" value="resource" />
 | 
				
			||||||
 | 
					            and assign using Predicate
 | 
				
			||||||
 | 
					            <select metal:use-macro="views/relation_macros/predicates" />
 | 
				
			||||||
 | 
					          </metal:control>
 | 
				
			||||||
 | 
					        </metal:create>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      <div   tal:define="items view/search;
 | 
				
			||||||
 | 
					                         action string:assign;
 | 
				
			||||||
 | 
					                         qualifier nothing;
 | 
				
			||||||
 | 
					                         summary string:Assignment candidates;
 | 
				
			||||||
 | 
					                         legend string:Search;
 | 
				
			||||||
 | 
					                         showPredicate nothing;
 | 
				
			||||||
 | 
					                         buttonText string:Assign;"
 | 
				
			||||||
 | 
					             style="padding-right:20px">
 | 
				
			||||||
 | 
					        <metal:assign use-macro="views/relation_macros/listing">
 | 
				
			||||||
 | 
					          <metal:search fill-slot="topActions">
 | 
				
			||||||
 | 
					            <metal:block use-macro="views/relation_macros/search">
 | 
				
			||||||
 | 
					              <select name="searchType" metal:fill-slot="types">
 | 
				
			||||||
 | 
					                <option value="loops:resource:*"
 | 
				
			||||||
 | 
					                        tal:attributes="selected python:
 | 
				
			||||||
 | 
					                            searchType == 'loops:resource:*'">Any</option>
 | 
				
			||||||
 | 
					                <tal:types repeat="type view/resourceTypesForSearch">
 | 
				
			||||||
 | 
					                  <option value="loops:resource:Document"
 | 
				
			||||||
 | 
					                          i18n:translate=""
 | 
				
			||||||
 | 
					                          tal:attributes="value type/token;
 | 
				
			||||||
 | 
					                                    selected python: type.token == searchType"
 | 
				
			||||||
 | 
					                          tal:content="type/title">Topic</option>
 | 
				
			||||||
 | 
					                </tal:types>
 | 
				
			||||||
 | 
					              </select>
 | 
				
			||||||
 | 
					            </metal:block>
 | 
				
			||||||
 | 
					          </metal:search>
 | 
				
			||||||
 | 
					          <metal:special fill-slot="specialButtons">
 | 
				
			||||||
 | 
					            <input type="hidden" name="assignAs" value="resource" />
 | 
				
			||||||
 | 
					            Object(s) using Predicate
 | 
				
			||||||
 | 
					            <select name="predicate">
 | 
				
			||||||
 | 
					              <tal:types repeat="pred view/predicates">
 | 
				
			||||||
 | 
					                <option value=".loops/concepts/hasType"
 | 
				
			||||||
 | 
					                    i18n:translate=""
 | 
				
			||||||
 | 
					                    tal:attributes="value pred/token"
 | 
				
			||||||
 | 
					                    tal:content="pred/title">Predicate</option>
 | 
				
			||||||
 | 
					              </tal:types>
 | 
				
			||||||
 | 
					            </select>
 | 
				
			||||||
 | 
					          </metal:special>
 | 
				
			||||||
 | 
					        </metal:assign>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <pages
 | 
					  <pages
 | 
				
			||||||
      for="loops.interfaces.IConcept"
 | 
					      for="loops.interfaces.IConcept"
 | 
				
			||||||
      class=".concept.ConceptView"
 | 
					      class=".concept.ConceptConfigureView"
 | 
				
			||||||
      permission="zope.ManageContent">
 | 
					      permission="zope.ManageContent">
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    <page
 | 
					    <page
 | 
				
			||||||
| 
						 | 
					@ -114,6 +114,12 @@
 | 
				
			||||||
        menu="zmi_views" title="Related Concepts"
 | 
					        menu="zmi_views" title="Related Concepts"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    <page
 | 
				
			||||||
 | 
					        name="resources.html"
 | 
				
			||||||
 | 
					        template="concept_resources.pt"
 | 
				
			||||||
 | 
					        menu="zmi_views" title="Resources"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
  </pages>
 | 
					  </pages>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  <editform
 | 
					  <editform
 | 
				
			||||||
| 
						 | 
					@ -163,6 +169,21 @@
 | 
				
			||||||
      add="zope.ManageContent"
 | 
					      add="zope.ManageContent"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!-- resource in general -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <pages
 | 
				
			||||||
 | 
					      for="loops.interfaces.IResource"
 | 
				
			||||||
 | 
					      class=".resource.ResourceConfigureView"
 | 
				
			||||||
 | 
					      permission="zope.ManageContent">
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <page
 | 
				
			||||||
 | 
					        name="concepts.html"
 | 
				
			||||||
 | 
					        template="resource_concepts.pt"
 | 
				
			||||||
 | 
					        menu="zmi_views" title="Concepts"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  </pages>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
  <!-- document -->
 | 
					  <!-- document -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <!--<zope:view
 | 
					  <!--<zope:view
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,7 @@
 | 
				
			||||||
            <td>
 | 
					            <td>
 | 
				
			||||||
              <a tal:condition="item/typeTitle | nothing"
 | 
					              <a tal:condition="item/typeTitle | nothing"
 | 
				
			||||||
                 tal:content="item/typeTitle" href="#"
 | 
					                 tal:content="item/typeTitle" href="#"
 | 
				
			||||||
 | 
					                 tal:omit-tag="not:item/typeUrl"
 | 
				
			||||||
                 tal:attributes="href
 | 
					                 tal:attributes="href
 | 
				
			||||||
                    string:${item/typeUrl}/@@SelectedManagementView.html">
 | 
					                    string:${item/typeUrl}/@@SelectedManagementView.html">
 | 
				
			||||||
                Type
 | 
					                Type
 | 
				
			||||||
| 
						 | 
					@ -85,7 +86,7 @@
 | 
				
			||||||
        <input name="create.title" size="30"
 | 
					        <input name="create.title" size="30"
 | 
				
			||||||
               tal:attributes="value nothing" /> 
 | 
					               tal:attributes="value nothing" /> 
 | 
				
			||||||
        <span i18n:translate="">Type</span>
 | 
					        <span i18n:translate="">Type</span>
 | 
				
			||||||
        <select name="create.type">
 | 
					        <select name="create.type" metal:define-slot="types">
 | 
				
			||||||
          <tal:types repeat="type view/conceptTypes">
 | 
					          <tal:types repeat="type view/conceptTypes">
 | 
				
			||||||
            <option value=".loops/concepts/topic"
 | 
					            <option value=".loops/concepts/topic"
 | 
				
			||||||
                    i18n:translate=""
 | 
					                    i18n:translate=""
 | 
				
			||||||
| 
						 | 
					@ -96,6 +97,7 @@
 | 
				
			||||||
        </select>
 | 
					        </select>
 | 
				
			||||||
      </div><br />
 | 
					      </div><br />
 | 
				
			||||||
      <div class="formControls">
 | 
					      <div class="formControls">
 | 
				
			||||||
 | 
					        <metal:control define-slot="control">
 | 
				
			||||||
          <input class="context" type="submit" name="form.button.submit"
 | 
					          <input class="context" type="submit" name="form.button.submit"
 | 
				
			||||||
                 value="Create Object"
 | 
					                 value="Create Object"
 | 
				
			||||||
                 i18n:attributes="value"
 | 
					                 i18n:attributes="value"
 | 
				
			||||||
| 
						 | 
					@ -106,7 +108,7 @@
 | 
				
			||||||
            <option value="parent" i18n:translate="">Parent</option>
 | 
					            <option value="parent" i18n:translate="">Parent</option>
 | 
				
			||||||
          </select>
 | 
					          </select>
 | 
				
			||||||
          using Predicate
 | 
					          using Predicate
 | 
				
			||||||
        <select name="create.predicate">
 | 
					          <select name="create.predicate" metal:define-macro="predicates">
 | 
				
			||||||
            <tal:types repeat="pred view/predicates">
 | 
					            <tal:types repeat="pred view/predicates">
 | 
				
			||||||
              <option value=".loops/concepts/hasType"
 | 
					              <option value=".loops/concepts/hasType"
 | 
				
			||||||
                      i18n:translate=""
 | 
					                      i18n:translate=""
 | 
				
			||||||
| 
						 | 
					@ -114,6 +116,7 @@
 | 
				
			||||||
                      tal:content="pred/title">Predicate</option>
 | 
					                      tal:content="pred/title">Predicate</option>
 | 
				
			||||||
            </tal:types>
 | 
					            </tal:types>
 | 
				
			||||||
          </select>
 | 
					          </select>
 | 
				
			||||||
 | 
					        </metal:control>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
  </fieldset>
 | 
					  </fieldset>
 | 
				
			||||||
| 
						 | 
					@ -131,7 +134,7 @@
 | 
				
			||||||
        <input name="searchTerm"
 | 
					        <input name="searchTerm"
 | 
				
			||||||
               tal:attributes="value searchTerm" />
 | 
					               tal:attributes="value searchTerm" />
 | 
				
			||||||
        <span i18n:translate="">Type</span>
 | 
					        <span i18n:translate="">Type</span>
 | 
				
			||||||
        <select name="searchType">
 | 
					        <select name="searchType" metal:define-slot="types">
 | 
				
			||||||
          <option value="loops:concept:*"
 | 
					          <option value="loops:concept:*"
 | 
				
			||||||
                  tal:attributes="selected python:
 | 
					                  tal:attributes="selected python:
 | 
				
			||||||
                      searchType == 'loops:concept:*'">Any</option>
 | 
					                      searchType == 'loops:concept:*'">Any</option>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,12 +24,15 @@ $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zope.cachedescriptors.property import Lazy
 | 
					from zope.cachedescriptors.property import Lazy
 | 
				
			||||||
from zope.app import zapi
 | 
					from zope.app import zapi
 | 
				
			||||||
 | 
					from zope.app.catalog.interfaces import ICatalog
 | 
				
			||||||
from zope.app.dublincore.interfaces import ICMFDublinCore
 | 
					from zope.app.dublincore.interfaces import ICMFDublinCore
 | 
				
			||||||
from zope.proxy import removeAllProxies
 | 
					from zope.proxy import removeAllProxies
 | 
				
			||||||
from zope.security import canAccess, canWrite
 | 
					from zope.security import canAccess, canWrite
 | 
				
			||||||
from zope.security.proxy import removeSecurityProxy
 | 
					from zope.security.proxy import removeSecurityProxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from loops.interfaces import IDocument, IMediaAsset
 | 
					from loops.interfaces import IDocument, IMediaAsset
 | 
				
			||||||
 | 
					from loops.browser.common import BaseView
 | 
				
			||||||
 | 
					from loops.browser.concept import ConceptRelationView, ConceptConfigureView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
renderingFactories = {
 | 
					renderingFactories = {
 | 
				
			||||||
    'text/plain': 'zope.source.plaintext',
 | 
					    'text/plain': 'zope.source.plaintext',
 | 
				
			||||||
| 
						 | 
					@ -40,11 +43,69 @@ renderingFactories = {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DocumentView(object):
 | 
					class ResourceView(BaseView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, context, request):
 | 
					    def concepts(self):
 | 
				
			||||||
        self.context = context
 | 
					        for r in self.context.getConceptRelations():
 | 
				
			||||||
        self.request = request
 | 
					            yield ConceptRelationView(r, self.request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResourceConfigureView(ResourceView, ConceptConfigureView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update(self):
 | 
				
			||||||
 | 
					        request = self.request
 | 
				
			||||||
 | 
					        action = request.get('action')
 | 
				
			||||||
 | 
					        if action is None:
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        if action == 'create':
 | 
				
			||||||
 | 
					            self.createAndAssign()
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        tokens = request.get('tokens', [])
 | 
				
			||||||
 | 
					        for token in tokens:
 | 
				
			||||||
 | 
					            parts = token.split(':')
 | 
				
			||||||
 | 
					            token = parts[0]
 | 
				
			||||||
 | 
					            if len(parts) > 1:
 | 
				
			||||||
 | 
					                relToken = parts[1]
 | 
				
			||||||
 | 
					            concept = self.loopsRoot.loopsTraverse(token)
 | 
				
			||||||
 | 
					            if action == 'assign':
 | 
				
			||||||
 | 
					                predicate = request.get('predicate') or None
 | 
				
			||||||
 | 
					                if predicate:
 | 
				
			||||||
 | 
					                    predicate = removeSecurityProxy(
 | 
				
			||||||
 | 
					                                    self.loopsRoot.loopsTraverse(predicate))
 | 
				
			||||||
 | 
					                self.context.assignConcept(removeSecurityProxy(concept), predicate)
 | 
				
			||||||
 | 
					            elif action == 'remove':
 | 
				
			||||||
 | 
					                predicate = self.loopsRoot.loopsTraverse(relToken)
 | 
				
			||||||
 | 
					                self.context.deassignConcept(concept, [predicate])
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def search(self):
 | 
				
			||||||
 | 
					        request = self.request
 | 
				
			||||||
 | 
					        if request.get('action') != 'search':
 | 
				
			||||||
 | 
					            return []
 | 
				
			||||||
 | 
					        searchTerm = request.get('searchTerm', None)
 | 
				
			||||||
 | 
					        searchType = request.get('searchType', None)
 | 
				
			||||||
 | 
					        result = []
 | 
				
			||||||
 | 
					        if searchTerm or searchType != 'none':
 | 
				
			||||||
 | 
					            criteria = {}
 | 
				
			||||||
 | 
					            if searchTerm:
 | 
				
			||||||
 | 
					                criteria['loops_title'] = searchTerm
 | 
				
			||||||
 | 
					            if searchType:
 | 
				
			||||||
 | 
					                if searchType.endswith('*'):
 | 
				
			||||||
 | 
					                    start = searchType[:-1]
 | 
				
			||||||
 | 
					                    end = start + '\x7f'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    start = end = searchType
 | 
				
			||||||
 | 
					                criteria['loops_type'] = (start, end)
 | 
				
			||||||
 | 
					            cat = zapi.getUtility(ICatalog)
 | 
				
			||||||
 | 
					            result = cat.searchResults(**criteria)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            result = self.loopsRoot.getConceptManager().values()
 | 
				
			||||||
 | 
					        if searchType == 'none':
 | 
				
			||||||
 | 
					            result = [r for r in result if r.conceptType is None]
 | 
				
			||||||
 | 
					        return self.viewIterator(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DocumentView(ResourceView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def render(self):
 | 
					    def render(self):
 | 
				
			||||||
        """ Return the rendered content (data) of the context object.
 | 
					        """ Return the rendered content (data) of the context object.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								browser/resource_concepts.pt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								browser/resource_concepts.pt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					<tal:tag condition="view/update" />
 | 
				
			||||||
 | 
					<html metal:use-macro="context/@@standard_macros/view"
 | 
				
			||||||
 | 
					      i18n:domain="loops">
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <div metal:fill-slot="body">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <h1 tal:content="context/title">Concept Title</h1><br />
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      <div   tal:define="items view/concepts;
 | 
				
			||||||
 | 
					                         action string:remove;
 | 
				
			||||||
 | 
					                         qualifier string:parents;
 | 
				
			||||||
 | 
					                         summary string:Currently assigned objects;
 | 
				
			||||||
 | 
					                         legend string:Parent Concepts;
 | 
				
			||||||
 | 
					                         showPredicate string:yes;
 | 
				
			||||||
 | 
					                         buttonText string:Remove Parents;"
 | 
				
			||||||
 | 
					             style="padding-right:20px">
 | 
				
			||||||
 | 
					          <metal:parents use-macro="views/relation_macros/listing" />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div   tal:define="items view/search;
 | 
				
			||||||
 | 
					                         action string:assign;
 | 
				
			||||||
 | 
					                         qualifier nothing;
 | 
				
			||||||
 | 
					                         summary string:Assignment candidates;
 | 
				
			||||||
 | 
					                         legend string:Search;
 | 
				
			||||||
 | 
					                         showPredicate nothing;
 | 
				
			||||||
 | 
					                         buttonText string:Assign;"
 | 
				
			||||||
 | 
					             style="padding-right:20px">
 | 
				
			||||||
 | 
					        <metal:assign use-macro="views/relation_macros/listing">
 | 
				
			||||||
 | 
					          <metal:search fill-slot="topActions">
 | 
				
			||||||
 | 
					            <metal:block use-macro="views/relation_macros/search" />
 | 
				
			||||||
 | 
					          </metal:search>
 | 
				
			||||||
 | 
					          <metal:special fill-slot="specialButtons">
 | 
				
			||||||
 | 
					            Object(s) using Predicate
 | 
				
			||||||
 | 
					            <select name="predicate">
 | 
				
			||||||
 | 
					              <tal:types repeat="pred view/predicates">
 | 
				
			||||||
 | 
					                <option value=".loops/concepts/hasType"
 | 
				
			||||||
 | 
					                    i18n:translate=""
 | 
				
			||||||
 | 
					                    tal:attributes="value pred/token"
 | 
				
			||||||
 | 
					                    tal:content="pred/title">Predicate</option>
 | 
				
			||||||
 | 
					              </tal:types>
 | 
				
			||||||
 | 
					            </select>
 | 
				
			||||||
 | 
					          </metal:special>
 | 
				
			||||||
 | 
					        </metal:assign>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					@ -173,7 +173,7 @@ class Concept(Contained, Persistent):
 | 
				
			||||||
        if predicate is None:
 | 
					        if predicate is None:
 | 
				
			||||||
            predicate = self.getConceptManager().getDefaultPredicate()
 | 
					            predicate = self.getConceptManager().getDefaultPredicate()
 | 
				
			||||||
        registry = zapi.getUtility(IRelationRegistry)
 | 
					        registry = zapi.getUtility(IRelationRegistry)
 | 
				
			||||||
        registry.register(ResourceRelation(self, resource, predicate))
 | 
					        registry.register(ResourceRelation(self, resource))
 | 
				
			||||||
        # TODO (?): avoid duplicates
 | 
					        # TODO (?): avoid duplicates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def deassignResource(self, resource, predicates=None):
 | 
					    def deassignResource(self, resource, predicates=None):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,10 +205,33 @@ class IResource(ILoopsObject, IPotentialTarget):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getClients(relationships=None):
 | 
					    def getClients(relationships=None):
 | 
				
			||||||
        """ Return a sequence of objects that are clients of the resource,
 | 
					        """ Return a sequence of objects that the resource is the target of.
 | 
				
			||||||
            i.e. that have some relation with it.
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getConcepts(predicates=None):
 | 
				
			||||||
 | 
					        """ Return a tuple of concepts related to self as parent concepts,
 | 
				
			||||||
 | 
					            optionally restricted to the predicates given.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getConceptRelations(predicates=None, concepts=None):
 | 
				
			||||||
 | 
					        """ Return a sequence of relations to concepts assigned to self
 | 
				
			||||||
 | 
					            as parent concepts, optionally restricted to the predicates given
 | 
				
			||||||
 | 
					            or to a certain concept.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def assignConcept(concept, predicate):
 | 
				
			||||||
 | 
					        """ Assign an existing concept to self using the predicate given.
 | 
				
			||||||
 | 
					            The assigned concept will be a parent concept of self.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            The predicate defaults to the concept manager's default predicate.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deassignConcept(concept, predicates=None):
 | 
				
			||||||
 | 
					        """ Remove the concept relations to the concept given from self,
 | 
				
			||||||
 | 
					            optionally restricting them to the predicates given.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IDocumentSchema(IResourceSchema):
 | 
					class IDocumentSchema(IResourceSchema):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										41
									
								
								resource.py
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								resource.py
									
										
									
									
									
								
							| 
						 | 
					@ -27,6 +27,7 @@ from zope.app.container.btree import BTreeContainer
 | 
				
			||||||
from zope.app.container.contained import Contained
 | 
					from zope.app.container.contained import Contained
 | 
				
			||||||
from zope.app.file.image import Image as BaseMediaAsset
 | 
					from zope.app.file.image import Image as BaseMediaAsset
 | 
				
			||||||
from zope.component import adapts
 | 
					from zope.component import adapts
 | 
				
			||||||
 | 
					from zope.i18nmessageid import MessageFactory
 | 
				
			||||||
from zope.interface import implements
 | 
					from zope.interface import implements
 | 
				
			||||||
from persistent import Persistent
 | 
					from persistent import Persistent
 | 
				
			||||||
from cStringIO import StringIO
 | 
					from cStringIO import StringIO
 | 
				
			||||||
| 
						 | 
					@ -39,12 +40,18 @@ from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView
 | 
				
			||||||
from interfaces import IResourceManager, IResourceManagerContained
 | 
					from interfaces import IResourceManager, IResourceManagerContained
 | 
				
			||||||
from interfaces import ILoopsContained
 | 
					from interfaces import ILoopsContained
 | 
				
			||||||
from interfaces import IIndexAttributes
 | 
					from interfaces import IIndexAttributes
 | 
				
			||||||
 | 
					from concept import ResourceRelation
 | 
				
			||||||
 | 
					from view import TargetRelation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_ = MessageFactory('loops')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Resource(Contained, Persistent):
 | 
					class Resource(Contained, Persistent):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    implements(IResource, IResourceManagerContained, IRelatable)
 | 
					    implements(IResource, IResourceManagerContained, IRelatable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _size = _width = _height = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _title = u''
 | 
					    _title = u''
 | 
				
			||||||
    def getTitle(self): return self._title
 | 
					    def getTitle(self): return self._title
 | 
				
			||||||
    def setTitle(self, title): self._title = title
 | 
					    def setTitle(self, title): self._title = title
 | 
				
			||||||
| 
						 | 
					@ -57,17 +64,34 @@ class Resource(Contained, Persistent):
 | 
				
			||||||
    def getContentType(self): return self._contentType
 | 
					    def getContentType(self): return self._contentType
 | 
				
			||||||
    contentType = property(getContentType, setContentType)
 | 
					    contentType = property(getContentType, setContentType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, title=u''):
 | 
				
			||||||
 | 
					        self.title = title
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getLoopsRoot(self):
 | 
					    def getLoopsRoot(self):
 | 
				
			||||||
        return zapi.getParent(self).getLoopsRoot()
 | 
					        return zapi.getParent(self).getLoopsRoot()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getClients(self, relationships=None):
 | 
					    def getClients(self, relationships=None):
 | 
				
			||||||
 | 
					        if relationships is None:
 | 
				
			||||||
 | 
					            relationships = [TargetRelation]
 | 
				
			||||||
        rels = getRelations(second=self, relationships=relationships)
 | 
					        rels = getRelations(second=self, relationships=relationships)
 | 
				
			||||||
        return [r.first for r in rels]
 | 
					        return [r.first for r in rels]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, title=u''):
 | 
					    # concept relations
 | 
				
			||||||
        self.title = title
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _size = _width = _height = 0
 | 
					    def getConceptRelations (self, predicates=None, concept=None):
 | 
				
			||||||
 | 
					        predicates = predicates is None and ['*'] or predicates
 | 
				
			||||||
 | 
					        relationships = [ResourceRelation(None, self, p) for p in predicates]
 | 
				
			||||||
 | 
					        # TODO: sort...
 | 
				
			||||||
 | 
					        return getRelations(first=concept, second=self, relationships=relationships)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def getConcepts(self, predicates=None):
 | 
				
			||||||
 | 
					        return [r.first for r in self.getConceptRelations(predicates)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def assignConcept(self, concept, predicate=None):
 | 
				
			||||||
 | 
					        concept.assignResource(self, predicate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deassignConcept(self, concept, predicates=None):
 | 
				
			||||||
 | 
					        concept.deassignResource(self, predicates)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Document(Resource):
 | 
					class Document(Resource):
 | 
				
			||||||
| 
						 | 
					@ -138,3 +162,14 @@ class IndexAttributes(object):
 | 
				
			||||||
        context = self.context
 | 
					        context = self.context
 | 
				
			||||||
        return ':'.join(('loops:resource', context.__class__.__name__))
 | 
					        return ':'.join(('loops:resource', context.__class__.__name__))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def getResourceTypes():
 | 
				
			||||||
 | 
					    return (('loops.resource.Document', _(u'Document')),
 | 
				
			||||||
 | 
					            ('loops.resource.MediaAsset', _(u'Media Asset')),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def getResourceTypesForSearch():
 | 
				
			||||||
 | 
					    return (('loops:resource:Document', _(u'Document')),
 | 
				
			||||||
 | 
					            ('loops:resource:MediaAsset', _(u'Media Asset')),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue