示例#1
0
def duplicate(link, obj):
    """Create duplicate link from obj to link.target."""
    obj_links = IRelationshipLinks(obj)

    for olink in obj_links:
        if (olink.target is link.target and olink.role_hash == link.role_hash
                and olink.rel_type_hash == link.rel_type_hash):
            raise DuplicateRelationship

    shared = OOBTree()
    for key, val in link.shared.items():
        shared[key] = val
    zope.event.notify(
        BeforeRelationshipEvent(link.rel_type, (obj, link.my_role),
                                (link.target, link.role), shared))
    uri_cache = getURICache()
    uri_cache.cache(link.rel_type)
    uri_cache.cache(link.my_role)
    uri_cache.cache(link.role)
    link_a = Link(link.my_role, link.target, link.role, link.rel_type, shared)
    IRelationshipLinks(obj).add(link_a)
    link_b = Link(link.role, obj, link.my_role, link.rel_type, shared)
    IRelationshipLinks(link.target).add(link_b)
    zope.event.notify(
        RelationshipAddedEvent(link.rel_type, (obj, link.my_role),
                               (link.target, link.role), shared))
示例#2
0
 def state(self, other):
     links = IRelationshipLinks(self.this)
     try:
         link = links.find(self.my_role, other, self.other_role, self.rel_type)
     except ValueError:
         return None
     return link.state
示例#3
0
    def build(self, context):
        int_ids = getUtility(IIntIds)
        schedule_calendars = set()
        calendar = getScheduleCalendar(self.calendar.__parent__)
        if calendar is None:
            return

        schedule_calendars.add(calendar)

        for event in self.events:
            schedule = context.shared.schedule_map.get(event['timetable_key'])
            if schedule is None:
                continue

            period = context.shared.period_map[event['period_key']]
            owner_int_id = int(schedule.__parent__.__name__)
            owner = int_ids.getObject(owner_int_id)

            calendar = getScheduleCalendar(owner)
            if calendar is None:
                continue

            if calendar not in schedule_calendars:
                schedule_calendars.add(calendar)

            new_event = self.findEvent(calendar, period, event['dtstart'],
                                       event['duration'])
            if new_event is not None:
                new_event.description = event['description']
                new_event.location = event['location']
                for resource in event['resources']:
                    if resource not in new_event.resources:
                        new_event.bookResource(resource)

        # XXX: maybe copy over old "free" section events here

        schedule_cal_relationships = [(cal, IRelationshipLinks(cal))
                                      for cal in schedule_calendars]

        old_relationships = IRelationshipLinks(self.calendar)
        old_subscriptions = list(
            old_relationships.getLinksByRole(URICalendarSubscriber))

        for link in old_subscriptions:
            old_info = link.extra_info
            for schedule_cal, relationships in schedule_cal_relationships:
                info = CalendarOverlayInfo(schedule_cal, old_info.show,
                                           old_info.color1, old_info.color2)
                info.__parent__ = old_info.__parent__
                try:
                    relationships.find(link.my_role, link.target, link.role,
                                       link.rel_type)
                except ValueError:
                    relate(link.rel_type, (schedule_cal, link.my_role),
                           (link.target, link.role),
                           extra_info=info)

        for link in old_subscriptions:
            unrelate(link.rel_type, (self.calendar, link.my_role),
                     (link.target, link.role))
示例#4
0
 def state(self, other):
     links = IRelationshipLinks(self.this)
     try:
         link = links.find(self.my_role, other, self.other_role,
                           self.rel_type)
     except ValueError:
         return None
     return link.state
示例#5
0
 def __nonzero__(self):
     linkset = IRelationshipLinks(self.this)
     iterator = iter(linkset.iterLinksByRole(self.other_role, self.rel_type))
     try:
         iterator.next()
     except StopIteration:
         return False
     else:
         return True
示例#6
0
 def __nonzero__(self):
     linkset = IRelationshipLinks(self.this)
     iterator = iter(linkset.iterLinksByRole(self.other_role,
                                             self.rel_type))
     try:
         iterator.next()
     except StopIteration:
         return False
     else:
         return True
