diff --git a/common.py b/common.py
index d4fd906..1fd8324 100644
--- a/common.py
+++ b/common.py
@@ -38,6 +38,7 @@ from cybertools.storage.interfaces import IStorageInfo
from cybertools.typology.interfaces import IType
from loops.interfaces import ILoopsObject, ILoopsContained
from loops.interfaces import IConcept, IResource, IResourceAdapter
+from loops import util
# convenience functions
@@ -95,6 +96,8 @@ class AdapterBase(object):
_noexportAttributes = ()
_textIndexAttributes = ()
+ languageInfo = None
+
def __init__(self, context):
self.context = context
self.__parent__ = context # to get the permission stuff right
@@ -130,6 +133,14 @@ class AdapterBase(object):
def name(self):
return getName(self.context)
+ @Lazy
+ def uid(self):
+ return util.getUidForObject(self.context)
+
+ def getChildren(self):
+ for c in self.context.getChildren():
+ yield adapted(c, self.languageInfo)
+
class ResourceAdapterBase(AdapterBase):
@@ -142,6 +153,10 @@ class ResourceAdapterBase(AdapterBase):
storageName = None
storageParams = None
+ def getChildren(self):
+ for r in self.context.getResources():
+ yield adapted(r)
+
# other adapters
@@ -309,7 +324,7 @@ class ParentRelationSet(RelationSet):
def add(self, related, order=0, relevance=1.0):
if isinstance(related, AdapterBase):
related = related.context
- self.context.deassignParent(related, [self.predicate])
+ self.context.deassignParent(related, [self.predicate]) # avoid duplicates
self.context.assignParent(related, self.predicate, order, relevance)
def remove(self, related):
@@ -327,6 +342,7 @@ class ChildRelationSet(RelationSet):
def add(self, related, order=0, relevance=1.0):
if isinstance(related, AdapterBase):
related = related.context
+ self.context.deassignChild(related, [self.predicate]) # avoid duplicates
self.context.assignChild(related, self.predicate, order, relevance)
def remove(self, related):
diff --git a/expert/concept.py b/expert/concept.py
index 5b905dd..958b6c2 100644
--- a/expert/concept.py
+++ b/expert/concept.py
@@ -32,7 +32,7 @@ from zope.cachedescriptors.property import Lazy
from cybertools.typology.interfaces import IType
from loops.common import AdapterBase
-from loops.interfaces import IConcept, IConceptSchema
+from loops.interfaces import IConcept, IConceptSchema, ILoopsAdapter
from loops.security.common import canListObject
from loops.type import TypeInterfaceSourceList
from loops.versioning.util import getVersion
@@ -173,7 +173,7 @@ class ConceptQuery(BaseQuery):
# QueryConcept: concept objects that allow querying the database.
-class IQueryConcept(IConceptSchema):
+class IQueryConcept(ILoopsAdapter):
""" The schema for the query type.
"""
diff --git a/interfaces.py b/interfaces.py
index f20f4e9..47aa6d4 100644
--- a/interfaces.py
+++ b/interfaces.py
@@ -185,11 +185,26 @@ class IConcept(IConceptSchema, ILoopsObject, IPotentialTarget):
"""
+class ILoopsAdapter(IConceptSchema):
+ """ Common interface for concept and resource adapters.
+ """
+
+ context = Attribute('The underlying persistent object.')
+ uid = Attribute('Unique id of the context object.')
+
+ def getChildren():
+ """ Return a collection of child objects provided by the context
+ object.
+ """
+
+
class IConceptView(Interface):
- """ Used for accessing a concept via a node's target attribute"""
+ """ Used for accessing a concept via a node's target attribute.
+
+ Obsolete.
+ """
-#class IConceptManager(ILoopsObject, IContainer):
class IConceptManager(ILoopsObject):
""" A manager/container for concepts.
"""
@@ -684,7 +699,7 @@ class xxIMappingAttributeRelation(IConceptSchema):
# resources
-class IResourceAdapter(IBaseResourceSchema):
+class IResourceAdapter(IBaseResourceSchema, ILoopsAdapter):
""" 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.
diff --git a/layout/base.py b/layout/base.py
index 8f5c496..02f50ca 100644
--- a/layout/base.py
+++ b/layout/base.py
@@ -29,7 +29,6 @@ from zope.interface import implements
from cybertools.composer.layout.base import Layout, LayoutInstance
from cybertools.composer.layout.interfaces import ILayoutInstance
from loops.common import adapted
-from loops.layout.browser import ConceptView
from loops.layout.interfaces import ILayoutNode, ILayoutNodeContained
from loops.view import Node
diff --git a/layout/browser/concept.py b/layout/browser/concept.py
new file mode 100644
index 0000000..93044ba
--- /dev/null
+++ b/layout/browser/concept.py
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Layout-based concept views.
+
+$Id$
+"""
+
+from zope import component
+from zope.cachedescriptors.property import Lazy
+from zope.traversing.browser import absoluteURL
+
+from cybertools.composer.layout.browser.view import Page
+from loops.browser.common import BaseView
+from loops.common import adapted
+from loops.i18n.browser import LanguageInfo
+from loops.interfaces import IConcept
+from loops.layout.interfaces import ILayoutNode
+from loops.versioning.util import getVersion
+from loops import util
+
+
+class ConceptView(object):
+
+ node = None
+
+ def __init__(self, context, request):
+ self.context = context # this is the adapted concept!
+ self.request = request
+
+ @Lazy
+ def title(self):
+ return self.context.title
+
+ @Lazy
+ def url(self):
+ return '%s/.%s' % (absoluteURL(self.node, self.request), self.context.uid)
+
+ @property
+ def children(self):
+ for c in self.context.getChildren():
+ view = component.getMultiAdapter((c, self.request), name='layout')
+ view.node = self.node
+ yield view
+
diff --git a/layout/browser/configure.zcml b/layout/browser/configure.zcml
new file mode 100644
index 0000000..6e27359
--- /dev/null
+++ b/layout/browser/configure.zcml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/browser/node.py b/layout/browser/node.py
new file mode 100644
index 0000000..0553227
--- /dev/null
+++ b/layout/browser/node.py
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Layout node views.
+
+$Id$
+"""
+
+from zope.cachedescriptors.property import Lazy
+
+from cybertools.composer.layout.browser.view import Page
+
+
+class LayoutNodeView(Page):
+
+ @Lazy
+ def layoutName(self):
+ return self.context.viewName or 'page'
+
+ @Lazy
+ def layoutNames(self):
+ result = []
+ n = self.context
+ while n is not None:
+ if n.viewName:
+ result.append(n.viewName)
+ n = n.getParentNode()
+ result.append('page')
+ return result
+
diff --git a/layout/browser/browser.py b/layout/browser/traversal.py
similarity index 56%
rename from layout/browser/browser.py
rename to layout/browser/traversal.py
index 3fcdc4f..afa2ec8 100644
--- a/layout/browser/browser.py
+++ b/layout/browser/traversal.py
@@ -17,76 +17,22 @@
#
"""
-Layout node views.
+Layout node traversers.
$Id$
"""
-from zope import component
from zope.app.container.traversal import ItemTraverser
from zope.cachedescriptors.property import Lazy
from zope.component import adapts
-from zope.interface import implements
-from zope.traversing.browser import absoluteURL
-from cybertools.composer.layout.browser.view import Page
-from loops.browser.common import BaseView
from loops.common import adapted
from loops.i18n.browser import LanguageInfo
-from loops.interfaces import IConcept
from loops.layout.interfaces import ILayoutNode
from loops.versioning.util import getVersion
from loops import util
-class LayoutNodeView(Page):
-
- @Lazy
- def layoutName(self):
- return self.context.viewName or 'page'
-
- @Lazy
- def layoutNames(self):
- result = []
- n = self.context
- while n is not None:
- if n.viewName:
- result.append(n.viewName)
- n = n.getParentNode()
- result.append('page')
- return result
-
-
-class ConceptView(object):
-
- node = None
-
- def __init__(self, context, request):
- if IConcept.providedBy(context):
- self.adapted = adapted(context)
- self.context = context
- else:
- self.adapted = context
- self.context = context.context
- self.request = request
-
- @Lazy
- def title(self):
- return self.context.title
-
- @Lazy
- def url(self):
- return '%s/.%s' % (absoluteURL(self.node, self.request),
- util.getUidForObject(self.context))
-
- @property
- def children(self):
- for c in self.context.getChildren():
- view = component.getMultiAdapter((adapted(c), self.request), name='layout')
- view.node = self.node
- yield view
-
-
class NodeTraverser(ItemTraverser):
adapts(ILayoutNode)
@@ -105,6 +51,5 @@ class NodeTraverser(ItemTraverser):
target = adapted(target, LanguageInfo(target, request))
viewAnnotations['target'] = target
return target
- #return self.context
obj = super(NodeTraverser, self).publishTraverse(request, name)
return obj
diff --git a/layout/configure.zcml b/layout/configure.zcml
index 059d27e..1ac17a2 100644
--- a/layout/configure.zcml
+++ b/layout/configure.zcml
@@ -20,55 +20,6 @@
for="loops.layout.interfaces.ILayoutNode"
factory="loops.layout.base.NodeLayoutInstance" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+