reorganize resource stuff - dynamic typing, first type is 'file'
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1289 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
		
							parent
							
								
									89ae9aeab0
								
							
						
					
					
						commit
						e860cf5a07
					
				
					 16 changed files with 349 additions and 298 deletions
				
			
		
							
								
								
									
										46
									
								
								README.txt
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								README.txt
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -17,12 +17,12 @@ with lower-level aspects like type or state management.
 | 
			
		|||
 | 
			
		||||
  >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
 | 
			
		||||
  >>> site = placefulSetUp(True)
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  >>> from zope.app import zapi
 | 
			
		||||
  >>> from zope.app.tests import ztapi
 | 
			
		||||
  >>> from zope.interface import Interface
 | 
			
		||||
  >>> from zope.publisher.browser import TestRequest
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Concepts and Relations
 | 
			
		||||
======================
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ also need a default predicate concept; the default name for this is
 | 
			
		|||
 | 
			
		||||
Now we can assign the concept c2 as a child to c1 (using the standard
 | 
			
		||||
ConceptRelation):
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
  >>> cc1.assignChild(cc2)
 | 
			
		||||
 | 
			
		||||
We can now ask our concepts for their related child and parent concepts:
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +163,7 @@ The token attribute provided with the items returned by the children() and
 | 
			
		|||
parents() methods identifies identifies not only the item itself but
 | 
			
		||||
also the relationship to the context object using a combination
 | 
			
		||||
of URIs to item and the predicate of the relationship:
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  >>> [c.token for c in children]
 | 
			
		||||
  ['.loops/concepts/cc2:.loops/concepts/standard']
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -207,11 +207,11 @@ types and predicates.
 | 
			
		|||
  >>> from zope.schema.interfaces import IIterableSource
 | 
			
		||||
  >>> ztapi.provideAdapter(IIterableSource, ITerms, LoopsTerms,
 | 
			
		||||
  ...                      with=(IBrowserRequest,))
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
  >>> sorted((t.title, t.token) for t in view.conceptTypes())
 | 
			
		||||
  [(u'Topic', '.loops/concepts/topic'), (u'Type', '.loops/concepts/type'),
 | 
			
		||||
      (u'Unknown Type', '.loops/concepts/unknown')]
 | 
			
		||||
          
 | 
			
		||||
 | 
			
		||||
  >>> sorted((t.title, t.token) for t in view.predicates())
 | 
			
		||||
  [(u'subconcept', '.loops/concepts/standard')]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +222,7 @@ Index attributes adapter
 | 
			
		|||
  >>> idx = IndexAttributes(cc2)
 | 
			
		||||
  >>> idx.text()
 | 
			
		||||
  u'cc2 Zope 3'
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  >>> idx.title()
 | 
			
		||||
  u'cc2 Zope 3'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -230,16 +230,16 @@ Index attributes adapter
 | 
			
		|||
Resources and what they have to do with Concepts
 | 
			
		||||
================================================
 | 
			
		||||
 | 
			
		||||
  >>> from loops.interfaces import IDocument, IMediaAsset
 | 
			
		||||
  >>> from loops.interfaces import IResource, IDocument, IMediaAsset
 | 
			
		||||
 | 
			
		||||
We first need a resource manager:
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
  >>> from loops.resource import ResourceManager
 | 
			
		||||
  >>> loopsRoot['resources'] = ResourceManager()
 | 
			
		||||
  >>> resources = loopsRoot['resources']
 | 
			
		||||
 | 
			
		||||
A common type of resource is a document:
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
  >>> from loops.interfaces import IDocument
 | 
			
		||||
  >>> from loops.resource import Document
 | 
			
		||||
  >>> doc1 = Document(u'Zope Info')
 | 
			
		||||
| 
						 | 
				
			
			@ -247,9 +247,9 @@ A common type of resource is a document:
 | 
			
		|||
  >>> doc1.title
 | 
			
		||||
  u'Zope Info'
 | 
			
		||||
  >>> doc1.data
 | 
			
		||||
  u''
 | 
			
		||||
  >>> doc1.contentType
 | 
			
		||||
  ''
 | 
			
		||||
  >>> doc1.contentType
 | 
			
		||||
  u''
 | 
			
		||||
 | 
			
		||||
Another one is a media asset:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +258,7 @@ Another one is a media asset:
 | 
			
		|||
  >>> img = MediaAsset(u'A png Image')
 | 
			
		||||
 | 
			
		||||
For testing we use some simple files from the tests directory:
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
  >>> from loops import tests
 | 
			
		||||
  >>> import os
 | 
			
		||||
  >>> path = os.path.join(*tests.__path__)
 | 
			
		||||
| 
						 | 
				
			
			@ -312,7 +312,7 @@ These relations may also be managed starting from a resource using
 | 
			
		|||
the resource configuration view:
 | 
			
		||||
 | 
			
		||||
  >>> from loops.browser.resource import ResourceConfigureView
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
Index attributes adapter
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +320,7 @@ Index attributes adapter
 | 
			
		|||
  >>> idx = IndexAttributes(doc1)
 | 
			
		||||
  >>> idx.text()
 | 
			
		||||
  u'doc1 Zope Info'
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  >>> idx.title()
 | 
			
		||||
  u'doc1 Zope Info'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -340,7 +340,7 @@ the views or nodes, however, present informations coming from the concepts
 | 
			
		|||
or resources they are related to.
 | 
			
		||||
 | 
			
		||||
We first need a view manager:
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
  >>> from loops.view import ViewManager, Node
 | 
			
		||||
  >>> from zope.security.checker import NamesChecker, defineChecker
 | 
			
		||||
  >>> nodeChecker = NamesChecker(('body',))
 | 
			
		||||
| 
						 | 
				
			
			@ -351,7 +351,7 @@ We first need a view manager:
 | 
			
		|||
 | 
			
		||||
The view space is typically built up with nodes; a node may be a top-level
 | 
			
		||||
menu that may contain other nodes as menu or content items:
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
  >>> m1 = Node(u'Menu')
 | 
			
		||||
  >>> views['m1'] = m1
 | 
			
		||||
  >>> m11 = Node(u'Zope')
 | 
			
		||||
| 
						 | 
				
			
			@ -426,7 +426,7 @@ out - this is usually done through ZCML.)
 | 
			
		|||
  >>> from cybertools.relation.interfaces import IRelationInvalidatedEvent
 | 
			
		||||
  >>> ztapi.subscribe([ITargetRelation, IRelationInvalidatedEvent], None,
 | 
			
		||||
  ...                 removeTargetRelation)
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  >>> m111.target = cc1
 | 
			
		||||
  >>> m111.target is cc1
 | 
			
		||||
  True
 | 
			
		||||
| 
						 | 
				
			
			@ -487,10 +487,10 @@ accessing a target via a node view it is usually wrapped in a corresponding
 | 
			
		|||