示例#7
0
 def __contains__(self, other):
     if other is None:
         return False
     linkset = IRelationshipLinks(self.this)
     for link in linkset.getCachedLinksByTarget(other):
         if (link.rel_type_hash == hash(self.rel_type) and
             link.my_role_hash == hash(self.my_role) and
             link.role_hash == hash(self.other_role) and
             self._filter(link)):
             return True
     return False
示例#8
0
 def __contains__(self, other):
     if other is None:
         return False
     linkset = IRelationshipLinks(self.this)
     for link in linkset.getCachedLinksByTarget(other):
         if (link.rel_type_hash == hash(self.rel_type)
                 and link.my_role_hash == hash(self.my_role)
                 and link.role_hash == hash(self.other_role)
                 and self._filter(link)):
             return True
     return False
示例#9
0
 def __contains__(self, other):
     if other is None:
         return False
     other = removeSecurityProxy(other)
     linkset = IRelationshipLinks(self.this)
     filter = self.rel_type.filter
     for link in linkset.getCachedLinksByTarget(other):
         if (link.my_role_hash == hash(self.my_role)
                 and link.role_hash == hash(self.other_role)
                 and filter(link)):
             return True
     return False
示例#10
0
 def relate(self, other, meaning=ACTIVE, code=ACTIVE_CODE):
     links = IRelationshipLinks(self.this)
     try:
         link = links.find(self.my_role, other, self.other_role, self.rel_type)
     except ValueError:
         relate(self.rel_type,
                (self.this, self.my_role),
                (other, self.other_role))
         link = links.find(self.my_role, other, self.other_role, self.rel_type)
     link.state.set(self.filter_date, meaning=meaning, code=code)
     notify(LinkStateModifiedEvent(
             link, self.this, other, self.filter_date, meaning, code))
示例#11
0
 def __contains__(self, other):
     if other is None:
         return False
     other = removeSecurityProxy(other)
     linkset = IRelationshipLinks(self.this)
     filter = self.rel_type.filter
     for link in linkset.getCachedLinksByTarget(other):
         if (link.my_role_hash == hash(self.my_role) and
             link.role_hash == hash(self.other_role) and
             filter(link)):
             return True
     return False
示例#12
0
 def relate(self, other, meaning=ACTIVE, code=ACTIVE_CODE):
     links = IRelationshipLinks(self.this)
     try:
         link = links.find(self.my_role, other, self.other_role,
                           self.rel_type)
     except ValueError:
         relate(self.rel_type, (self.this, self.my_role),
                (other, self.other_role))
         link = links.find(self.my_role, other, self.other_role,
                           self.rel_type)
     link.state.set(self.filter_date, meaning=meaning, code=code)
     notify(
         LinkStateModifiedEvent(link, self.this, other, self.filter_date,
                                meaning, code))
示例#13
0
def evolveRelationships(date, target, rel_type, other_role, new_type):
    int_ids = getUtility(IIntIds)
    links = IRelationshipLinks(target).iterLinksByRole(other_role)
    for link in links:
        link = int_ids.getObject(link.lid)
        if link.rel_type != rel_type:
            continue
        backlink = IRelationshipLinks(link.target).find(
            link.role, target, link.my_role, link.rel_type)
        link.rel_type = backlink.rel_type = new_type
        if 'tmp' not in link.shared:
            link.shared['tmp'] = ()
        link.state.set(date)
        notify(ObjectModifiedEvent(link))
        notify(ObjectModifiedEvent(backlink))
示例#14
0
 def getLinks(self):
     links_1 = IRelationshipLinks(self.participant1)
     links_2 = IRelationshipLinks(self.participant2)
     try:
         link_1_to_2 = links_1.find(
             self.role1, self.participant2, self.role2,
             self.rel_type)
     except ValueError:
         raise NoSuchRelationship
     try:
         link_2_to_1 = links_2.find(
             self.role2, self.participant1, self.role1,
             self.rel_type)
     except ValueError:
         raise NoSuchRelationship
     return link_1_to_2, link_2_to_1
