This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/Logtalk/examples/relations/relations.lgt

796 lines
22 KiB
Plaintext
Raw Normal View History

:- protocol(relationp).
:- info([
version is 1.0,
author is 'Paulo Moura',
date is 2000/7/24,
comment is 'Relations between objects protocol.']).
:- private(tuple_/1).
:- dynamic(tuple_/1).
:- mode(tuple_(?list), zero_or_more).
:- info(tuple_/1, [
comment is 'Stores the relation tuples.',
argnames is ['Tuple']]).
:- public(tuple/1).
:- mode(tuple(?list), zero_or_more).
:- info(tuple/1, [
comment is 'Returns a relation tuple.',
argnames is ['Tuple']]).
:- public(tuples/1).
:- mode(tuples(-list), one).
:- info(tuples/1, [
comment is 'Returns a list of all relation tuples.',
argnames is ['Tuples']]).
:- public(add_tuple/1).
:- mode(add_tuple(+list), zero_or_one).
:- info(add_tuple/1, [
comment is 'Adds a new relation tuple.',
argnames is ['Tuple']]).
:- public(remove_tuple/1).
:- mode(remove_tuple(?list), zero_or_more).
:- info(remove_tuple/1, [
comment is 'Removes a matching relation tuple.',
argnames is ['Tuple']]).
:- public(remove_all_tuples/0).
:- mode(remove_all_tuples, one).
:- info(remove_all_tuples/0, [
comment is 'Removes all relation tuples.']).
:- public(number_of_tuples/1).
:- mode(number_of_tuples(-integer), one).
:- info(number_of_tuples/1, [
comment is 'Returns the current number of relation tuples.',
argnames is ['Number']]).
:- public(plays_role_in_tuple/3).
:- mode(plays_role_in_tuple(?object, ?atom, ?list), zero_or_more).
:- info(plays_role_in_tuple/3, [
comment is 'List of tuples where an object plays a role.',
argnames is ['Object', 'Role', 'Tuples']]).
:- public(plays_roles/2).
:- mode(plays_roles(?object, -list), zero_or_more).
:- info(plays_roles/2, [
comment is 'Returns a list of all roles played by an object in the relation tuples.',
argnames is ['Object', 'Roles']]).
:- public(plays_role_n_times/3).
:- mode(plays_role_n_times(?object, ?atom, -integer), zero_or_more).
:- info(plays_role_n_times/3, [
comment is 'Number of times that an object plays a role in the relation tuples.',
argnames is ['Object', 'Role', 'Times']]).
:- private(domain_/2).
:- dynamic(domain_/2).
:- mode(domain_(?atom, ?object), zero_or_more).
:- info(domain_/2, [
comment is 'Table of role domains.',
argnames is ['Role', 'Domain']]).
:- public(domains/1).
:- mode(domains(-list), zero_or_one).
:- info(domains/1, [
comment is 'List of domains for all roles.',
argnames is ['Domains']]).
:- public(domain/2).
:- mode(domain(?atom, ?object), zero_or_more).
:- info(domain/2, [
comment is 'Role domain.',
argnames is ['Role', 'Domain']]).
:- public(set_domains/1).
:- mode(set_domains(+list), zero_or_one).
:- info(set_domains/1, [
comment is 'Set the domains for all roles.',
argnames is ['Domains']]).
:- private(descriptor_/1).
:- dynamic(descriptor_/1).
:- mode(descriptor_(?list), zero_or_one).
:- info(descriptor_/1, [
comment is 'Stores the relation tuple descriptor.',
argnames is ['Descriptor']]).
:- public(descriptor/1).
:- mode(descriptor(?list), zero_or_one).
:- info(descriptor/1, [
comment is 'Returns the relation tuple descriptor.',
argnames is ['Descriptor']]).
:- public(degree/1).
:- mode(degree(?integer), zero_or_one).
:- info(degree/1, [
comment is 'Descriptor length.',
argnames is ['Degree']]).
:- public(set_descriptor/1).
:- mode(set_descriptor(+list), zero_or_one).
:- info(set_descriptor/1, [
comment is 'Sets the relation tuple descriptor.',
argnames is ['Descriptor']]).
:- private(key_/1).
:- dynamic(key_/1).
:- mode(key_(?list), zero_or_more).
:- info(key_/1, [
comment is 'Stores the relation keys.',
argnames is ['Key']]).
:- public(key/1).
:- mode(key(?list), zero_or_more).
:- info(key/1, [
comment is 'Returns a relation key.',
argnames is ['Key']]).
:- public(keys/1).
:- mode(keys(-list), one).
:- info(keys/1, [
comment is 'Returns a list of all relation keys.',
argnames is ['Keys']]).
:- public(set_keys/1).
:- mode(set_keys(+list), zero_or_one).
:- info(set_keys/1, [
comment is 'Sets the relation keys.',
argnames is ['Keys']]).
:- private(delete_option_/2).
:- dynamic(delete_option_/2).
:- mode(delete_option_(?atom, ?atom), zero_or_more).
:- info(delete_option_/2, [
comment is 'Stores role delete options.',
argnames is ['Role', 'Option']]).
:- public(delete_options/1).
:- mode(delete_options(-list), zero_or_one).
:- info(delete_options/1, [
comment is 'Returns a list of all role - delete option pairs.',
argnames is ['Options']]).
:- public(delete_option/2).
:- mode(delete_option(?atom, ?atom), zero_or_more).
:- info(delete_option/2, [
comment is 'Returns role delete options.',
argnames is ['Role', 'Option']]).
:- public(set_delete_options/1).
:- mode(set_delete_options(+list), zero_or_one).
:- info(set_delete_options/1, [
comment is 'Sets the roles delete options.',
argnames is ['Options']]).
:- private(cardinality_/3).
:- dynamic(cardinality_/3).
:- mode(cardinality_(?atom, ?nonvar, ?nonvar), zero_or_more).
:- info(cardinality_/3, [
comment is 'Table of roles minimum and maximum cardinalities.',
argnames is ['Role', 'Min', 'Max']]).
:- public(cardinalities/1).
:- mode(cardinalities(-list), zero_or_one).
:- info(cardinalities/1, [
comment is 'List of minimum and maximum cardinalities of all roles.',
argnames is ['Cardinalities']]).
:- public(cardinality/3).
:- mode(cardinality(?atom, ?nonvar, ?nonvar), zero_or_more).
:- info(cardinality/3, [
comment is 'Role minimum and maximum cardinalities.',
argnames is ['Role', 'Min', 'Max']]).
:- public(set_cardinalities/1).
:- mode(set_cardinalities(+list), zero_or_one).
:- info(cardinalities/1, [
comment is 'Sets the minimum and maximum cardinalities of all roles.',
argnames is ['Cardinalities']]).
:- protected(set_monitors/1).
:- mode(set_monitors(+list), one).
:- protected(del_all_monitors/0).
:- mode(del_all_monitors, one).
:- protected(del_monitors/1).
:- mode(del_monitors(+list), one).
:- protected(restore_monitors/0).
:- mode(restore_monitors, zero_or_one).
:- end_protocol.
:- object(relation,
implements(relationp),
instantiates(class),
specializes(object)).
:- info([
version is 1.2,
date is 2004/8/15,
author is 'Esteban Zimanyi, Paulo Moura',
comment is 'Enables the representation of relations between independent objects.']).
:- uses(before_event_registry).
:- uses(after_event_registry).
:- uses(list,
[length/2, member/2, memberchk/2, nth1/3, same_length/2]).
tuple(Tuple) :-
::tuple_(Tuple).
tuples(Tuples) :-
findall(Tuple, ::tuple_(Tuple), Tuples).
add_tuple(Tuple) :-
\+ ::descriptor(_),
self(Self),
sender(Sender),
throw(error(descriptor_not_defined, Self::add_tuple(Tuple), Sender)).
add_tuple(Tuple) :-
::descriptor(Descriptor),
\+ same_length(Tuple, Descriptor),
self(Self),
sender(Sender),
throw(error(invalid_length, Self::add_tuple(Tuple), Sender)).
add_tuple(Tuple) :-
::descriptor(Descriptor),
::key(Key),
make_tuple_template(Tuple, Descriptor, Key, Template),
::tuple(Template),
self(Self),
sender(Sender),
throw(error(breaks_key(Key), Self::add_tuple(Tuple), Sender)).
add_tuple(Tuple) :-
::descriptor(Descriptor),
nth1(Position, Tuple, Object),
nth1(Position, Descriptor, Role),
::cardinality(Role, _, Maximum),
::plays_role_n_times(Object, Role, Number),
Maximum = Number,
self(Self),
sender(Sender),
throw(error(breaks_max_cardinality(Object, Role, Maximum), Self::add_tuple(Tuple), Sender)).
add_tuple(Tuple) :-
::descriptor(Descriptor),
nth1(Position, Tuple, Object),
nth1(Position, Descriptor, Role),
::domain(Role, Domain),
(Domain::strict_instance ->
\+ Domain::valid(Object)
;
\+ Object::ancestor(Domain)),
self(Self),
sender(Sender),
throw(error(breaks_domain(Object, Role, Domain), Self::add_tuple(Tuple), Sender)).
add_tuple(Tuple) :-
::assertz(tuple_(Tuple)),
::set_monitors(Tuple).
make_tuple_template([], [], _, []).
make_tuple_template([Object| Objects], [Role| Roles], Key, [Var| Rest]) :-
(member(Role, Key) ->
Var = Object
;
true),
make_tuple_template(Objects, Roles, Key, Rest).
remove_tuple(Tuple) :-
\+ ::descriptor(_),
self(Self),
sender(Sender),
throw(error(descriptor_not_defined, Self::remove_tuple(Tuple), Sender)).
remove_tuple(Tuple) :-
::descriptor(Descriptor),
nth1(Position, Tuple, Object),
nth1(Position, Descriptor, Role),
::cardinality(Role, Minimum, _),
::plays_role_n_times(Object, Role, Number),
Minimum = Number,
self(Self),
sender(Sender),
throw(error(breaks_min_cardinality(Object, Role, Minimum), Self::remove_tuple(Tuple), Sender)).
remove_tuple(Tuple) :-
::retract(tuple_(Tuple)),
::del_monitors(Tuple).
remove_all_tuples :-
::retractall(tuple_(_)),
::del_all_monitors.
number_of_tuples(Number) :-
findall(1, ::tuple_(_), List),
length(List, Number).
plays_roles(Object, Roles) :-
::descriptor(Descriptor),
setof(Role,
Tuple^Position^ (::tuple(Tuple),
member(Object, Tuple),
nth1(Position, Tuple, Object),
once(nth1(Position, Descriptor, Role))),
Roles).
plays_role_in_tuple(Object, Role, Tuple) :-
::descriptor(Descriptor),
::tuple(Tuple),
nth1(Position, Tuple, Object),
nth1(Position, Descriptor, Role).
plays_role_n_times(Object, Role, Number) :-
::descriptor(Descriptor),
nth1(Position, Descriptor, Role),
setof(Tuple,
(::tuple(Tuple),
nth1(Position, Tuple, Object)),
Tuples),
length(Tuples, Number).
domains(Domains) :-
::descriptor(Descriptor),
domains(Descriptor, Domains).
domains([], []).
domains([Role| Roles], [Domain| Domains]) :-
::domain_(Role, Domain),
domains(Roles, Domains).
domain(Role, Domain) :-
::domain_(Role, Domain).
set_domains(Domains) :-
\+ ::descriptor(_),
self(Self),
sender(Sender),
throw(error(descriptor_not_defined, Self::set_domains(Domains), Sender)).
set_domains(Domains) :-
::tuple(_),
self(Self),
sender(Sender),
throw(error(non_empty_relation, Self::set_domains(Domains), Sender)).
set_domains(Domains) :-
::descriptor(Descriptor),
set_domains(Domains, Descriptor).
set_domains([], []).
set_domains([Role| Roles], [Domain| Domains]) :-
::retractall(domain_(Role, _)),
::assertz(domain_(Role, Domain)),
set_domains(Roles, Domains).
descriptor(Descriptor) :-
::descriptor_(Descriptor).
degree(Degree) :-
::descriptor_(Descriptor),
length(Descriptor, Degree).
set_descriptor(Descriptor) :-
\+ ::tuple(_),
::assertz(descriptor_(Descriptor)),
::set_keys([Descriptor]),
set_role_defaults(Descriptor).
set_role_defaults([]).
set_role_defaults([Role| Roles]) :-
::set_domain(Role, object),
::set_cardinality(Role, 0, n),
::set_delete_option(Role, cascade),
set_role_defaults(Roles).
key(Key) :-
::key_(Key).
keys(Keys) :-
findall(Key, ::key_(Key), Keys).
set_keys(Keys) :-
\+ ::descriptor(_),
self(Self),
sender(Sender),
throw(error(descriptor_not_defined, Self::set_keys(Keys), Sender)).
set_keys(Keys) :-
::tuple(_),
self(Self),
sender(Sender),
throw(error(non_empty_relation, Self::set_keys(Keys), Sender)).
set_keys(Keys) :-
\+ valid_keys(Keys),
self(Self),
sender(Sender),
throw(error(invalid_key, Self::set_keys(Keys), Sender)).
set_keys(Keys) :-
::retractall(key_(_)),
set_keys2(Keys).
set_keys2([]).
set_keys2([Key| Keys]) :-
::assertz(key_(Key)),
set_keys2(Keys).
valid_keys(Keys) :-
::descriptor(Descriptor),
valid_keys(Keys, Descriptor).
valid_keys([], _).
valid_keys([Key| Keys], Descriptor) :-
forall(
member(Role, Key),
memberchk(Role, Descriptor)),
valid_keys(Keys, Descriptor).
delete_options(Options) :-
::descriptor(Descriptor),
delete_options(Descriptor, Options).
delete_options([], []).
delete_options([Role| Roles], [Option| Options]) :-
::delete_option_(Role, Option),
delete_options(Roles, Options).
delete_option(Role, Option) :-
::delete_option_(Role, Option).
set_delete_options(Options) :-
\+ ::descriptor(_),
self(Self),
sender(Sender),
throw(error(descriptor_not_defined, Self::set_delete_options(Options), Sender)).
set_delete_options(Options) :-
::tuple(_),
self(Self),
sender(Sender),
throw(error(non_empty_relation, Self::set_delete_options(Options), Sender)).
set_delete_options(Options) :-
::descriptor(Descriptor),
\+ same_length(Options, Descriptor),
self(Self),
sender(Sender),
throw(error(invalid_length, Self::set_delete_options(Options), Sender)).
set_delete_options(Options) :-
\+ valid_delete_options(Options),
self(Self),
sender(Sender),
throw(error(invalid_delete_option, Self::set_delete_options(Options), Sender)).
set_delete_options(Options) :-
::descriptor(Descriptor),
set_delete_options(Descriptor, Options).
set_delete_options([], []).
set_delete_options([Role| Roles], [Option| Options]) :-
::retractall(delete_option_(Role, _)),
::assertz(delete_option_(Role, Option)),
set_delete_options(Roles, Options).
valid_delete_options([]).
valid_delete_options([Option| Options]) :-
once((Option = restrict; Option = cascade)),
valid_delete_options(Options).
cardinalities(Cardinalities) :-
::descriptor(Descriptor),
cardinalities(Descriptor, Cardinalities).
cardinalities([], []).
cardinalities([Role| Roles], [(Min, Max)| Cardinalities]) :-
::cardinality_(Role, Min, Max),
cardinalities(Roles, Cardinalities).
cardinality(Role, Min, Max) :-
::cardinality_(Role, Min, Max).
set_cardinalities(Cardinalities) :-
\+ ::descriptor(_),
self(Self),
sender(Sender),
throw(error(descriptor_not_defined, Self::set_cardinalities(Cardinalities), Sender)).
set_cardinalities(Cardinalities) :-
::tuple(_),
self(Self),
sender(Sender),
throw(error(non_empty_relation, Self::set_cardinalities(Cardinalities), Sender)).
set_cardinalities(Cardinalities) :-
\+ valid_cardinalities(Cardinalities),
self(Self),
sender(Sender),
throw(error(invalid_cardinality, Self::set_cardinalities(Cardinalities), Sender)).
set_cardinalities(Cardinalities) :-
::descriptor(Descriptor),
set_cardinalities(Cardinalities, Descriptor).
set_cardinalities([], []).
set_cardinalities([(Min, Max)| Cardinalities], [Role| Roles]) :-
::retractall(cardinality_(Role, _, _)),
::assertz(cardinality_(Role, Min, Max)),
set_cardinalities(Cardinalities, Roles).
valid_cardinalities([]).
valid_cardinalities([Cardinality| Cardinalities]) :-
nonvar(Cardinality),
Cardinality = (Min, Max),
lower_cardinality(Min, Max),
valid_cardinalities(Cardinalities).
lower_cardinality(I, n) :-
integer(I), !.
lower_cardinality(I, J) :-
integer(I),
integer(J),
I < J.
free(Options) :-
::remove_all_tuples,
^^free(Options).
set_monitors([]).
set_monitors([Object| Objects]) :-
(instantiates_class(Object, Class) ->
self(Self),
before_event_registry::set_monitor(Class, delete(Object, _), _, Self)
;
true),
set_monitors(Objects).
del_monitors([]).
del_monitors([Object| Objects]) :-
((instantiates_class(Object, Class),
\+ (::tuple(Other), member(Object, Other))) ->
self(Self),
before_event_registry::del_monitors(Class, delete(Object, _), _, Self)
;
true),
del_monitors(Objects).
del_all_monitors :-
self(Self),
before_event_registry::del_monitors(_, _, _, Self),
after_event_registry::del_monitors(_, _, _, Self).
before(_, delete(Object, Options), _) :-
!,
((::delete_option(Role, restrict),
::plays_role_in_tuple(Object, Role, Tuple)) ->
self(Self),
sender(Sender),
throw(error(can_not_be_deleted(Tuple, Object, Role), Self::delete(Object, Options), Sender))
;
forall(
::plays_role_in_tuple(Object, Role, Tuple),
::remove_tuple(Tuple))).
before(_, _, _).
after(_, _, _).
restore_monitors :-
self(Self),
before_event_registry::del_monitors(_, _, _, Self),
after_event_registry::del_monitors(_, _, _, Self),
forall(::tuple(Tuple), ::set_monitors(Tuple)).
print :-
::descriptor(Descriptor),
write('descriptor:'), nl, write(' '), writeq(Descriptor), nl,
::domains(Domains),
write('domains:'), nl, write(' '), writeq(Domains), nl,
::cardinalities(Cardinalities),
write('cardinalities:'), nl, write(' '), writeq(Cardinalities), nl,
::delete_options(Options),
write('delete options:'), nl, write(' '), writeq(Options), nl,
write('keys:'), nl,
forall(::key(Key), (write(' '), writeq(Key), nl)),
write('tuples:'), nl,
forall(::tuple(Tuple), (write(' '), writeq(Tuple), nl)).
:- end_object.
:- 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.