:- object(relation, implements(relationp), instantiates(class), specializes(object)). :- info([ version is 1.1, date is 2004/5/9, 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). 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), \+ list::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), list::nth1(Position, Tuple, Object), list::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), list::nth1(Position, Tuple, Object), list::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]) :- (list::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), list::nth1(Position, Tuple, Object), list::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), list::length(List, Number). plays_roles(Object, Roles) :- ::descriptor(Descriptor), setof(Role, Tuple^Position^ (::tuple(Tuple), list::member(Object, Tuple), list::nth1(Position, Tuple, Object), once(list::nth1(Position, Descriptor, Role))), Roles). plays_role_in_tuple(Object, Role, Tuple) :- ::descriptor(Descriptor), ::tuple(Tuple), list::nth1(Position, Tuple, Object), list::nth1(Position, Descriptor, Role). plays_role_n_times(Object, Role, Number) :- ::descriptor(Descriptor), list::nth1(Position, Descriptor, Role), setof(Tuple, (::tuple(Tuple), list::nth1(Position, Tuple, Object)), Tuples), list::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), list::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( list::member(Role, Key), list::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), \+ list::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), list::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.