示例#15
0
 def relationships(self, **party):
     other_role = self.getPartyRole(**party)
     obj = party.values()[0]
     links = IRelationshipLinks(obj).iterLinksByRole(other_role,
                                                     rel_type=self.rel_type)
     for link in links:
         yield RelationshipInfo(obj, link)
示例#16
0
def unrelateOnDeletion(event):
    """Remove all relationships when an object is deleted."""
    if not IObjectRemovedEvent.providedBy(event):
        return
    linkset = IRelationshipLinks(event.object, None)
    if linkset is not None:
        # event.object may be a ContainedProxy
        unrelateAll(getProxiedObject(event.object))
示例#17
0
 def unrelate(self, other):
     """Delete state on filtered date or unrelate completely if
     no states left or filtered date is .all()
     """
     links = IRelationshipLinks(self.this)
     link = links.find(self.my_role, other, self.other_role, self.rel_type)
     if self.filter_date is None:
         unrelate(self.rel_type, (self.this, self.my_role),
                  (other, self.other_role))
         return
     state = link.state
     date = state.closest(self.filter_date)
     if date is None:
         raise KeyError(self.filter_date)
     del state[date]
     try:
         iter(state).next()
     except StopIteration:
         unrelate(self.rel_type, (self.this, self.my_role),
                  (other, self.other_role))
示例#18
0
def unrelateCalendarOnDeletion(event):
    """When you delete an object, relationships of it's calendar should be removed

        >>> from schooltool.relationship.tests import setUp, tearDown
        >>> from schooltool.testing.setup import setUpCalendaring

        >>> setUp()
        >>> setUpCalendaring()

        >>> import zope.event
        >>> old_subscribers = zope.event.subscribers[:]
        >>> from schooltool.app.overlay import unrelateCalendarOnDeletion
        >>> zope.event.subscribers.append(unrelateCalendarOnDeletion)


    We will need some object that implements IHaveCalendar for that:

        >>> from zope.container.btree import BTreeContainer
        >>> container = BTreeContainer()
        >>> from schooltool.person.person import Person
        >>> container = BTreeContainer()
        >>> container['jonas'] = jonas = Person(username="******")
        >>> container['petras'] = petras =  Person(username="******")

    Let's add calendar of Petras to the list of overlaid calendars:

        >>> jonas.overlaid_calendars.add(ISchoolToolCalendar(petras))
        <...CalendarOverlayInfo object at ...>
        >>> list(jonas.overlaid_calendars)
        [<schooltool.app.overlay.CalendarOverlayInfo object at ...>]

    If we delete Petras - Jonas should have no calendars in his overlay list:

        >>> del container['petras']
        >>> list(jonas.overlaid_calendars)
        []

    Restore old subscribers:

        >>> zope.event.subscribers[:] = old_subscribers
        >>> tearDown()

    """
    if not IObjectRemovedEvent.providedBy(event):
        return
    # event.object may be a ContainedProxy
    obj = getProxiedObject(event.object)
    if not IHaveCalendar.providedBy(obj):
        return
    calendar = ISchoolToolCalendar(obj)
    linkset = IRelationshipLinks(calendar, None)
    if linkset is not None:
        unrelateAll(calendar)
示例#19
0
 def unrelate(self, other):
     """Delete state on filtered date or unrelate completely if
     no states left or filtered date is .all()
     """
     links = IRelationshipLinks(self.this)
     link = links.find(self.my_role, other, self.other_role, self.rel_type)
     if self.filter_date is None:
         unrelate(self.rel_type,
                  (self.this, self.my_role),
                  (other, self.other_role))
         return
     state = link.state
     date = state.closest(self.filter_date)
     if date is None:
         raise KeyError(self.filter_date)
     del state[date]
     try:
         iter(state).next()
     except StopIteration:
         unrelate(self.rel_type,
                  (self.this, self.my_role),
                  (other, self.other_role))
示例#20
0
def unrelateAll(obj):
    """Break all relationships of `obj`.

    Note that this operation is not atomic: if an event subscriber catches
    a BeforeRemovingRelationshipEvent and vetoes the operation, some
    relationships may have been removed, while others may still be there.
    """
    links_of_a = IRelationshipLinks(obj)
    relationships = [(link.rel_type, (obj, link.my_role),
                      (link.target, link.role)) for link in links_of_a]
    for args in relationships:
        try:
            unrelate(*args)
        except NoSuchRelationship:
            pass  # it was a loop, so we tried to delete it twice
    return
