%Metamodel A

%(1) All attributes of a data have distint names 

attribute_distinct_names:-rdf(Data,mmA:'data.attr_of',Att1),
						rdf(Data,mmA:'data.attr_of',Att2),
						Att1\=Att2,
						rdf(Att1,mmA:'attribute.name',Name1),
						rdf(Att2,mmA:'attribute.name',Name2),
						Name1=Name2.
						
%(2) Each data has a key attribute

exists_key:-setof(Att,(rdf(_,mmA:'data.attr_of',Att),rdf(Att,mmA:'attribute.key',literal(type(_,true)))),Keys),Keys=[].

%(3) Each data has a unique key attribute 

unique_key :- rdf(Data,mmA:'data.attr_of',Att1),
			rdf(Data,mmA:'data.attr_of',Att2),
			Att1\=Att2,
			rdf(Att1,mmA:'attribute.key',literal(type(_,true))),
			rdf(Att2,mmA:'attribute.key',literal(type(_,true))).

%(4) Each attribute is associated to exactly one data 

unique_data_attribute:-rdf(Att,rdf:type,mmA:attribute),
			rdf(Att,mmA:'attribute.is',Data1),
			rdf(Att,mmA:'attribute.is',Data2),
			Data1\=Data2.



%(5) Each data is contained in exactly one store

unique_store_data:- setof(Store,rdf(_,mmA:'data.contained_in',Store),Stores),Stores=[_,_|_].


%(6) All data have distinct names

unique_name_data :- rdf(Data,mmA:'data.name',Name1),
					rdf(Data,mmA:'data.name',Name2),
					Name1\=Name2.

%(7) All data have distinct containers

unique_container_data :-rdf(Data,mmA:'data.container',Container1),
				rdf(Data,mmA:'data.container',Container2),
				Container1\=Container2.


%(8) Each qualifier is associated to exactly one role

unique_role_qualifier :- rdf(Qualifier,mmA:'qualifier.has',Role1),
						rdf(Qualifier,mmA:'qualifier.has',Role2),
						Role1\=Role2.

%(9)  All qualifier names of a data are distinct

unique_name_qualifier :- rdf(Qualifier,mmA:'qualifier.name',Name1),
						rdf(Qualifier,mmA:'qualifier.name',Name2),
						Name1\=Name2.

%(10) All qualifiers are key attributes

qualifiers_are_keys :- rdf(_,mmA:'qualifier.name',Name),
	\+ (rdf(Attribute,mmA:'attribute.name',Name),rdf(Attribute,mmA:'attribute.key',literal(type(_,true)))).

%(11) Each relation has two roles

two_roles_relation :- setof(Role,rdf(_,mmA:'relation.is_role',Role),Roles),Roles\=[_,_].

%(12) All relation names are distinct

unique_name_relations:-rdf(Relation1,mmA:'relation.name',Name1),
					rdf(Relation2,mmA:'relation.name',Name2),
					Relation1\=Relation2,
					Name1=Name2.

%(13) Each role is associated to exactly one relation

unique_relation_role:-rdf(Role,mmA:'role.has_role',Relation1),
				rdf(Role,mmA:'role.has_role',Relation2),
				Relation1\=Relation2.

%(14) Each role is associated to exactly one data

unique_data_role:-rdf(Role,mmA:'role.isdata',Data1),
			rdf(Role,mmA:'role.isdata',Data2),
			Data1\=Data2.

%(15) All role names of a data are distinct

unique_role_names_data :-rdf(Data,mmA:'data.role_of',Role1),
				rdf(Data,mmA:'data.role_of',Role2),
				rdf(Role1,mmA:'role.name',Name1),
				rdf(Role2,mmA:'role.name',Name2),
				Role1\=Role2,
				Name1=Name2.

%(16) Each store is associated to exactly one data

unique_data_store :- rdf(Store,mmA:'store.contains',Data1),
					rdf(Store,mmA:'store.contains',Data2),
					Data1\=Data2.


%Metamodel  B


%(17) All col names of a row are distinct

unique_col_names_row :-rdf(Row,mmB:'row.is_col',Col1),
			rdf(Row,mmB:'row.is_col',Col2),
			Col1\=Col2,
			rdf(Col1,mmB:'col:name',Name1),
			rdf(Col2,mmB:'col:name',Name2),
			Name1=Name2.

%(18) All foreign names of a row are distinct

unique_foreign_names_row :-rdf(Row,mmB:'row.is_foreign',Foreign1),
				rdf(Row,mmB:'row.is_foreign',Foreign2),
				Foreign1\=Foreign2,
				rdf(Foreign1,mmB:'foreign:name',Name1),
				rdf(Foreign2,mmB:'foreign:name',Name2),
				Name1=Name2.