view; these views we have to provide as multi-adapters:
 | 
			
		||||
 | 
			
		||||
  >>> from loops.browser.node import ConfigureView
 | 
			
		||||
  >>> from loops.browser.resource import DocumentView, MediaAssetView
 | 
			
		||||
  >>> from loops.browser.resource import DocumentView, ResourceView
 | 
			
		||||
  >>> ztapi.provideAdapter(IDocument, Interface, DocumentView,
 | 
			
		||||
  ...                      with=(IBrowserRequest,))
 | 
			
		||||
  >>> ztapi.provideAdapter(IMediaAsset, Interface, MediaAssetView,
 | 
			
		||||
  >>> ztapi.provideAdapter(IResource, Interface, ResourceView,
 | 
			
		||||
  ...                      with=(IBrowserRequest,))
 | 
			
		||||
 | 
			
		||||
  >>> form = {'action': 'create', 'create.title': 'New Resource',
 | 
			
		||||
| 
						 | 
				
			
			@ -592,10 +592,10 @@ Let's add some more nodes and reorder them:
 | 
			
		|||
  >>> m11['m114'] = m114
 | 
			
		||||
  >>> m11.keys()
 | 
			
		||||
  ['m111', 'm112', 'm113', 'm114']
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
A special management view provides methods for moving objects down, up,
 | 
			
		||||
to the bottom, and to the top.
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
  >>> from cybertools.container.ordered import OrderedContainerView
 | 
			
		||||
  >>> view = OrderedContainerView(m11, TestRequest())
 | 
			
		||||
  >>> view.move_bottom(('m113',))
 | 
			
		||||
| 
						 | 
				
			
			@ -641,7 +641,7 @@ instance to another.
 | 
			
		|||
  >>> exporter.dumpData()
 | 
			
		||||
 | 
			
		||||
Load them again from the exported file:
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  >>> importer = NodesImporter(views)
 | 
			
		||||
  >>> importer.filename = dumpname
 | 
			
		||||
  >>> imported = importer.getData()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ class BaseView(object):
 | 
			
		|||
    @Lazy
 | 
			
		||||
    def loopsRoot(self):
 | 
			
		||||
        return self.context.getLoopsRoot()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @Lazy
 | 
			
		||||
    def url(self):
 | 
			
		||||
        return zapi.absoluteURL(self.context, self.request)
 | 
			
		||||
| 
						 | 
				
			
			@ -199,9 +199,10 @@ class LoopsTerms(object):
 | 
			
		|||
    @Lazy
 | 
			
		||||
    def loopsRoot(self):
 | 
			
		||||
        return self.context.getLoopsRoot()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def getTerm(self, value):
 | 
			
		||||
        #return BaseView(value, self.request)
 | 
			
		||||
        #if value is None:
 | 
			
		||||
        #    return SimpleTerm(None, '', u'not assigned')
 | 
			
		||||
        title = value.title or zapi.getName(value)
 | 
			
		||||
        token = self.loopsRoot.getLoopsUri(value)
 | 
			
		||||
        return SimpleTerm(value, token, title)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,14 +66,14 @@ class ConceptEditForm(EditForm):
 | 
			
		|||
class ConceptView(BaseView):
 | 
			
		||||
 | 
			
		||||
    template = NamedTemplate('loops.concept_macros')
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @Lazy
 | 
			
		||||
    def macro(self):
 | 
			
		||||
        return self.template.macros['conceptdata']
 | 
			
		||||
 | 
			
		||||
    def fieldData(self):
 | 
			
		||||
        ti = IType(self.context).typeInterface
 | 
			
		||||
        if not ti: return 
 | 
			
		||||
        if not ti: return
 | 
			
		||||
        adapter = ti(self.context)
 | 
			
		||||
        for n, f in schema.getFieldsInOrder(ti):
 | 
			
		||||
            value = getattr(adapter, n, '')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -233,6 +233,21 @@
 | 
			
		|||
 | 
			
		||||
  <!-- resource in general -->
 | 
			
		||||
 | 
			
		||||
  <page
 | 
			
		||||
      for="loops.interfaces.IResource"
 | 
			
		||||
      name="index.html"
 | 
			
		||||
      permission="zope.View"
 | 
			
		||||
      class=".resource.ResourceView"
 | 
			
		||||
      attribute="show" />
 | 
			
		||||
 | 
			
		||||
  <zope:adapter
 | 
			
		||||
      for="loops.interfaces.IResource
 | 
			
		||||
           zope.publisher.interfaces.browser.IBrowserRequest"
 | 
			
		||||
      provides="zope.interface.Interface"
 | 
			
		||||
      factory="loops.browser.resource.ResourceView"
 | 
			
		||||
      permission="zope.View"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <pages
 | 
			
		||||
      for="loops.interfaces.IResource"
 | 
			
		||||
      class=".resource.ResourceConfigureView"
 | 
			
		||||
| 
						 | 
				
			
			@ -246,12 +261,19 @@
 | 
			
		|||
 | 
			
		||||
  </pages>
 | 
			
		||||
 | 
			
		||||
  <zope:adapter
 | 
			
		||||
      for="loops.interfaces.IResource
 | 
			
		||||
           zope.publisher.interfaces.browser.IBrowserRequest"
 | 
			
		||||
      provides="zope.interface.Interface"
 | 
			
		||||
      factory="loops.browser.resource.ResourceView"
 | 
			
		||||
      permission="zope.View"
 | 
			
		||||
  <page
 | 
			
		||||
      name="edit.html"
 | 
			
		||||
      for="loops.interfaces.IResource"
 | 
			
		||||
      class="loops.browser.resource.ResourceEditForm"
 | 
			
		||||
      permission="zope.ManageContent"
 | 
			
		||||
      menu="zmi_views" title="Edit"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <!-- suppress the upload menu item: -->
 | 
			
		||||
  <menuItem
 | 
			
		||||
      for="loops.interfaces.IResource"
 | 
			
		||||
      menu="zmi_views" action="upload.html" title="Upload"
 | 
			
		||||
      filter="nothing"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <!-- document -->
 | 
			
		||||
| 
						 | 
				
			
			@ -263,33 +285,6 @@
 | 
			
		|||
      class=".resource.DocumentView"
 | 
			
		||||
      attribute="show" />
 | 
			
		||||
 | 
			
		||||
  <addform
 | 
			
		||||
      label="Add Document"
 | 
			
		||||
      name="AddLoopsDocument.html"
 | 
			
		||||
      schema="loops.interfaces.IDocumentSchema"
 | 
			
		||||
      fields="title data contentType"
 | 
			
		||||
      content_factory="loops.resource.Document"
 | 
			
		||||
      template="add.pt"
 | 
			
		||||
      permission="zope.ManageContent" />
 | 
			
		||||
 | 
			
		||||
  <addMenuItem
 | 
			
		||||
      class="loops.resource.Document"
 | 
			
		||||
      title="Document"
 | 
			
		||||
      description="A document is an editable information unit"
 | 
			
		||||
      permission="zope.ManageContent"
 | 
			
		||||
      view="AddLoopsDocument.html"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
<!--  <editform
 | 
			
		||||
      label="Edit Document"
 | 
			
		||||
      name="edit.html"
 | 
			
		||||
      schema="loops.interfaces.IDocumentSchema"
 | 
			
		||||
      fields="title data contentType"
 | 
			
		||||
      for="loops.interfaces.IDocument"
 | 
			
		||||
      template="edit.pt"
 | 
			
		||||
      permission="zope.ManageContent"
 | 
			
		||||
      menu="zmi_views" title="Edit" />-->
 | 
			
		||||
 | 
			
		||||
  <page
 | 
			
		||||
      name="edit.html"
 | 
			
		||||
      for="loops.interfaces.IDocument"
 | 
			
		||||
| 
						 | 
				
			
			@ -322,25 +317,7 @@
 | 
			
		|||
 | 
			
		||||
  <!-- media asset -->
 | 
			
		||||
 | 
			
		||||
  <addform
 | 
			
		||||
      label="Add Media Asset"
 | 
			
		||||
      name="AddLoopsMediaAsset.html"
 | 
			
		||||
      schema="loops.interfaces.IMediaAssetSchema"
 | 
			
		||||
      fields="title data contentType"
 | 
			
		||||
      content_factory="loops.resource.MediaAsset"
 | 
			
		||||
      template="add.pt"
 | 
			
		||||
      permission="zope.ManageContent"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <addMenuItem
 | 
			
		||||
      class="loops.resource.MediaAsset"
 | 
			
		||||
      title="Media Asset"
 | 
			
		||||
      description="A media asset is a binary file, image, video or audio file"
 | 
			
		||||
      permission="zope.ManageContent"
 | 
			
		||||
      view="AddLoopsMediaAsset.html"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <editform
 | 
			
		||||
  <!--<editform
 | 
			
		||||
      label="Edit Media Asset"
 | 
			
		||||
      name="edit.html"
 | 
			
		||||
      schema="loops.interfaces.IMediaAssetSchema"
 | 
			
		||||
| 
						 | 
				
			
			@ -349,7 +326,7 @@
 | 
			
		|||
      template="edit.pt"
 | 
			
		||||
      permission="zope.ManageContent"
 | 
			
		||||
      menu="zmi_views" title="Edit Media Asset"
 | 
			
		||||
      />
 | 
			
		||||
      />-->
 | 
			
		||||
 | 
			
		||||
  <!--<page
 | 
			
		||||
      name="edit.html"
 | 
			
		||||
| 
						 | 
				
			
			@ -359,21 +336,6 @@
 | 
			
		|||
      menu="zmi_views" title="Edit"
 | 
			
		||||
      />-->
 | 
			
		||||
 | 
			
		||||
  <!-- suppress the upload menu item: -->
 | 
			
		||||
  <menuItem
 | 
			
		||||
      for="loops.interfaces.IMediaAsset"
 | 
			
		||||
      menu="zmi_views" action="upload.html" title="Upload"
 | 
			
		||||
      filter="nothing"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <zope:adapter
 | 
			
		||||
      for="loops.interfaces.IMediaAsset
 | 
			
		||||
           zope.publisher.interfaces.browser.IBrowserRequest"
 | 
			
		||||
      provides="zope.interface.Interface"
 | 
			
		||||
      factory="loops.browser.resource.MediaAssetView"
 | 
			
		||||
      permission="zope.View"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
  <!-- view manager -->
 | 
			
		||||
 | 
			
		||||
  <addform
 | 
			
		||||
| 
						 | 
				
			
			@ -584,6 +546,10 @@
 | 
			
		|||
           for="loops.type.TypeInterfaceSourceList
 | 
			
		||||
                zope.publisher.interfaces.browser.IBrowserRequest" />
 | 
			
		||||
 | 
			
		||||
  <zope:adapter factory="loops.browser.common.LoopsTerms"
 | 
			
		||||
           for="loops.resource.ResourceTypeSourceList
 | 
			
		||||
                zope.publisher.interfaces.browser.IBrowserRequest" />
 | 
			
		||||
 | 
			
		||||
  <zope:view factory="loops.view.NodeTraverser"
 | 
			
		||||
        for="loops.interfaces.INode"
 | 
			
		||||
        type="zope.publisher.interfaces.browser.IBrowserRequest"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -204,7 +204,7 @@ class NodeView(BaseView):
 | 
			
		|||
 | 
			
		||||
    def active(self, item):
 | 
			
		||||
        return item.context == self.context or item.context in self.parents
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
    def targetDefaultView(self):
 | 
			
		||||
        target = self.request.annotations.get('loops.view', {}).get('target')
 | 
			
		||||
        if target is None:
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +250,7 @@ class ConfigureView(NodeView):
 | 
			
		|||
        obj = self.targetObject
 | 
			
		||||
        if obj is not None:
 | 
			
		||||
            return zapi.getMultiAdapter((obj, self.request))
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def update(self):
 | 
			
		||||
        request = self.request
 | 
			
		||||
        action = request.get('action')
 | 
			
		||||
| 
						 | 
				
			
			@ -291,6 +291,8 @@ class ConfigureView(NodeView):
 | 
			
		|||
        target.title = form.get('create.title', u'')
 | 
			
		||||
        if IConcept.providedBy(target):
 | 
			
		||||
            target.conceptType = type.typeProvider
 | 
			
		||||
        elif IResource.providedBy(target):
 | 
			
		||||
            target.resourceType = type.typeProvider
 | 
			
		||||
        notify(ObjectCreatedEvent(target))
 | 
			
		||||
        notify(ObjectModifiedEvent(target))
 | 
			
		||||
        self.context.target = target
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,8 +33,8 @@ from zope.proxy import removeAllProxies
 | 
			
		|||
from zope.security import canAccess, canWrite
 | 
			
		||||
from zope.security.proxy import removeSecurityProxy
 | 
			
		||||
 | 
			
		||||
from loops.interfaces import IDocument, IMediaAsset
 | 
			
		||||
from loops.interfaces import IFileSystemResource, IControlledResource
 | 
			
		||||
from cybertools.typology.interfaces import IType
 | 
			
		||||
from loops.interfaces import IBaseResource, IDocument, IMediaAsset
 | 
			
		||||
from loops.browser.common import EditForm, BaseView
 | 
			
		||||
from loops.browser.concept import ConceptRelationView, ConceptConfigureView
 | 
			
		||||
from loops.browser.node import NodeView
 | 
			
		||||
| 
						 | 
				
			
			@ -48,12 +48,27 @@ renderingFactories = {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourceEditForm(EditForm):
 | 
			
		||||
 | 
			
		||||
    @Lazy
 | 
			
		||||
    def typeInterface(self):
 | 
			
		||||
        return IType(self.context).typeInterface
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def form_fields(self):
 | 
			
		||||
        fields = FormFields(IBaseResource)
 | 
			
		||||
        typeInterface = self.typeInterface
 | 
			
		||||
        if typeInterface is not None:
 | 
			
		||||
            fields = FormFields(fields, typeInterface)
 | 
			
		||||
        return fields
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DocumentEditForm(EditForm):
 | 
			
		||||
    #form_fields = FormFields(IDocument, IFileSystemResource, IControlledResource)
 | 
			
		||||
    form_fields = FormFields(IDocument)
 | 
			
		||||
    for f in form_fields:
 | 
			
		||||
        f.render_context |= DISPLAY_UNWRITEABLE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MediaAssetEditForm(EditForm):
 | 
			
		||||
    form_fields = FormFields(IMediaAsset)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +77,20 @@ class ResourceView(BaseView):
 | 
			
		|||
 | 
			
		||||
    template = ViewPageTemplateFile('resource_macros.pt')
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def macro(self):
 | 
			
		||||
        if 'image/' in self.context.contentType:
 | 
			
		||||
            return self.template.macros['image']
 | 
			
		||||
        else:
 | 
			
		||||
            return self.template.macros['download']
 | 
			
		||||
 | 
			
		||||
    def show(self):
 | 
			
		||||
        data = self.context.data
 | 
			
		||||
        response = self.request.response
 | 
			
		||||
        response.setHeader('Content-Type', self.context.contentType)
 | 
			
		||||
        response.setHeader('Content-Length', len(data))
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def concepts(self):
 | 
			
		||||
        for r in self.context.getConceptRelations():
 | 
			
		||||
            yield ConceptRelationView(r, self.request)
 | 
			
		||||
| 
						 | 
				
			
			@ -130,8 +159,10 @@ class ResourceConfigureView(ResourceView, ConceptConfigureView):
 | 
			
		|||
 | 
			
		||||
class DocumentView(ResourceView):
 | 
			
		||||
 | 
			
		||||
    macro = ResourceView.template.macros['render']
 | 
			
		||||
    
 | 
			
		||||
    @property
 | 
			
		||||
    def macro(self):
 | 
			
		||||
        return ResourceView.template.macros['render']
 | 
			
		||||
 | 
			
		||||
    def render(self):
 | 
			
		||||
        """ Return the rendered content (data) of the context object.
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -143,19 +174,3 @@ class DocumentView(ResourceView):
 | 
			
		|||
        view = zapi.getMultiAdapter((removeAllProxies(source), self.request))
 | 
			
		||||
        return view.render()
 | 
			
		||||
 | 
			
		||||
    def show(self):
 | 
			
		||||
        data = self.context.data
 | 
			
		||||
        response = self.request.response
 | 
			
		||||
        response.setHeader('Content-Type', self.context.contentType)
 | 
			
		||||
        response.setHeader('Content-Length', len(data))
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
class MediaAssetView(ResourceView):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def macro(self):
 | 
			
		||||
        if 'image/' in self.context.contentType:
 | 
			
		||||
            return self.template.macros['image']
 | 
			
		||||
        else:
 | 
			
		||||
            return self.template.macros['download']
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										47
									
								
								common.py
									
										
									
									
									
								
							
							
						
						
									
										47
									
								
								common.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -29,9 +29,54 @@ from zope.app.dublincore.zopedublincore import ScalarProperty
 | 
			
		|||
from zope.component import adapts
 | 
			
		||||
from zope.interface import implements
 | 
			
		||||
from zope.cachedescriptors.property import Lazy
 | 
			
		||||
from loops.interfaces import ILoopsObject
 | 
			
		||||
from loops.interfaces import ILoopsObject, IConcept, IResource
 | 
			
		||||
from loops.interfaces import IResourceAdapter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# type interface adapters
 | 
			
		||||
 | 
			
		||||
class AdapterBase(object):
 | 
			
		||||
    """ (Mix-in) Class for concept adapters that provide editing of fields
 | 
			
		||||
        defined by the type interface.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    adapts(IConcept)
 | 
			
		||||
 | 
			
		||||
    _attributes = ('context', '__parent__', )
 | 
			
		||||
    _schemas = list(IConcept)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, context):
 | 
			
		||||
        self.context = context # to get the permission stuff right
 | 
			
		||||
        self.__parent__ = context
 | 
			
		||||
 | 
			
		||||
    def __getattr__(self, attr):
 | 
			
		||||
        self.checkAttr(attr)
 | 
			
		||||
        return getattr(self.context, '_' + attr, None)
 | 
			
		||||
 | 
			
		||||
    def __setattr__(self, attr, value):
 | 
			
		||||
        if attr in self._attributes:
 | 
			
		||||
            object.__setattr__(self, attr, value)
 | 
			
		||||
        else:
 | 
			
		||||
            self.checkAttr(attr)
 | 
			
		||||
            setattr(self.context, '_' + attr, value)
 | 
			
		||||
 | 
			
		||||
    def checkAttr(self, attr):
 | 
			
		||||
        if attr not in self._schemas:
 | 
			
		||||
            raise AttributeError(attr)
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return self.context == other.context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourceAdapterBase(AdapterBase):
 | 
			
		||||
 | 
			
		||||
    adapts(IResource)
 | 
			
		||||
 | 
			
		||||
    _schemas = list(IResourceAdapter)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# other adapters
 | 
			
		||||
 | 
			
		||||
class LoopsDCAdapter(ZDCAnnotatableAdapter):
 | 
			
		||||
 | 
			
		||||
    implements(IZopeDublinCore)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -125,6 +125,30 @@
 | 
			
		|||
 | 
			
		||||
  </content>
 | 
			
		||||
 | 
			
		||||
  <interface
 | 
			
		||||
      interface=".interfaces.IResource"
 | 
			
		||||
      type="zope.app.content.interfaces.IContentType" />
 | 
			
		||||
 | 
			
		||||
  <class class=".resource.Resource">
 | 
			
		||||
 | 
			
		||||
    <implements
 | 
			
		||||
       interface="zope.app.annotation.interfaces.IAttributeAnnotatable" />
 | 
			
		||||
 | 
			
		||||
    <factory
 | 
			
		||||
        id="loops.Resource"
 | 
			
		||||
        description="Document" />
 | 
			
		||||
 | 
			
		||||
    <require
 | 
			
		||||
        permission="zope.View"
 | 
			
		||||
        interface=".interfaces.IBaseResource
 | 
			
		||||
                   zope.app.size.interfaces.ISized" />
 | 
			
		||||
 | 
			
		||||
    <require
 | 
			
		||||
        permission="zope.ManageContent"
 | 
			
		||||
        set_schema=".interfaces.IBaseResource" />
 | 
			
		||||
 | 
			
		||||
  </class>
 | 
			
		||||
 | 
			
		||||
  <interface
 | 
			
		||||
      interface=".interfaces.IDocument"
 | 
			
		||||
      type="zope.app.content.interfaces.IContentType" />
 | 
			
		||||
| 
						 | 
				
			
			@ -141,19 +165,12 @@
 | 
			
		|||
    <require
 | 
			
		||||
        permission="zope.View"
 | 
			
		||||
        interface=".interfaces.IDocument
 | 
			
		||||
                   .interfaces.IFileSystemResource
 | 
			
		||||
                   .interfaces.IControlledResource
 | 
			
		||||
                   zope.app.size.interfaces.ISized" />
 | 
			
		||||
 | 
			
		||||
    <require
 | 
			
		||||
        permission="zope.ManageContent"
 | 
			
		||||
        set_schema=".interfaces.IDocument" />
 | 
			
		||||
 | 
			
		||||
    <require
 | 
			
		||||
        permission="zope.ManageApplication"
 | 
			
		||||
        set_schema=".interfaces.IFileSystemResource
 | 
			
		||||
                    .interfaces.IControlledResource" />
 | 
			
		||||
 | 
			
		||||
  </content>
 | 
			
		||||
 | 
			
		||||
  <interface
 | 
			
		||||
| 
						 | 
				
			
			@ -171,11 +188,11 @@
 | 
			
		|||
 | 
			
		||||
    <require
 | 
			
		||||
        permission="zope.View"
 | 
			
		||||
        interface=".interfaces.IMediaAsset" />
 | 
			
		||||
        interface=".interfaces.IBaseResource" />
 | 
			
		||||
 | 
			
		||||
    <require
 | 
			
		||||
        permission="zope.ManageContent"
 | 
			
		||||
        set_schema=".interfaces.IMediaAsset" />
 | 
			
		||||
        set_schema=".interfaces.IBaseResource" />
 | 
			
		||||
 | 
			
		||||
  </content>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -249,12 +266,7 @@
 | 
			
		|||
           trusted="True" />
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.common.LoopsDCAdapter"
 | 
			
		||||
           for="loops.interfaces.IDocument"
 | 
			
		||||
           provides="zope.app.dublincore.interfaces.IZopeDublinCore"
 | 
			
		||||
           trusted="True" />
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.common.LoopsDCAdapter"
 | 
			
		||||
           for="loops.interfaces.IMediaAsset"
 | 
			
		||||
           for="loops.interfaces.IResource"
 | 
			
		||||
           provides="zope.app.dublincore.interfaces.IZopeDublinCore"
 | 
			
		||||
           trusted="True" />
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -264,16 +276,30 @@
 | 
			
		|||
 | 
			
		||||
  <adapter factory="loops.concept.IndexAttributes" />
 | 
			
		||||
  <adapter factory="loops.resource.IndexAttributes" />
 | 
			
		||||
  <adapter factory="loops.resource.IndexableResource" />
 | 
			
		||||
  <adapter factory="loops.resource.IndexableResource" trusted="True" />
 | 
			
		||||
  <class class="loops.resource.IndexableResource">
 | 
			
		||||
    <require permission="zope.View"
 | 
			
		||||
             interface="loops.interfaces.IBaseResourceSchema" />
 | 
			
		||||
  </class>
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.resource.DocumentReadFileAdapter" />
 | 
			
		||||
  <adapter factory="loops.resource.DocumentWriteFileAdapter" />
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.type.LoopsType" />
 | 
			
		||||
  <adapter factory="loops.type.ConceptType" />
 | 
			
		||||
  <adapter factory="loops.type.ResourceType" />
 | 
			
		||||
  <adapter factory="loops.type.ResourceType"
 | 
			
		||||
           for="loops.interfaces.IDocument" />
 | 
			
		||||
  <adapter factory="loops.type.ResourceType"
 | 
			
		||||
           for="loops.interfaces.IMediaAsset" />
 | 
			
		||||
  <adapter factory="loops.type.LoopsTypeManager" />
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.type.TypeConcept" />
 | 
			
		||||
  <adapter factory="loops.type.TypeConcept" trusted="True" />
 | 
			
		||||
  <class class="loops.type.TypeConcept">
 | 
			
		||||
    <require permission="zope.View"
 | 
			
		||||
             interface="loops.interfaces.ITypeConcept" />
 | 
			
		||||
    <require permission="zope.ManageContent"
 | 
			
		||||
             set_schema="loops.interfaces.ITypeConcept" />
 | 
			
		||||
  </class>
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.query.QueryConcept" trusted="True" />
 | 
			
		||||
  <class class="loops.query.QueryConcept">
 | 
			
		||||
| 
						 | 
				
			
			@ -283,6 +309,14 @@
 | 
			
		|||
             set_schema="loops.query.IQueryConcept" />
 | 
			
		||||
  </class>
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.resource.FileAdapter" trusted="True" />
 | 
			
		||||
  <class class="loops.resource.FileAdapter">
 | 
			
		||||
    <require permission="zope.View"
 | 
			
		||||
             interface="loops.interfaces.IFile" />
 | 
			
		||||
    <require permission="zope.ManageContent"
 | 
			
		||||
             set_schema="loops.interfaces.IFile" />
 | 
			
		||||
  </class>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <adapter factory="loops.setup.SetupManager" />
 | 
			
		||||
  <adapter factory="loops.external.NodesLoader" />
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +336,7 @@
 | 
			
		|||
      />
 | 
			
		||||
 | 
			
		||||
  <vocabulary
 | 
			
		||||
      factory="loops.type.ResourceTypeSourceList"
 | 
			
		||||
      factory="loops.resource.ResourceTypeSourceList"
 | 
			
		||||
      name="loops.resourceTypeSource"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										100
									
								
								interfaces.py
									
										
									
									
									
								
							
							
						
						
									
										100
									
								
								interfaces.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -29,6 +29,7 @@ from zope.app.container.constraints import contains, containers
 | 
			
		|||
from zope.app.container.interfaces import IContainer, IOrderedContainer
 | 
			
		||||
from zope.app.file.interfaces import IImage as IBaseAsset
 | 
			
		||||
from zope.app.folder.interfaces import IFolder
 | 
			
		||||
from zope.app.size.interfaces import ISized
 | 
			
		||||
from cybertools.relation.interfaces import IRelation
 | 
			
		||||
 | 
			
		||||
import util
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +63,7 @@ class IPotentialTarget(Interface):
 | 
			
		|||
 | 
			
		||||
class IConcept(ILoopsObject, IPotentialTarget):
 | 
			
		||||
    """ The concept is the central element of the loops framework.
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
        A concept is related to other concepts, may have resources
 | 
			
		||||
        associated with it and may be referenced by views.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +131,7 @@ class IConcept(ILoopsObject, IPotentialTarget):
 | 
			
		|||
    def getResources(predicates=None):
 | 
			
		||||
        """ Return a sequence of resources assigned to self,
 | 
			
		||||
            optionally restricted to the predicates given.
 | 
			
		||||
        """        
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
    def getResourceRelations(predicates=None, resource=None):
 | 
			
		||||
        """ Return a sequence of relations to resources assigned to self,
 | 
			
		||||
| 
						 | 
				
			
			@ -143,12 +144,12 @@ class IConcept(ILoopsObject, IPotentialTarget):
 | 
			
		|||
 | 
			
		||||
            The relationship defaults to ConceptResourceRelation.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    def deassignResource(resource, predicates=None):
 | 
			
		||||
        """ Remove the relations to the resource given from self, optionally
 | 
			
		||||
            restricting them to the predicates given.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IConceptView(Interface):
 | 
			
		||||
    """ Used for accessing a concept via a node's target attribute"""
 | 
			
		||||
| 
						 | 
				
			
			@ -178,12 +179,12 @@ class IConceptManagerContained(Interface):
 | 
			
		|||
# resource interfaces
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IBaseResource(Interface):
 | 
			
		||||
class IBaseResource(ILoopsObject):
 | 
			
		||||
    """ New base interface for resources. Functionality beyond this simple
 | 
			
		||||
        interface is provided by adapters that are chosen via the
 | 
			
		||||
        resource type's typeInterface.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    title = schema.TextLine(
 | 
			
		||||
                title=_(u'Title'),
 | 
			
		||||
                description=_(u'Title of the resource'),
 | 
			
		||||
| 
						 | 
				
			
			@ -199,6 +200,26 @@ class IBaseResource(Interface):
 | 
			
		|||
        source="loops.resourceTypeSource",
 | 
			
		||||
        required=False)
 | 
			
		||||
 | 
			
		||||
    data = schema.Bytes(
 | 
			
		||||
                title=_(u'Data'),
 | 
			
		||||
                description=_(u'Resource raw data'),
 | 
			
		||||
                default='',
 | 
			
		||||
                missing_value='',
 | 
			
		||||
                required=False)
 | 
			
		||||
 | 
			
		||||
    contentType = schema.BytesLine(
 | 
			
		||||
                title=_(u'Content Type'),
 | 
			
		||||
                description=_(u'Content type (format) of the data field'),
 | 
			
		||||
                default='',
 | 
			
		||||
                missing_value='',
 | 
			
		||||
                required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IBaseResourceSchema(Interface):
 | 
			
		||||
    """ New schema for resources; to be used by sub-interfaces that will
 | 
			
		||||
        be implemented by type adapters.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IResourceSchema(Interface):
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -224,29 +245,6 @@ class IResourceSchema(Interface):
 | 
			
		|||
                required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# the next two interfaces are probably obsolete:
 | 
			
		||||
 | 
			
		||||
class IFileSystemResource(Interface):
 | 
			
		||||
 | 
			
		||||
    fsPath = schema.BytesLine(
 | 
			
		||||
                title=_(u'Filesystem Path'),
 | 
			
		||||
                description=_(u'Optional path to a file in the filesystem '
 | 
			
		||||
                               'to be used for storing the resource'),
 | 
			
		||||
                default='',
 | 
			
		||||
                missing_value='',
 | 
			
		||||
                required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IControlledResource(Interface):
 | 
			
		||||
 | 
			
		||||
    readOnly = schema.Bool(
 | 
			
		||||
                title=_(u'Read only'),
 | 
			
		||||
                description=_(u'Check this if resource may not be modified '
 | 
			
		||||
                               'after being first filled with non-empty content'),
 | 
			
		||||
                default=False,
 | 
			
		||||
                required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IResource(ILoopsObject, IPotentialTarget):
 | 
			
		||||
    """ A resource is an atomic information element that is made
 | 
			
		||||
        available via a view or a concept.
 | 
			
		||||
| 
						 | 
				
			
			@ -323,10 +321,10 @@ class IMediaAssetView(IMediaAssetSchema):
 | 
			
		|||
 | 
			
		||||
class IMediaAsset(IMediaAssetSchema, IResource, IBaseAsset):
 | 
			
		||||
    """ A resource containing a (typically binary) file-like content
 | 
			
		||||
        or an image. 
 | 
			
		||||
        or an image.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IResourceManager(ILoopsObject, IContainer):
 | 
			
		||||
    """ A manager/container for resources.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -475,7 +473,7 @@ class ILoops(ILoopsObject):
 | 
			
		|||
        """ Retrieve object specified by the loops uri (starting with
 | 
			
		||||
        '.loops/') given.
 | 
			
		||||
        """
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def getConceptManager():
 | 
			
		||||
        """ Return the (default) concept manager.
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -545,7 +543,7 @@ class ITypeConcept(Interface):
 | 
			
		|||
    # storage = schema.Choice()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IResourceAdapter(Interface):
 | 
			
		||||
class IResourceAdapter(IBaseResourceSchema):
 | 
			
		||||
    """ Base interface for adapters for resources. This is the base interface
 | 
			
		||||
        of the interfaces to be used as typeInterface attribute on type concepts
 | 
			
		||||
        specifying resource types.
 | 
			
		||||
| 
						 | 
				
			
			@ -556,15 +554,15 @@ class IFile(IResourceAdapter):
 | 
			
		|||
    """ A media asset that is not shown on a (web) page like an image but
 | 
			
		||||
        may be downloaded instead.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IImage(IResourceAdapter):
 | 
			
		||||
    """ A media asset that may be embedded in a (web) page as an image.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ITextDocument(IResourceAdapter):
 | 
			
		||||
    """ A resource containing some sort of plain text that may be rendered and 
 | 
			
		||||
    """ A resource containing some sort of plain text that may be rendered and
 | 
			
		||||
        edited without necessarily involving a special external application
 | 
			
		||||
        (like e.g. OpenOffice); typical content types are text/html, text/xml,
 | 
			
		||||
        text/restructured, etc.
 | 
			
		||||
| 
						 | 
				
			
			@ -581,3 +579,27 @@ class IViewConfiguratorSchema(Interface):
 | 
			
		|||
        default=u'',
 | 
			
		||||
        required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# the next two interfaces are obsolete, they will be replaced by IResourceStorage:
 | 
			
		||||
 | 
			
		||||
class IFileSystemResource(Interface):
 | 
			
		||||
 | 
			
		||||
    fsPath = schema.BytesLine(
 | 
			
		||||
                title=_(u'Filesystem Path'),
 | 
			
		||||
                description=_(u'Optional path to a file in the filesystem '
 | 
			
		||||
                               'to be used for storing the resource'),
 | 
			
		||||
                default='',
 | 
			
		||||
                missing_value='',
 | 
			
		||||
                required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IControlledResource(Interface):
 | 
			
		||||
 | 
			
		||||
    readOnly = schema.Bool(
 | 
			
		||||
                title=_(u'Read only'),
 | 
			
		||||
                description=_(u'Check this if resource may not be modified '
 | 
			
		||||
                               'after being first filled with non-empty content'),
 | 
			
		||||
                default=False,
 | 
			
		||||
                required=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,8 @@ from loops.interfaces import IConcept, IResource
 | 
			
		|||
from loops.knowledge.interfaces import IPerson, ITask
 | 
			
		||||
from loops.organize.party import Person as BasePerson
 | 
			
		||||
from loops.organize.task import Task as BaseTask
 | 
			
		||||
from loops.type import TypeInterfaceSourceList, AdapterBase
 | 
			
		||||
from loops.common import AdapterBase
 | 
			
		||||
from loops.type import TypeInterfaceSourceList
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# register type interfaces - (TODO: use a function for this)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,8 @@ from cybertools.typology.interfaces import IType
 | 
			
		|||
from loops.concept import Concept
 | 
			
		||||
from loops.interfaces import IConcept
 | 
			
		||||
from loops.organize.interfaces import IPerson, ANNOTATION_KEY
 | 
			
		||||
from loops.type import TypeInterfaceSourceList, AdapterBase
 | 
			
		||||
from loops.common import AdapterBase
 | 
			
		||||
from loops.type import TypeInterfaceSourceList
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# register type interfaces - (TODO: use a function for this)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@ from zope.interface import implements
 | 
			
		|||
 | 
			
		||||
from cybertools.organize.interfaces import ITask
 | 
			
		||||
from loops.interfaces import IConcept
 | 
			
		||||
from loops.type import TypeInterfaceSourceList, AdapterBase
 | 
			
		||||
from loops.common import AdapterBase
 | 
			
		||||
from loops.type import TypeInterfaceSourceList
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TypeInterfaceSourceList.typeInterfaces += (ITask,)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,8 @@ from cybertools.typology.interfaces import IType
 | 
			
		|||
from cybertools.process.interfaces import IProcess
 | 
			
		||||
from cybertools.process.definition import Process as BaseProcess
 | 
			
		||||
from loops.interfaces import IConcept
 | 
			
		||||
from loops.type import TypeInterfaceSourceList, AdapterBase
 | 
			
		||||
from loops.common import AdapterBase
 | 
			
		||||
from loops.type import TypeInterfaceSourceList
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# register type interfaces - (TODO: use a function for this)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								query.py
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								query.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -32,7 +32,8 @@ from zope.security.proxy import removeSecurityProxy
 | 
			
		|||
 | 
			
		||||
from cybertools.typology.type import BaseType, TypeManager
 | 
			
		||||
from loops.interfaces import IConcept
 | 
			
		||||
from loops.type import AdapterBase, TypeInterfaceSourceList
 | 
			
		||||
from loops.common import AdapterBase
 | 
			
		||||
from loops.type import TypeInterfaceSourceList
 | 
			
		||||
 | 
			
		||||
_ = MessageFactory('loops')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										127
									
								
								resource.py
									
										
									
									
									
								
							
							
						
						
									
										127
									
								
								resource.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -25,13 +25,15 @@ $Id$
 | 
			
		|||
from zope.app import zapi
 | 
			
		||||
from zope.app.container.btree import BTreeContainer
 | 
			
		||||
from zope.app.container.contained import Contained
 | 
			
		||||
from zope.app.file.image import Image as BaseMediaAsset
 | 
			
		||||
from zope.app.file.image import Image
 | 
			
		||||
from zope.app.file.interfaces import IFile
 | 
			
		||||
from zope.app.filerepresentation.interfaces import IReadFile, IWriteFile
 | 
			
		||||
from zope.app.size.interfaces import ISized
 | 
			
		||||
from zope.cachedescriptors.property import Lazy
 | 
			
		||||
from zope.component import adapts
 | 
			
		||||
from zope.i18nmessageid import MessageFactory
 | 
			
		||||
from zope.interface import implements
 | 
			
		||||
from zope import schema
 | 
			
		||||
from persistent import Persistent
 | 
			
		||||
from cStringIO import StringIO
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,36 +41,42 @@ from textindexng.interfaces import IIndexableContent
 | 
			
		|||
from textindexng.content import IndexContentCollector
 | 
			
		||||
from cybertools.relation.registry import getRelations
 | 
			
		||||
from cybertools.relation.interfaces import IRelatable
 | 
			
		||||
from cybertools.typology.interfaces import ITypeManager
 | 
			
		||||
 | 
			
		||||
from interfaces import IBaseResource, IResource
 | 
			
		||||
from interfaces import IFile
 | 
			
		||||
from interfaces import IDocument, IDocumentSchema, IDocumentView
 | 
			
		||||
from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView
 | 
			
		||||
from interfaces import IFileSystemResource, IControlledResource
 | 
			
		||||
from interfaces import IResourceManager, IResourceManagerContained
 | 
			
		||||
from interfaces import ILoopsContained
 | 
			
		||||
from interfaces import IIndexAttributes
 | 
			
		||||
from concept import ResourceRelation
 | 
			
		||||
from common import ResourceAdapterBase
 | 
			
		||||
from view import TargetRelation
 | 
			
		||||
 | 
			
		||||
_ = MessageFactory('loops')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Resource(Contained, Persistent):
 | 
			
		||||
class Resource(Image, Contained):
 | 
			
		||||
 | 
			
		||||
    implements(IBaseResource, IResource, IResourceManagerContained, IRelatable, ISized)
 | 
			
		||||
 | 
			
		||||
    implements(IBaseResource, IResource, IFileSystemResource, IControlledResource,
 | 
			
		||||
               IResourceManagerContained, IRelatable)
 | 
			
		||||
               
 | 
			
		||||
    proxyInterface = IMediaAssetView
 | 
			
		||||
 | 
			
		||||
    _size = _width = _height = 0
 | 
			
		||||
 | 
			
		||||
    def __init__(self, title=u''):
 | 
			
		||||
        super(Resource, self).__init__()
 | 
			
		||||
        self.title = title
 | 
			
		||||
 | 
			
		||||
    def getResourceType(self):
 | 
			
		||||
        typePred = self.getLoopsRoot().getConceptManager().getTypePredicate()
 | 
			
		||||
        cm = self.getLoopsRoot().getConceptManager()
 | 
			
		||||
        typePred = cm.getTypePredicate()
 | 
			
		||||
        if typePred is None:
 | 
			
		||||
            return None
 | 
			
		||||
        concepts = self.getConcepts([typePred])
 | 
			
		||||
        # TODO (?): check for multiple types (->Error)
 | 
			
		||||
        return concepts and concepts[0] or None
 | 
			
		||||
        return concepts and concepts[0] or cm.get('file', None)
 | 
			
		||||
    def setResourceType(self, concept):
 | 
			
		||||
        current = self.getResourceType()
 | 
			
		||||
        if current != concept:
 | 
			
		||||
| 
						 | 
				
			
			@ -80,32 +88,32 @@ class Resource(Contained, Persistent):
 | 
			
		|||
                self.deassignConcept(current, [typePred])
 | 
			
		||||
            self.assignConcept(concept, typePred)
 | 
			
		||||
    resourceType = property(getResourceType, setResourceType)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    _title = u''
 | 
			
		||||
    def getTitle(self): return self._title
 | 
			
		||||
    def setTitle(self, title): self._title = title
 | 
			
		||||
    title = property(getTitle, setTitle)
 | 
			
		||||
 | 
			
		||||
    _contentType = ''
 | 
			
		||||
    def _setData(self, data):
 | 
			
		||||
        dataFile = StringIO(data)  # let File tear it into pieces
 | 
			
		||||
        super(Resource, self)._setData(dataFile)
 | 
			
		||||
        if not self.contentType:
 | 
			
		||||
            self.guessContentType(data)
 | 
			
		||||
    data = property(Image._getData, _setData)
 | 
			
		||||
 | 
			
		||||
    def guessContentType(self, data):
 | 
			
		||||
        if not isinstance(data, str): # seems to be a file object
 | 
			
		||||
            data = data.read(20)
 | 
			
		||||
        if data.startswith('%PDF'):
 | 
			
		||||
            self.contentType = 'application/pdf'
 | 
			
		||||
 | 
			
		||||
    _contentType = u''
 | 
			
		||||
    def setContentType(self, contentType):
 | 
			
		||||
        if contentType:
 | 
			
		||||
            self._contentType = contentType
 | 
			
		||||
    def getContentType(self): return self._contentType
 | 
			
		||||
    contentType = property(getContentType, setContentType)
 | 
			
		||||
 | 
			
		||||
    _fsPath = ''
 | 
			
		||||
    def setFsPath(self, fsPath): self._fsPath = fsPath
 | 
			
		||||
    def getFsPath(self): return self._fsPath
 | 
			
		||||
    fsPath = property(getFsPath, setFsPath)
 | 
			
		||||
 | 
			
		||||
    _readOnly = ''
 | 
			
		||||
    def setReadOnly(self, readOnly): self._readOnly = readOnly
 | 
			
		||||
    def getReadOnly(self): return self._readOnly
 | 
			
		||||
    readOnly = property(getReadOnly, setReadOnly)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, title=u''):
 | 
			
		||||
        self.title = title
 | 
			
		||||
 | 
			
		||||
    def getLoopsRoot(self):
 | 
			
		||||
        return zapi.getParent(self).getLoopsRoot()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +130,7 @@ class Resource(Contained, Persistent):
 | 
			
		|||
        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)]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -132,17 +140,7 @@ class Resource(Contained, Persistent):
 | 
			
		|||
    def deassignConcept(self, concept, predicates=None):
 | 
			
		||||
        concept.deassignResource(self, predicates)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Document(Resource):
 | 
			
		||||
 | 
			
		||||
    implements(IDocument, ISized)
 | 
			
		||||
 | 
			
		||||
    proxyInterface = IDocumentView
 | 
			
		||||
 | 
			
		||||
    _data = u''
 | 
			
		||||
    def setData(self, data): self._data = data
 | 
			
		||||
    def getData(self): return self._data
 | 
			
		||||
    data = property(getData, setData)
 | 
			
		||||
    # ISized interface
 | 
			
		||||
 | 
			
		||||
    def getSize(self):
 | 
			
		||||
        return len(self.data)
 | 
			
		||||
| 
						 | 
				
			
			@ -154,29 +152,24 @@ class Document(Resource):
 | 
			
		|||
        return '%i Bytes' % self.getSize()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MediaAsset(Resource, BaseMediaAsset):
 | 
			
		||||
class Document(Resource):
 | 
			
		||||
 | 
			
		||||
    implements(IMediaAsset)
 | 
			
		||||
    implements(IDocument)
 | 
			
		||||
 | 
			
		||||
    proxyInterface = IMediaAssetView
 | 
			
		||||
    proxyInterface = IDocumentView
 | 
			
		||||
 | 
			
		||||
    def __init__(self, title=u''):
 | 
			
		||||
        super(MediaAsset, self).__init__()
 | 
			
		||||
        self.title = title
 | 
			
		||||
 | 
			
		||||
    def _setData(self, data):
 | 
			
		||||
        dataFile = StringIO(data)  # let File tear it into pieces
 | 
			
		||||
        super(MediaAsset, self)._setData(dataFile)
 | 
			
		||||
        if not self.contentType:
 | 
			
		||||
            self.guessContentType(data)
 | 
			
		||||
    _data = ''
 | 
			
		||||
    def setData(self, data): self._data = data
 | 
			
		||||
    def getData(self): return self._data
 | 
			
		||||
    data = property(getData, setData)
 | 
			
		||||
 | 
			
		||||
    data = property(BaseMediaAsset._getData, _setData)
 | 
			
		||||
 | 
			
		||||
    def guessContentType(self, data):
 | 
			
		||||
        if not isinstance(data, str): # seems to be a file object
 | 
			
		||||
            data = data.read(20)
 | 
			
		||||
        if data.startswith('%PDF'):
 | 
			
		||||
            self.contentType = 'application/pdf'
 | 
			
		||||
class MediaAsset(Resource):
 | 
			
		||||
 | 
			
		||||
    implements(IMediaAsset)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourceManager(BTreeContainer):
 | 
			
		||||
| 
						 | 
				
			
			@ -188,17 +181,19 @@ class ResourceManager(BTreeContainer):
 | 
			
		|||
 | 
			
		||||
    def getViewManager(self):
 | 
			
		||||
        return self.getLoopsRoot().getViewManager()
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# adapters and similar stuff
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FileAdapter(object):
 | 
			
		||||
class FileAdapter(ResourceAdapterBase):
 | 
			
		||||
    """ A type adapter for providing file functionality for resources.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    def __init__(self, context):
 | 
			
		||||
        self.context = context
 | 
			
		||||
 | 
			
		||||
    implements(IFile)
 | 
			
		||||
 | 
			
		||||
    # TODO: provide specialized access to data attribute analog to zope.app.file;
 | 
			
		||||
    #       automatically set contentType...
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DocumentWriteFileAdapter(object):
 | 
			
		||||
| 
						 | 
				
			
			@ -259,3 +254,23 @@ class IndexableResource(object):
 | 
			
		|||
        icc.addBinary(fields[0], context.data, context.contentType, language='de')
 | 
			
		||||
        return icc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourceTypeSourceList(object):
 | 
			
		||||
 | 
			
		||||
    implements(schema.interfaces.IIterableSource)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, context):
 | 
			
		||||
        self.context = context
 | 
			
		||||
 | 
			
		||||
    def __iter__(self):
 | 
			
		||||
        return iter(self.resourceTypes)
 | 
			
		||||
 | 
			
		||||
    @Lazy
 | 
			
		||||
    def resourceTypes(self):
 | 
			
		||||
        types = ITypeManager(self.context).listTypes(include=('resource',))
 | 
			
		||||
        return [t.typeProvider for t in types if t.typeProvider is not None]
 | 
			
		||||
 | 
			
		||||
    def __len__(self):
 | 
			
		||||
        return len(self.resourceTypes)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										64
									
								
								type.py
									
										
									
									
									
								
							
							
						
						
									
										64
									
								
								type.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -36,6 +36,7 @@ from loops.interfaces import ITypeConcept
 | 
			
		|||
from loops.interfaces import IResourceAdapter, IFile, IImage, ITextDocument
 | 
			
		||||
from loops.concept import Concept
 | 
			
		||||
from loops.resource import Resource, Document, MediaAsset
 | 
			
		||||
from loops.common import AdapterBase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LoopsType(BaseType):
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +66,7 @@ class LoopsType(BaseType):
 | 
			
		|||
    def typeInterface(self):
 | 
			
		||||
        adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept)
 | 
			
		||||
        if adapter is not None:
 | 
			
		||||
            return adapter.typeInterface
 | 
			
		||||
            return removeSecurityProxy(adapter.typeInterface)
 | 
			
		||||
        else:
 | 
			
		||||
            conceptType = self.typeProvider
 | 
			
		||||
            typeConcept = self.root.getConceptManager().getTypeConcept()
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +131,7 @@ class ResourceType(LoopsType):
 | 
			
		|||
        type concepts as is already the case for concepts.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    adapts(IResource)
 | 
			
		||||
    #adapts(IResource)
 | 
			
		||||
 | 
			
		||||
    typeTitles = {'MediaAsset': u'Media Asset'}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -214,15 +215,13 @@ class LoopsTypeManager(TypeManager):
 | 
			
		|||
                        for cls in (Document, MediaAsset)])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TypeConcept(object):
 | 
			
		||||
