use OOSet and separate Relation objects for subtask relations

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@537 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2005-08-10 18:58:00 +00:00
parent 10d9d20403
commit bc05aad5a4
5 changed files with 180 additions and 12 deletions

View file

@ -0,0 +1,75 @@
<!-- $Id$ -->
<configure
xmlns:zope="http://namespaces.zope.org/zope"
xmlns="http://namespaces.zope.org/browser"
i18n_domain="zope"
>
<addform
label="Add Task"
name="AddTask.html"
schema="loops.interfaces.ITask"
content_factory="loops.task.Task"
fields="title"
permission="zope.ManageContent"
/>
<addMenuItem
class="loops.task.Task"
title="Task"
description="A Task is a piece of work or something else a resource may be allocated to"
permission="zope.ManageContent"
view="AddTask.html"
/>
<editform
label="Edit Task"
name="edit.html"
schema="loops.interfaces.ITask"
for="loops.interfaces.ITask"
permission="zope.ManageContent"
menu="zmi_views" title="Edit"
/>
<containerViews
for="loops.interfaces.ITask"
index="zope.View"
contents="zope.View"
add="zope.ManageContent"
/>
<defaultView
for="loops.interfaces.ITask"
name="details.html"
/>
<page
name="details.html"
for="loops.interfaces.ITask"
class=".task.Details"
template="task_details.pt"
permission="zope.View"
menu="zmi_views" title="Details"
/>
<pages
for="loops.interfaces.ITask"
class=".task.SubtaskAssignments"
permission="zope.ManageContent"
>
<page
name="subtasks.html"
template="subtasks_assign.pt"
menu="zmi_views" title="Subtasks"
/>
<page
name="subtask_assign"
attribute="assignSubtask"
/>
</pages>
</configure>

View file

@ -28,6 +28,33 @@ from zope.app.container.interfaces import IOrderedContainer
from zope.schema import Text, TextLine, List, Object, Int
class IRelations(Interface):
""" Holds a set of relations (more precisely: ends of relations).
A simple implementation is to just use an IOSet.
"""
def add(relation):
""" Add a relation.
relationClass is the class that should be used for the relation
object; it should have a default setting, e.g. Relation.
"""
def remove(relation):
"""
"""
class IRelation(Interface):
""" Represents a relation from one object to another.
"""
source = Object(Interface,
title=u'Source Object',
description=u"Object that is the source of the relation")
target = Object(Interface,
title=u'Target Object',
description=u"Object that is the target of the relation")
class IResourceConstraint(Interface):
""" A ResourceConstraint governs which Resource objects may be
allocated to a Task object.
@ -244,4 +271,3 @@ class IResource(IOrderedContainer):
source task types given.
"""

47
relation.py Normal file
View file

@ -0,0 +1,47 @@
#
# Copyright (c) 2004 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
#
"""
relation classes implementation.
$Id$
"""
from BTrees.OOBTree import OOSet
from zope.interface import implements
from zope.app import zapi
from interfaces import IRelation, IRelations
class Relation(object):
implements(IRelation)
def __init__(self, source, target):
self._source = source
self._target = target
class Relations(OOSet):
implements(IRelations)
def add(self, relation, **kw):
self.insert(relation)

41
task.py
View file

@ -27,11 +27,24 @@ from zope.app.container.ordered import OrderedContainer
from zope.app.copypastemove import ObjectCopier
from zope.app import zapi
from relation import Relation, Relations
from resource import Resource
from interfaces import ITask
from copy import copy
class ResourceAllocation(Relation):
""" A relation that represents an allocation of a resource
to a task.
"""
class ResourceAllocations(Relations):
""" A set of resource allocations.
"""
class Task(OrderedContainer):
implements(ITask)
@ -43,24 +56,27 @@ class Task(OrderedContainer):
def __init__(self):
OrderedContainer.__init__(self)
self._subtasks = []
self._parentTasks = []
self._subtasks = Relations()
self._parentTasks = Relations()
self._resourceAllocs = {}
self.resourceConstraints = []
# subtasks:
def getSubtasks(self, taskTypes=None):
st = self._subtasks
st = [ r._target for r in self._subtasks ]
st.sort(lambda x,y: x.priority < y.priority and -1 or 1)
return tuple(st)
def getParentTasks(self, taskTypes=None):
return tuple(self._parentTasks)
pt = [ r._source for r in self._parentTasks ]
return tuple(pt)
def assignSubtask(self, task):
self._subtasks = self._subtasks + [task]
task._parentTasks = task._parentTasks + [self]
if task not in self.getSubtasks():
rel = Relation(self, task)
self._subtasks.add(rel)
task._parentTasks.add(rel)
def createSubtask(self, taskType=None, container=None, name=None):
container = container or zapi.getParent(self)
@ -71,8 +87,10 @@ class Task(OrderedContainer):
return task
def deassignSubtask(self, task):
self._subtasks.remove(task)
task._parentTasks.remove(self)
hits = [ r for r in self._subtasks if r._target == task ]
if hits:
self._subtasks.remove(hits[0])
task._parentTasks.remove(hits[0])
# resource allocations:
@ -172,10 +190,11 @@ class Task(OrderedContainer):
newName = self._createTaskName(targetContainer)
newTask = copy(self)
targetContainer[newName] = newTask
newTask._subtasks = []
for st in self.getSubtasks():
subtasks = self.getSubtasks()
newTask._subtasks.clear()
for st in subtasks:
newSt = st.copyTask(targetContainer)
newSt._parentTasks.remove(self)
newSt._parentTasks.clear()
newTask.assignSubtask(newSt)
return newTask

View file

@ -234,6 +234,7 @@ class TestTaskCopy(unittest.TestCase):
ts1.allocateResource(r1)
t2 = t1.copyTask()
self.failIf(t1 is t2, 't1 and t2 are still the same')
self.assertEquals(1, len(t1.getSubtasks()))
st2 = t2.getSubtasks()
self.assertEquals(1, len(st2))
ts2 = st2[0]