示例#21
0
 def getLinks(self):
     links_1 = IRelationshipLinks(self.participant1)
     links_2 = IRelationshipLinks(self.participant2)
     try:
         link_1_to_2 = links_1.find(self.role1, self.participant2,
                                    self.role2, self.rel_type)
     except ValueError:
         raise NoSuchRelationship
     try:
         link_2_to_1 = links_2.find(self.role2, self.participant1,
                                    self.role1, self.rel_type)
     except ValueError:
         raise NoSuchRelationship
     return link_1_to_2, link_2_to_1
示例#22
0
def unrelateOnCopy(event):
    """Remove all relationships when an object is copied."""
    if not IObjectCopiedEvent.providedBy(event):
        return
    # event.object may be a ContainedProxy
    obj = getProxiedObject(event.object)
    linkset = IRelationshipLinks(obj, None)
    if linkset is not None:
        links_to_remove = []
        for link in linkset:
            other_linkset = IRelationshipLinks(link.target)
            try:
                other_linkset.find(link.role, obj, link.my_role, link.rel_type)
            except ValueError:
                # The corresponding other link was not copied, so we have a
                # degenerate one-sided relationship.  Let's remove it
                # altogether.  It would not difficult to have a different
                # function, cloneRelationshipsOnCopy, that would create
                # a corresponding link in other_linkset.
                links_to_remove.append(link)
        for link in links_to_remove:
            linkset.remove(link)
示例#23
0
def iterRelatedObjects(obj, role, rel_type=None, catalog=None):
    """Return all objects related to `obj` with a given role."""
    return IRelationshipLinks(obj).iterTargetsByRole(role,
                                                     rel_type,
                                                     catalog=catalog)
    def build(self, context):
        int_ids = getUtility(IIntIds)
        schedule_calendars = set()
        calendar = getScheduleCalendar(self.calendar.__parent__)
        if calendar is None:
            return

        schedule_calendars.add(calendar)

        for event in self.events:
            schedule = context.shared.schedule_map.get(event['timetable_key'])
            if schedule is None:
                continue

            period = context.shared.period_map[event['period_key']]
            owner_int_id = int(schedule.__parent__.__name__)
            owner = int_ids.getObject(owner_int_id)

            calendar = getScheduleCalendar(owner)
            if calendar is None:
                continue

            if calendar not in schedule_calendars:
                schedule_calendars.add(calendar)

            new_event = self.findEvent(
                calendar, period, event['dtstart'], event['duration'])
            if new_event is not None:
                new_event.description = event['description']
                new_event.location = event['location']
                for resource in event['resources']:
                    if resource not in new_event.resources:
                        new_event.bookResource(resource)

        # XXX: maybe copy over old "free" section events here

        schedule_cal_relationships = [
            (cal, IRelationshipLinks(cal)) for cal in schedule_calendars]

        old_relationships = IRelationshipLinks(self.calendar)
        old_subscriptions = list(
            old_relationships.getLinksByRole(URICalendarSubscriber))

        for link in old_subscriptions:
            old_info = link.extra_info
            for schedule_cal, relationships in schedule_cal_relationships:
                info = CalendarOverlayInfo(schedule_cal, old_info.show,
                                           old_info.color1, old_info.color2)
                info.__parent__ = old_info.__parent__
                try:
                    relationships.find(
                        link.my_role, link.target, link.role, link.rel_type)
                except ValueError:
                    relate(link.rel_type,
                           (schedule_cal, link.my_role),
                           (link.target, link.role),
                           extra_info = info)

        for link in old_subscriptions:
            unrelate(link.rel_type,
                     (self.calendar, link.my_role),
                     (link.target, link.role))
示例#25
0
 def int_ids(self):
     int_ids = getUtility(IIntIds)
     linkset = IRelationshipLinks(self.this)
     for link in linkset.iterLinksByRole(self.other_role, self.rel_type):
         yield int_ids.getId(LinkTargetKeyReference(link))