class TypeConcept(AdapterBase):
 | 
			
		||||
    """ typeInterface adapter for concepts of type 'type'.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    implements(ITypeConcept)
 | 
			
		||||
    adapts(IConcept)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, context):
 | 
			
		||||
        self.context = removeSecurityProxy(context)
 | 
			
		||||
    _schemas = list(ITypeConcept) + list(IConcept)
 | 
			
		||||
 | 
			
		||||
    def getTypeInterface(self):
 | 
			
		||||
        ti = getattr(self.context, '_typeInterface', None)
 | 
			
		||||
| 
						 | 
				
			
			@ -251,56 +250,3 @@ class TypeInterfaceSourceList(object):
 | 
			
		|||
    def __len__(self):
 | 
			
		||||
        return len(self.typeInterfaces)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourceTypeSourceList(object):
 | 
			
		||||
 | 
			
		||||
    implements(schema.interfaces.IIterableSource)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, context):
 | 
			
		||||
        self.context = context
 | 
			
		||||
 | 
			
		||||
    def __iter__(self):
 | 
			
		||||
        return iter(self.resourceTypes)
 | 
			
		||||
 | 
			
		||||
    @Lazy
 | 
			
		||||
    def resourceTypes(self):
 | 
			
		||||
        types = ITypeManager(self.context).listTypes(include=('resource',))
 | 
			
		||||
        return [t.typeProvider for t in types]
 | 
			
		||||
 | 
			
		||||
    def __len__(self):
 | 
			
		||||
        return len(self.resourceTypes)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdapterBase(object):
 | 
			
		||||
    """ (Mix-in) Class for concept adapters that provide editing of fields
 | 
			
		||||
        defined by the type interface.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    adapts(IConcept)
 | 
			
		||||
 | 
			
		||||
    _attributes = ('context', '__parent__', )
 | 
			
		||||
    _schemas = list(IConcept)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, context):
 | 
			
		||||
        self.context = context # to get the permission stuff right
 | 
			
		||||
        self.__parent__ = context
 | 
			
		||||
 | 
			
		||||
    def __getattr__(self, attr):
 | 
			
		||||
        self.checkAttr(attr)
 | 
			
		||||
        return getattr(self.context, '_' + attr, None)
 | 
			
		||||
 | 
			
		||||
    def __setattr__(self, attr, value):
 | 
			
		||||
        if attr in self._attributes:
 | 
			
		||||
            object.__setattr__(self, attr, value)
 | 
			
		||||
        else:
 | 
			
		||||
            self.checkAttr(attr)
 | 
			
		||||
            setattr(self.context, '_' + attr, value)
 | 
			
		||||
 | 
			
		||||
    def checkAttr(self, attr):
 | 
			
		||||
        if attr not in self._schemas:
 | 
			
		||||
            raise AttributeError(attr)
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return self.context == other.context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue