218 lines
7.1 KiB
Python
218 lines
7.1 KiB
Python
#
|
|
# Copyright (c) 2007 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
|
|
#
|
|
|
|
"""
|
|
Adapters for IConcept providing interfaces from the
|
|
cybertools.knowledge package.
|
|
|
|
$Id$
|
|
"""
|
|
|
|
from zope import interface, component
|
|
from zope.app import zapi
|
|
from zope.component import adapts
|
|
from zope.interface import implements
|
|
from zope.cachedescriptors.property import Lazy
|
|
|
|
from cybertools.typology.interfaces import IType
|
|
from cybertools.knowledge.interfaces import IKnowledgeElement, IKnowledgeProvider
|
|
from cybertools.knowledge.knowing import Knowing
|
|
from loops.common import ParentRelationSetProperty, ChildRelationSetProperty
|
|
from loops.interfaces import IConcept, IResource
|
|
from loops.i18n.common import I18NAdapterBase
|
|
from loops.knowledge.interfaces import IPerson, ITask, ITopic
|
|
from loops.organize.party import Person as BasePerson
|
|
from loops.organize.task import Task as BaseTask
|
|
from loops.common import AdapterBase
|
|
from loops.type import TypeInterfaceSourceList
|
|
|
|
|
|
# register type interfaces - (TODO: use a function for this)
|
|
|
|
TypeInterfaceSourceList.typeInterfaces += (IPerson, ITopic, IKnowledgeElement,
|
|
ITask, IKnowledgeProvider)
|
|
|
|
|
|
class KnowledgeAdapterMixin(object):
|
|
|
|
@Lazy
|
|
def conceptManager(self):
|
|
return self.context.getLoopsRoot().getConceptManager()
|
|
|
|
@Lazy
|
|
def standardPred(self):
|
|
return self.conceptManager.getDefaultPredicate()
|
|
|
|
@Lazy
|
|
def dependsPred(self):
|
|
return self.conceptManager['depends']
|
|
|
|
@Lazy
|
|
def knowsPred(self):
|
|
return self.conceptManager['knows']
|
|
|
|
@Lazy
|
|
def requiresPred(self):
|
|
return self.conceptManager['requires']
|
|
|
|
@Lazy
|
|
def providesPred(self):
|
|
return self.conceptManager['provides']
|
|
|
|
def __eq__(self, other):
|
|
return self.context == other.context
|
|
|
|
|
|
class Person(BasePerson, Knowing, KnowledgeAdapterMixin):
|
|
""" A typeInterface adapter for concepts of type 'person', including
|
|
knowledge/learning management features.
|
|
"""
|
|
|
|
_adapterAttributes = BasePerson._adapterAttributes + ('knowledge',)
|
|
_noexportAttributes = ('knowledge',)
|
|
|
|
knowledge = ParentRelationSetProperty('knows')
|
|
|
|
implements(IPerson)
|
|
|
|
def getKnowledge(self):
|
|
return (IKnowledgeElement(c)
|
|
for c in self.context.getParents((self.knowsPred,)))
|
|
|
|
def knows(self, obj):
|
|
self.context.assignParent(obj.context, self.knowsPred)
|
|
|
|
def removeKnowledge(self, obj):
|
|
self.context.deassignParent(obj.context, (self.knowsPred,))
|
|
|
|
|
|
class Topic(I18NAdapterBase, KnowledgeAdapterMixin):
|
|
""" A typeInterface adapter for concepts of type 'topic' that
|
|
may act as a knowledge element.
|
|
"""
|
|
|
|
implements(ITopic)
|
|
_adapterAttributes = I18NAdapterBase._adapterAttributes + ('parent',)
|
|
|
|
def getParent(self):
|
|
parents = self.context.getParents((self.standardPred,))
|
|
return parents and IKnowledgeElement(parents[0]) or None
|
|
def setParent(self, obj):
|
|
old = self.getParent()
|
|
if old is not None and old.context != self.context:
|
|
self.context.deassignParent(old.context, (self.standardPred,))
|
|
self.context.assignParent(obj.context, self.standardPred)
|
|
parent = property(getParent, setParent)
|
|
|
|
def getDependencies(self):
|
|
return (IKnowledgeElement(c)
|
|
for c in self.context.getParents((self.dependsPred,)))
|
|
|
|
def dependsOn(self, obj):
|
|
self.context.assignParent(obj.context, self.dependsPred)
|
|
|
|
def removeDependency(self, obj):
|
|
self.context.deassignParent(obj.context, (self.dependsPred,))
|
|
|
|
def getDependents(self):
|
|
return (IKnowledgeElement(c)
|
|
for c in self.context.getChildren((self.dependsPred,)))
|
|
|
|
def getKnowers(self):
|
|
return (IPerson(c)
|
|
for c in self.context.getChildren((self.knowsPred,)))
|
|
|
|
def getProviders(self):
|
|
return (IKnowledgeProvider(c)
|
|
for c in self.context.getChildren((self.providesPred,))
|
|
+ self.context.getResources((self.providesPred,)))
|
|
|
|
|
|
class Task(BaseTask, KnowledgeAdapterMixin):
|
|
""" A typeInterface adapter for concepts of type 'task' that
|
|
may act as a knowledge requirement profile.
|
|
"""
|
|
|
|
implements(ITask)
|
|
|
|
_adapterAttributes = BasePerson._adapterAttributes + ('requirements',)
|
|
_noexportAttributes = ('requirements',)
|
|
|
|
requirements = ParentRelationSetProperty('requires')
|
|
|
|
def getRequirements(self):
|
|
return (IKnowledgeElement(c)
|
|
for c in self.context.getParents((self.requiresPred,)))
|
|
|
|
def requires(self, obj):
|
|
self.context.assignParent(obj.context, self.requiresPred)
|
|
|
|
def removeRequirement(self, obj):
|
|
self.context.deassignParent(obj.context, (self.requiresPred,))
|
|
|
|
def getCandidates(self):
|
|
result = []
|
|
candidates = []
|
|
reqs = list(self.requirements)
|
|
for req in reqs:
|
|
for p in req.getKnowers():
|
|
if p not in candidates:
|
|
candidates.append(p)
|
|
item = dict(person=p, required=[], other=[], fit=0.0)
|
|
for k in p.knowledge:
|
|
if k in reqs:
|
|
item['required'].append(k)
|
|
item['fit'] += 1.0
|
|
else:
|
|
item['other'].append(k)
|
|
result.append(item)
|
|
for item in result:
|
|
item['fit'] = round(item['fit'] / len(reqs), 2)
|
|
return sorted(result, key=lambda x: (-x['fit'], x['person'].title))
|
|
|
|
|
|
class ConceptKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
|
|
|
|
implements(IKnowledgeProvider)
|
|
|
|
def getProvidedKnowledge(self):
|
|
return (IKnowledgeElement(c)
|
|
for c in self.context.getParents((self.providesPred,)))
|
|
|
|
def provides(self, obj):
|
|
self.context.assignParent(obj.context, self.providesPred)
|
|
|
|
def removeProvidedKnowledge(self, obj):
|
|
self.context.deassignParent(obj.context, (self.providesPred,))
|
|
|
|
|
|
class ResourceKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
|
|
|
|
implements(IKnowledgeProvider)
|
|
adapts(IResource)
|
|
|
|
def getProvidedKnowledge(self):
|
|
return (IKnowledgeElement(c)
|
|
for c in self.context.getConcepts((self.providesPred,)))
|
|
|
|
def provides(self, obj):
|
|
self.context.assignConcept(obj.context, self.providesPred)
|
|
|
|
def removeProvidedKnowledge(self, obj):
|
|
self.context.deassignConcept(obj.context, (self.providesPred,))
|
|
|