示例#26
0
 def __len__(self):
     count = 0
     linkset = IRelationshipLinks(self.this)
     for i in linkset.iterLinksByRole(self.other_role, self.rel_type):
         count += 1
     return count
示例#27
0
    def __contains__(self, key):
        return (self.lid, key) in self.catalog['shared']

    def __getitem__(self, key):
        return self.catalog['shared'].get(self.lid, key)

    def __setitem__(self, key, value):
        link = getUtility(IIntIds).getObject(self.lid)
        link.shared[key] = value
        notify(ObjectModifiedEvent(link))


def relate(rel_type, (a, role_of_a), (b, role_of_b), extra_info=None):
    """Establish a relationship between objects `a` and `b`."""
    for link in IRelationshipLinks(a):
        if (link.target is b and link.role_hash == hash(role_of_b)
                and link.rel_type_hash == hash(rel_type)):
            raise DuplicateRelationship
    shared = OOBTree()
    shared['X'] = extra_info
    zope.event.notify(
        BeforeRelationshipEvent(rel_type, (a, role_of_a), (b, role_of_b),
                                shared))
    uri_cache = getURICache()
    uri_cache.cache(rel_type)
    uri_cache.cache(role_of_a)
    uri_cache.cache(role_of_b)
    link_a = Link(role_of_a, b, role_of_b, rel_type, shared)
    IRelationshipLinks(a).add(link_a)
    link_b = Link(role_of_b, a, role_of_a, rel_type, shared)
示例#28
0
 def relationships(self):
     links = IRelationshipLinks(self.this).iterLinksByRole(
         self.other_role, rel_type=self.rel_type)
     for link in links:
         yield RelationshipInfo(self.this, link)
示例#29
0
 def __iter__(self):
     for link in IRelationshipLinks(self.this):
         if link.role == self.other_role and link.rel_type == self.rel_type:
             yield link.extra_info
示例#30
0
 def int_ids(self):
     int_ids = getUtility(IIntIds)
     linkset = IRelationshipLinks(self.this)
     for link in linkset.iterLinksByRole(self.other_role, self.rel_type):
         yield int_ids.getId(LinkTargetKeyReference(link))
示例#31
0
 def __len__(self):
     count = 0
     linkset = IRelationshipLinks(self.this)
     for i in linkset.iterLinksByRole(self.other_role, self.rel_type):
         count += 1
     return count
示例#32
0
    uri_cache.cache(link.rel_type)
    uri_cache.cache(link.my_role)
    uri_cache.cache(link.role)
    link_a = Link(link.my_role, link.target, link.role, link.rel_type, shared)
    IRelationshipLinks(obj).add(link_a)
    link_b = Link(link.role, obj, link.my_role, link.rel_type, shared)
    IRelationshipLinks(link.target).add(link_b)
    zope.event.notify(RelationshipAddedEvent(link.rel_type,
                                             (obj, link.my_role),
                                             (link.target, link.role),
                                             shared))


def unrelate(rel_type, (a, role_of_a), (b, role_of_b)):
    """Break a relationship between objects `a` and `b`."""
    links_of_a = IRelationshipLinks(a)
    links_of_b = IRelationshipLinks(b)
    try:
        link_a_to_b = links_of_a.find(role_of_a, b, role_of_b, rel_type)
    except ValueError:
        raise NoSuchRelationship
    extra_info = link_a_to_b.extra_info
    zope.event.notify(BeforeRemovingRelationshipEvent(rel_type,
                                                      (a, role_of_a),
                                                      (b, role_of_b),
                                                      extra_info))
    links_of_a.remove(link_a_to_b)
    # If links_of_b.find raises a ValueError, our data structures are out of
    # sync.
    link_b_to_a = links_of_b.find(role_of_b, a, role_of_a, rel_type)
    links_of_b.remove(link_b_to_a)
示例#33
0
 def _iter_filtered_links(self):
     links = IRelationshipLinks(self.this).getCachedLinksByRole(
         self.other_role)
     for link in links:
         if self._filter(link):
             yield link