allow for adoption of relations to a predicate interface;
with example implementation for a 'has Role' predicate in loops.organize
This commit is contained in:
parent
2709f73f94
commit
a8fce100fa
8 changed files with 111 additions and 29 deletions
|
@ -6,6 +6,8 @@ $Id$
|
||||||
1.1
|
1.1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- allow for adoption of relations to a predicate interface;
|
||||||
|
with example implementation for a 'has Role' predicate in loops.organize
|
||||||
- external collection: provide functionality for automatically populate
|
- external collection: provide functionality for automatically populate
|
||||||
meta information of media assets
|
meta information of media assets
|
||||||
- new query for retrieving work items independently of task or user
|
- new query for retrieving work items independently of task or user
|
||||||
|
|
|
@ -729,6 +729,12 @@ class IPredicate(IConceptSchema):
|
||||||
required=False)
|
required=False)
|
||||||
|
|
||||||
|
|
||||||
|
class IRelationAdapter(Interface):
|
||||||
|
""" Base interface for adapters to relations that allow the specification
|
||||||
|
of special properties of a relation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# probably not useful
|
# probably not useful
|
||||||
class xxIMappingAttributeRelation(IConceptSchema):
|
class xxIMappingAttributeRelation(IConceptSchema):
|
||||||
""" A relation based on a predicate ('mappingAttribute') that provides
|
""" A relation based on a predicate ('mappingAttribute') that provides
|
||||||
|
|
|
@ -390,15 +390,6 @@ Events listing
|
||||||
>>> list(listing.events())
|
>>> list(listing.events())
|
||||||
[<loops.browser.concept.ConceptRelationView ...>]
|
[<loops.browser.concept.ConceptRelationView ...>]
|
||||||
|
|
||||||
Allocation of persons to tasks
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
>>> from loops.organize.interfaces import IAllocated
|
|
||||||
>>> predicate = concepts['predicate']
|
|
||||||
>>> allocated = addAndConfigureObject(concepts, Concept, 'allocated',
|
|
||||||
... title=u'allocated',
|
|
||||||
... conceptType=predicate, predicateInterface=IAllocated)
|
|
||||||
|
|
||||||
|
|
||||||
Send Email to Members
|
Send Email to Members
|
||||||
=====================
|
=====================
|
||||||
|
@ -423,6 +414,45 @@ Show Presence of Other Users
|
||||||
>>> component.provideUtility(Presence())
|
>>> component.provideUtility(Presence())
|
||||||
|
|
||||||
|
|
||||||
|
Roles of Persons
|
||||||
|
================
|
||||||
|
|
||||||
|
When persons are assigned to a parent (e.g. an instutution or a project)
|
||||||
|
this assignment may be characterized by a certain role. This role may
|
||||||
|
be specified by using a special predicate that is associated with a
|
||||||
|
predicate interface that allows to specify the role.
|
||||||
|
|
||||||
|
(Note that the security-relevant assignment of persons is managed via
|
||||||
|
other special predicates: 'ismember', 'ismaster'. The 'hasrole'
|
||||||
|
predicate described here is intended for situations where the roles
|
||||||
|
may be chosen from an arbitrary list.)
|
||||||
|
|
||||||
|
>>> from loops.organize.interfaces import IHasRole
|
||||||
|
>>> predicate = concepts['predicate']
|
||||||
|
>>> hasRole = addAndConfigureObject(concepts, Concept, 'hasrole',
|
||||||
|
... title=u'has Role',
|
||||||
|
... conceptType=predicate, predicateInterface=IHasRole)
|
||||||
|
|
||||||
|
Let's now assign john to task01 and have a look at the relation created.
|
||||||
|
|
||||||
|
>>> task01.assignChild(john, hasRole)
|
||||||
|
>>> relation = task01.getChildRelations([hasRole])[0]
|
||||||
|
|
||||||
|
The role may be accessed by getting a relation adapter
|
||||||
|
|
||||||
|
>>> from loops.predicate import adaptedRelation
|
||||||
|
>>> adRelation = adaptedRelation(relation)
|
||||||
|
>>> adRelation.role is None
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> adRelation.role = 'member'
|
||||||
|
>>> relation._role
|
||||||
|
'member'
|
||||||
|
>>> adRelation = adaptedRelation(relation)
|
||||||
|
>>> adRelation.role
|
||||||
|
'member'
|
||||||
|
|
||||||
|
|
||||||
Calendar
|
Calendar
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,16 @@
|
||||||
set_schema="loops.organize.interfaces.ITask" />
|
set_schema="loops.organize.interfaces.ITask" />
|
||||||
</zope:class>
|
</zope:class>
|
||||||
|
|
||||||
|
<zope:adapter factory="loops.organize.party.HasRole"
|
||||||
|
provides="loops.organize.interfaces.IHasRole"
|
||||||
|
trusted="True" />
|
||||||
|
<zope:class class="loops.organize.party.HasRole">
|
||||||
|
<require permission="zope.View"
|
||||||
|
interface="loops.organize.interfaces.IHasRole" />
|
||||||
|
<require permission="zope.ManageContent"
|
||||||
|
set_schema="loops.organize.interfaces.IHasRole" />
|
||||||
|
</zope:class>
|
||||||
|
|
||||||
<!-- member registration -->
|
<!-- member registration -->
|
||||||
|
|
||||||
<zope:adapter factory="loops.organize.member.MemberRegistrationManager"
|
<zope:adapter factory="loops.organize.member.MemberRegistrationManager"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,9 +32,8 @@ from zope.security.proxy import removeSecurityProxy
|
||||||
from cybertools.organize.interfaces import IAddress as IBaseAddress
|
from cybertools.organize.interfaces import IAddress as IBaseAddress
|
||||||
from cybertools.organize.interfaces import IPerson as IBasePerson
|
from cybertools.organize.interfaces import IPerson as IBasePerson
|
||||||
from cybertools.organize.interfaces import ITask
|
from cybertools.organize.interfaces import ITask
|
||||||
from loops.interfaces import IConceptSchema
|
from loops.interfaces import ILoopsAdapter, IConceptSchema, IRelationAdapter
|
||||||
from loops.organize.util import getPrincipalFolder
|
from loops.organize.util import getPrincipalFolder
|
||||||
from loops.interfaces import ILoopsAdapter
|
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
|
||||||
|
@ -164,19 +163,20 @@ class ITask(IConceptSchema, ITask, ILoopsAdapter):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# 'allocated' predicate
|
# 'hasrole' predicate
|
||||||
|
|
||||||
class IAllocated(IConceptSchema):
|
class IHasRole(IRelationAdapter):
|
||||||
|
|
||||||
allocType = schema.Choice(
|
role = schema.Choice(
|
||||||
title=_(u'Allocation Type'),
|
title=_(u'Role'),
|
||||||
description=_(u'Specifies the kind of interaction a person or another '
|
description=_(u'Specifies the kind of interaction a person or another '
|
||||||
u'party has with the task or project it is allocated to.'),
|
u'party has with an institution, a task, or a project '
|
||||||
|
u'it is associated with.'),
|
||||||
source=util.KeywordVocabulary((
|
source=util.KeywordVocabulary((
|
||||||
('standard', _(u'Standard')),
|
('member', _(u'Member')),
|
||||||
('master', _(u'Master')),
|
('master', _(u'Master')),
|
||||||
)),
|
)),
|
||||||
default='standard',
|
default='member',
|
||||||
required=True)
|
required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -40,8 +40,9 @@ from cybertools.typology.interfaces import IType
|
||||||
from loops.common import AdapterBase
|
from loops.common import AdapterBase
|
||||||
from loops.concept import Concept
|
from loops.concept import Concept
|
||||||
from loops.interfaces import IConcept
|
from loops.interfaces import IConcept
|
||||||
from loops.organize.interfaces import IAddress, IPerson, IAllocated
|
from loops.organize.interfaces import IAddress, IPerson, IHasRole
|
||||||
from loops.organize.interfaces import ANNOTATION_KEY
|
from loops.organize.interfaces import ANNOTATION_KEY
|
||||||
|
from loops.predicate import RelationAdapter
|
||||||
from loops.security.common import assignOwner, removeOwner, allowEditingForOwner
|
from loops.security.common import assignOwner, removeOwner, allowEditingForOwner
|
||||||
from loops.type import TypeInterfaceSourceList
|
from loops.type import TypeInterfaceSourceList
|
||||||
from loops.predicate import PredicateInterfaceSourceList
|
from loops.predicate import PredicateInterfaceSourceList
|
||||||
|
@ -51,7 +52,7 @@ from loops import util
|
||||||
# register type interfaces - (TODO: use a function for this)
|
# register type interfaces - (TODO: use a function for this)
|
||||||
|
|
||||||
TypeInterfaceSourceList.typeInterfaces += (IPerson, IAddress)
|
TypeInterfaceSourceList.typeInterfaces += (IPerson, IAddress)
|
||||||
PredicateInterfaceSourceList.typeInterfaces += (IAllocated,)
|
PredicateInterfaceSourceList.predicateInterfaces += (IHasRole,)
|
||||||
|
|
||||||
|
|
||||||
def getPersonForUser(context, request=None, principal=None):
|
def getPersonForUser(context, request=None, principal=None):
|
||||||
|
@ -177,3 +178,11 @@ class Address(AdapterBase):
|
||||||
self.context._lines = value
|
self.context._lines = value
|
||||||
lines = property(getLines, setLines)
|
lines = property(getLines, setLines)
|
||||||
|
|
||||||
|
|
||||||
|
class HasRole(RelationAdapter):
|
||||||
|
""" Allows specification of a role for a relation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implements(IHasRole)
|
||||||
|
|
||||||
|
_contextAttributes = list(IHasRole)
|
||||||
|
|
|
@ -23,8 +23,8 @@ from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
|
||||||
from cybertools.util.jeep import Jeep
|
from cybertools.util.jeep import Jeep
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.concept import Concept
|
from loops.concept import Concept
|
||||||
from loops.organize.interfaces import IPerson
|
from loops.organize.interfaces import IPerson, IHasRole
|
||||||
from loops.organize.party import Person
|
from loops.organize.party import Person, HasRole
|
||||||
from loops.organize.task import Task
|
from loops.organize.task import Task
|
||||||
from loops.setup import addAndConfigureObject
|
from loops.setup import addAndConfigureObject
|
||||||
from loops.tests.auth import login
|
from loops.tests.auth import login
|
||||||
|
@ -38,6 +38,7 @@ def setupUtilitiesAndAdapters(loopsRoot):
|
||||||
component.provideAdapter(Person, provides=IPerson)
|
component.provideAdapter(Person, provides=IPerson)
|
||||||
component.provideAdapter(Task)
|
component.provideAdapter(Task)
|
||||||
component.provideAdapter(FoundPrincipalFactory)
|
component.provideAdapter(FoundPrincipalFactory)
|
||||||
|
component.provideAdapter(HasRole, provides=IHasRole)
|
||||||
return Jeep((
|
return Jeep((
|
||||||
('auth', auth),
|
('auth', auth),
|
||||||
('principalAnnotations', principalAnnotations),
|
('principalAnnotations', principalAnnotations),
|
||||||
|
|
34
predicate.py
34
predicate.py
|
@ -30,10 +30,10 @@ from zope.dottedname.resolve import resolve
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
from zope.traversing.api import getName
|
from zope.traversing.api import getName
|
||||||
|
|
||||||
from loops.interfaces import ILoopsObject, IConcept, IResource
|
from loops.interfaces import ILoopsObject, IConcept, IResource, IConceptRelation
|
||||||
from loops.interfaces import IPredicate #, IMappingAttributeRelation
|
from loops.interfaces import IPredicate, IRelationAdapter #, IMappingAttributeRelation
|
||||||
from loops.concept import Concept
|
from loops.concept import Concept
|
||||||
from loops.common import AdapterBase
|
from loops.common import adapted, AdapterBase
|
||||||
from loops.type import TypeInterfaceSourceList
|
from loops.type import TypeInterfaceSourceList
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,12 +60,36 @@ class PredicateInterfaceSourceList(TypeInterfaceSourceList):
|
||||||
may be used for specifying additional attributes of relations.
|
may be used for specifying additional attributes of relations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
typeInterfaces = ()
|
predicateInterfaces = ()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def typeInterfaces(self):
|
||||||
|
return self.predicateInterfaces
|
||||||
|
|
||||||
|
|
||||||
|
class RelationAdapter(AdapterBase):
|
||||||
|
""" Base class for adapters to relations that may be used for
|
||||||
|
specifying additional attributes for relations.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implements(IRelationAdapter)
|
||||||
|
adapts(IConceptRelation)
|
||||||
|
|
||||||
|
|
||||||
|
def adaptedRelation(relation):
|
||||||
|
if isinstance(relation, RelationAdapter):
|
||||||
|
return obj
|
||||||
|
ifc = adapted(relation.predicate).predicateInterface
|
||||||
|
if ifc is not None:
|
||||||
|
adRelation = component.queryAdapter(relation, ifc)
|
||||||
|
if adRelation is not None:
|
||||||
|
return adRelation
|
||||||
|
return relation
|
||||||
|
|
||||||
|
|
||||||
# standard relation adapters
|
# standard relation adapters
|
||||||
|
|
||||||
#PredicateInterfaceSourceList.typeInterfaces += (IMappingAttributeRelation,)
|
#PredicateInterfaceSourceList.predicateInterfaces += (IMappingAttributeRelation,)
|
||||||
|
|
||||||
|
|
||||||
#class MappingAttributeRelation(AdapterBase):
|
#class MappingAttributeRelation(AdapterBase):
|
||||||
|
|
Loading…
Add table
Reference in a new issue