%(19) All key names of a row are distinct

unique_key_names_row :-rdf(Row,mmB:'row.is_key',Key1),
				rdf(Row,mmB:'row.is_key',Key2),
				Key1\=Key2,
				rdf(Key1,mmB:'key:name',Name1),
				rdf(Key2,mmB:'key:name',Name2),
				Name1=Name2.

%(20) All foreigns of a row are keys of another row

foreign_keys:-rdf(R,mmB:'row.is_foreign',A),
			rdf(R,mmB:'row.name',N),
			rdf(A,mmB:'foreign.name',Name),
			N=literal(type(_,RC)),
			Name=literal(type(_,NN)),
			concat(RC,NameKey,NN),
			\+ rdf(_,mmB:'key.name',literal(type(_,NameKey))).

%(21) Each table is associated to exactly one row

unique_table_row :- rdf(Table,mmB:'table.has',Row1),
			rdf(Table,mmB:'table.has',Row2),
			Row1\=Row2.

%(22) Each row is associated to exactly one table

unique_row_table:-rdf(Row,mmB:'row.table',Table1),
			rdf(Row,mmB:'row.table',Table2),
			Table1\=Table2.

%(23) Each key is associated to exactly one row

unique_row_key :- rdf(Key,mmB:'key.has_key',Row1),
			rdf(Key,mmB:'key.has_key',Row2),
			Row1\=Row2.

%(24) Each col is associated to exactly one row

unique_row_col :- rdf(Col,mmB:'col.has_col',Row1),
			rdf(Col,mmB:'col.has_col',Row2),
			Row1\=Row2.

%(25) Each foreign is associated to exactly one row

unique_row_foreign :- rdf(Foreign,mmB:'foreign.has_foreign',Row1),
				rdf(Foreign,mmB:'foreign.has_foreign',Row2),
				Row1\=Row2.

%(26) All table names are distinct 

unique_table_names :- rdf(Table1,mmB:'table.name',Name1),
					rdf(Table2,mmB:'table.name',Name2),
					Table1\=Table2,
					Name1=Name2.

%(27) All row names are distinct

unique_row_names :- rdf(Row1,mmB:'row.name',Name1),
					rdf(Row2,mmB:'row.name',Name2),
					Row1\=Row2,
					Name1=Name2.

%(28) All rows have exactly one key

unique_key_row :- rdf(Row,mmB:'row.is_key',Key1),
			rdf(Row,mmB:'row.is_key',Key2),
			Key1\=Key2.

%(29) All rows have either all keys and cols or all foreigns

well_formed_rows:-rdf(Row,mmB:'row.is_key',_),
					rdf(Row,mmB:'row.is_foreign',_).
well_formed_rows:-rdf(Row,mmB:'row.is_col',_),
					rdf(Row,mmB:'row.is_foreign',_).


%Transformation

%(30) Key and col names and types are names and types of attributes

names_and_types :- rdf(_,mmB:'key.name',Name),
					\+rdf(_,mmA:'attribute.name',Name).

names_and_types :- rdf(_,mmB:'key.type',Type),
					\+rdf(_,mmA:'attribute.type',Type).

names_and_types :- rdf(_,mmB:'col.name',Name),
					\+rdf(_,mmA:'attribute.name',Name).

names_and_types :- rdf(_,mmB:'col.type',Type),
					\+rdf(_,mmA:'attribute.type',Type).

%(31) Table names are either container names or role names 


containers_or_roles :- rdf(_,mmB:'table.name',Name),
					\+rdf(_,mmA:'role.name',Name),
					\+rdf(_,mmA:'data.container',Name).

 

%(32) Row names are data names or concatenations of role names and data

 
data_or_roles_and_data :- rdf(_,mmB:'row.name',Name), Name=literal(type(_,N)),
					\+ rdf(_,mmA:'data.name',Name), 
					\+     (rdf(_,mmA:'role.name',Name1),
						rdf(_,mmA:'data.name',Name2),
						Name1=literal(type(_,N1)),
						Name2=literal(type(_,N2)),
						concat(N1,N2,N)).
					
 
%(33) Foreign names are concatenations of roles, data and key attributes

foreign_names :- rdf(_,mmB:'foreign.name',Name),Name=literal(type(_,N)),
				\+ (rdf(_,mmA:'role.name',Name1),Name1=literal(type(_,N1)),
					rdf(_,mmA:'data.name',Name2),Name2=literal(type(_,N2)),
					rdf(_,mmA:'attribute.name',Name3),Name3=literal(type(_,N3)),
					rdf(_,mmA:'attribute.key',Key),
					Key=literal(type(_,true)),
					concat(N1,N2,NAux),
					concat(NAux,N3,N)).
