:- object(constrained_relation, instantiates(class), specializes(relation)). :- info([ version is 3.2, date is 2005/1/29, author is 'Paulo Moura', comment is 'Enables the representation of relations with constraints on the state of participating objects.']). :- uses(list, [member/2, memberchk/2, subtract/3]). :- private(activ_points_/3). :- dynamic(activ_points_/3). :- mode(activ_points_(?atom, ?event, -list), zero_or_more). :- public(activ_point/3). :- mode(activ_point(?atom, ?event, ?callable), zero_or_more). :- public(activ_points/3). :- mode(activ_points(?atom, ?event, -list), zero_or_more). :- public(set_activ_points/3). :- mode(set_activ_points(+atom, +event, +list), one). :- protected(unique_messages/4). :- mode(unique_messages(+list, +atom, +event, -list), one). :- protected(propagate/5). :- mode(propagate(+atom, +callable, +object, +atom, +list), zero_or_one). before(Object, Message, Sender) :- self(Self), (Self \= Sender -> forall( (::activ_point(Role, before, Message), ::plays_role_in_tuple(Object, Role, Tuple)), ::propagate(before, Message, Object, Role, Tuple)) ; true), ^^before(Object, Message, Sender). after(Object, Message, Sender) :- self(Self), (Self \= Sender -> forall( (::activ_point(Role, after, Message), ::plays_role_in_tuple(Object, Role, Tuple)), ::propagate(after, Message, Object, Role, Tuple)) ; true), ^^after(Object, Message, Sender). set_monitors(Tuple) :- ^^set_monitors(Tuple), ::descriptor(Descriptor), set_monitors(Tuple, Descriptor). set_monitors([], []). set_monitors([Object| Objects], [Role| Roles]) :- once(::activ_points(Role, before, Messages1)), % avoid spurious backtracking set_object_before_monitors(Messages1, Object), once(::activ_points(Role, after, Messages2)), % avoid spurious backtracking set_object_after_monitors(Messages2, Object), set_monitors(Objects, Roles). set_object_before_monitors([], _). set_object_before_monitors([Message| Messages], Object) :- self(Self), before_event_registry::set_monitor(Object, Message, _, Self), set_object_before_monitors(Messages, Object). set_object_after_monitors([], _). set_object_after_monitors([Message| Messages], Object) :- self(Self), after_event_registry::set_monitor(Object, Message, _, Self), set_object_after_monitors(Messages, Object). del_monitors(Tuple) :- ^^del_monitors(Tuple), ::descriptor(Descriptor), del_monitors(Tuple, Descriptor). del_monitors([], []). del_monitors([Object| Objects], [Role| Roles]) :- del_object_monitors(Object, Role), del_monitors(Objects, Roles). del_object_monitors(Object, Role) :- ::plays_roles(Object, Roles) -> (member(Role, Roles) -> true ; del_object_monitors(Object, Role, Roles)) ; del_object_monitors(Object, Role, []). del_object_monitors(Object, Role, Roles) :- ::unique_messages(Roles, Role, before, Messages1), del_object_before_monitors(Messages1, Object), ::unique_messages(Roles, Role, after, Messages2), del_object_after_monitors(Messages2, Object). del_object_before_monitors([], _). del_object_before_monitors([Message| Messages], Object) :- self(Self), before_event_registry::del_monitors(Object, Message, _, Self), del_object_before_monitors(Messages, Object). del_object_after_monitors([], _). del_object_after_monitors([Message| Messages], Object) :- self(Self), after_event_registry::del_monitors(Object, Message, _, Self), del_object_after_monitors(Messages, Object). propagate(Event, Message, Object, Role, Tuple) :- self(Self), sender(Sender), throw(error(desc_responsibility, Self::propagate(Event, Message, Object, Role, Tuple), Sender)). activ_point(Role, Event, Message) :- ::activ_points_(Role, Event, Messages), member(Message, Messages). activ_points(Role, Event, List) :- ::activ_points_(Role, Event, List). set_activ_points(Role, Event, List) :- \+ ::descriptor(_), self(Self), sender(Sender), throw(error(descriptor_not_defined, Self::set_activ_points(Role, Event, List), Sender)). set_activ_points(Role, Event, List) :- ::descriptor(Descriptor), memberchk(Role, Descriptor), ::retractall(activ_points_(Role, Event, _)), ::assertz(activ_points_(Role, Event, List)). unique_messages(Roles, Role, Event, Messages) :- ::activ_points_(Role, Event, Original), filter_messages(Roles, Original, Event, Messages). filter_messages([], Messages, _, Messages). filter_messages([Role| Roles], Original, Event, Messages) :- ::activ_points_(Role, Event, Excluded), subtract(Original, Excluded, Rest), filter_messages(Roles, Rest, Event, Messages). set_descriptor(Descriptor) :- ^^set_descriptor(Descriptor), set_default_activ_points(Descriptor). set_default_activ_points([]). set_default_activ_points([Role| Roles]) :- ::set_activ_points(Role, before, []), ::set_activ_points(Role, after, []), set_default_activ_points(Roles). print :- ^^print, ::descriptor(Descriptor), write('call activation points:'), nl, findall(Messages, (member(Role, Descriptor), ::activ_points(Role, before, Messages)), CallList), write(' '), writeq(CallList), nl, write('exit activation points:'), nl, findall(Messages, (member(Role, Descriptor), ::activ_points(Role, after, Messages)), ExitList), write(' '), writeq(ExitList), nl. :- end_object.