From e9ecab0b53622ad5497746e13f22506ba93b36ea Mon Sep 17 00:00:00 2001 From: Gleb Peregud Date: Tue, 17 Apr 2012 18:47:38 +0200 Subject: [PATCH] run erl_tidy and reformat using erlang-mode on all code --- examples/eresye/auto.erl | 429 +++--- examples/eresye/cannibals.erl | 427 +++--- examples/eresye/journal.erl | 169 ++- examples/eresye/journal_sample.erl | 287 ++-- examples/eresye/phil.erl | 125 +- examples/eresye/prodcons.erl | 94 +- examples/eresye/relatives.erl | 134 +- examples/eresye/sample.erl | 122 +- examples/eresye/sieve.erl | 99 +- examples/eresye/wine.erl | 105 +- examples/eresye/wine_sample.erl | 75 +- examples/jade/exat_agent.erl | 47 +- examples/original_exat/pingagent.erl | 103 +- examples/original_exat/pingeragent.erl | 178 ++- examples/simple/simple_pingagent.erl | 55 +- examples/simple/simple_pingeragent.erl | 63 +- src/acl.erl | 705 +++++----- src/aclscan.erl | 140 +- src/aclscanner.erl | 194 ++- src/agent.erl | 411 +++--- src/ams.erl | 98 +- src/envelope.erl | 172 +-- src/eresye.erl | 1319 +++++++++--------- src/eresye_agenda.erl | 870 ++++++------ src/eresye_ontology.erl | 677 +++++----- src/eresye_ontology_resolver.erl | 162 ++- src/eresye_tree_list.erl | 368 +++-- src/eventmanager.erl | 12 +- src/exat.erl | 48 +- src/exat_app.erl | 67 +- src/exat_server.erl | 94 +- src/exat_sup.erl | 87 +- src/fipa_ontology_sl_codec.erl | 1715 +++++++++++++++++++++--- src/fipa_semantics_simple.erl | 72 +- src/http_server.erl | 141 +- src/logger.erl | 100 +- src/match_lib.erl | 155 +-- src/mtp.erl | 341 +++-- src/mtp_utils.erl | 20 +- src/multisync.erl | 19 +- src/object.erl | 330 +++-- src/ontology.erl | 1166 ++++++++-------- src/ontology_service.erl | 111 +- src/semantics.erl | 63 +- src/simple_agent.erl | 155 +-- src/sl.erl | 115 +- src/sync.erl | 275 ++-- 47 files changed, 6739 insertions(+), 5975 deletions(-) mode change 100755 => 100644 examples/jade/exat_agent.erl diff --git a/examples/eresye/auto.erl b/examples/eresye/auto.erl index a321e4a..4ea80c6 100644 --- a/examples/eresye/auto.erl +++ b/examples/eresye/auto.erl @@ -1,25 +1,25 @@ -% -% auto.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% +%% +%% auto.erl +%% +%% ------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% %% ====================================================== %% Automotive Expert System %% @@ -31,203 +31,222 @@ %% %% To execute, type 'auto:start().' %% ====================================================== -% - --module (auto). - --export ([normal_engine_state_conclusions/2, - unsatisfactory_engine_state_conclusions/2, - determine_engine_state/2, - determine_rotation_state/2, - determine_sluggishness/2, - determine_misfiring/2, - determine_knocking/2, - determine_low_output/2, - determine_gas_level/3, - determine_battery_state/2, - determine_point_surface_state_1/3, - determine_point_surface_state_2/2, - determine_conductivity_test/4, - no_repairs/2, - print_repair/3, - start/0]). - - -ask_yn (Prompt) -> - [Response | _] = io:get_line (Prompt), - case Response of - $y -> true; - _ -> false - end. - -ask_question (Prompt) -> - io:get_line (Prompt). - +%% -%% ********************** -%% * ENGINE STATE RULES * -%% ********************** -normal_engine_state_conclusions (Engine, {'working-state', engine, normal}) -> - eresye:assert (Engine, {repair, "No repair needed."}), - eresye:assert (Engine, {'spark-state', engine, normal}), - eresye:assert (Engine, {'charge-state', battery, charged}), - eresye:assert (Engine, {'rotation-state', engine, rotates}). +-module(auto). +-export([determine_battery_state/2, + determine_conductivity_test/4, determine_engine_state/2, + determine_gas_level/3, determine_knocking/2, + determine_low_output/2, determine_misfiring/2, + determine_point_surface_state_1/3, + determine_point_surface_state_2/2, + determine_rotation_state/2, determine_sluggishness/2, + no_repairs/2, normal_engine_state_conclusions/2, + print_repair/3, start/0, + unsatisfactory_engine_state_conclusions/2]). -unsatisfactory_engine_state_conclusions (Engine, - {'working-state', engine, - unsatisfactory}) -> - eresye:assert (Engine, {'charge-state', battery, charged}), - eresye:assert (Engine, {'rotation-state', engine, rotates}). +ask_yn(Prompt) -> + [Response | _] = io:get_line(Prompt), + case Response of + $y -> true; + _ -> false + end. +ask_question(Prompt) -> io:get_line(Prompt). +%% ********************** +%% * ENGINE STATE RULES * +%% ********************** +normal_engine_state_conclusions(Engine, + {'working-state', engine, normal}) -> + eresye:assert(Engine, {repair, "No repair needed."}), + eresye:assert(Engine, {'spark-state', engine, normal}), + eresye:assert(Engine, + {'charge-state', battery, charged}), + eresye:assert(Engine, + {'rotation-state', engine, rotates}). + +unsatisfactory_engine_state_conclusions(Engine, + {'working-state', engine, + unsatisfactory}) -> + eresye:assert(Engine, + {'charge-state', battery, charged}), + eresye:assert(Engine, + {'rotation-state', engine, rotates}). %% *************** %% * QUERY RULES * %% *************** -determine_engine_state (Engine, {start, _}) when not -["{'working-state', engine, _}", "{repair, _}"]; true -> - case ask_yn ('Does the engine start (yes/no)? ') of - true -> - case ask_yn ('Does the engine run normally (yes/no)? ') of - true -> eresye:assert (Engine, {'working-state', engine, normal}); - _ -> eresye:assert (Engine, {'working-state', engine, unsatisfactory}) - end; - _ -> eresye:assert (Engine, {'working-state', engine, 'does-not-start'}) - end. - - -determine_rotation_state (Engine, +determine_engine_state(Engine, {start, _}) + when not + ["{'working-state', engine, _}", "{repair, _}"]; + true -> + case ask_yn('Does the engine start (yes/no)? ') of + true -> + case ask_yn('Does the engine run normally (yes/no)? ') + of + true -> + eresye:assert(Engine, + {'working-state', engine, normal}); + _ -> + eresye:assert(Engine, + {'working-state', engine, unsatisfactory}) + end; + _ -> + eresye:assert(Engine, {'working-state', engine, 'does-not-start'}) -when not ["{'rotation-state', engine, _}", "{repair, _}"]; true -> - case ask_yn ('Does the engine rotate (yes/no)? ') of - true -> eresye:assert (Engine, {'rotation-state', engine, rotates}), - eresye:assert (Engine, {'spark-state', engine, 'irregular-spark'}); - _ -> eresye:assert (Engine, {'rotation-state', engine, 'does-not-rotate'}), - eresye:assert (Engine, {'spark-state', engine, 'does-not-spark'}) - end. - - -determine_sluggishness (Engine, {'working-state', engine, unsatisfactory}) -when not ["{repair, _}"]; true -> - case ask_yn ('Is the engine sluggish (yes/no)? ') of - true -> eresye:assert (Engine, {repair, "Clean the fuel line."}); - _ -> ok - end. - - -determine_misfiring (Engine, {'working-state', engine, unsatisfactory}) + end. + +determine_rotation_state(Engine, + {'working-state', engine, 'does-not-start'}) + when not + ["{'rotation-state', engine, _}", "{repair, _}"]; + true -> + case ask_yn('Does the engine rotate (yes/no)? ') of + true -> + eresye:assert(Engine, + {'rotation-state', engine, rotates}), + eresye:assert(Engine, + {'spark-state', engine, 'irregular-spark'}); + _ -> + eresye:assert(Engine, + {'rotation-state', engine, 'does-not-rotate'}), + eresye:assert(Engine, + {'spark-state', engine, 'does-not-spark'}) + end. + +determine_sluggishness(Engine, + {'working-state', engine, unsatisfactory}) when not ["{repair, _}"]; true -> - case ask_yn ('Does the engine misfire (yes/no)? ') of - true -> eresye:assert (Engine, {repair, "Point gap adjustment."}), - eresye:assert (Engine, {'spark-state', engine, 'irregular-spark'}); - _ -> ok - end. - - -determine_knocking (E, {'working-state', engine, unsatisfactory}) + case ask_yn('Is the engine sluggish (yes/no)? ') of + true -> + eresye:assert(Engine, {repair, "Clean the fuel line."}); + _ -> ok + end. + +determine_misfiring(Engine, + {'working-state', engine, unsatisfactory}) when not ["{repair, _}"]; true -> - case ask_yn ('Does the engine knock (yes/no)? ') of - true -> eresye:assert (E, {repair, "Timing adjustment."}); - _ -> ok - end. - - -determine_low_output (E, {'working-state', engine, unsatisfactory}) - when not ["{symptom, engine, _}", "{repair, _}"]; true -> - case ask_yn ('Is the output of the engine low (yes/no)? ') of - true -> eresye:assert (E, {symptom, engine, 'low-output'}); - _ -> eresye:assert (E, {symptom, engine, 'not-low-output'}) - end. - - -determine_gas_level (E, - {'working-state', engine, 'does-not-start'}, - {'rotation-state', engine, rotates}) + case ask_yn('Does the engine misfire (yes/no)? ') of + true -> + eresye:assert(Engine, + {repair, "Point gap adjustment."}), + eresye:assert(Engine, + {'spark-state', engine, 'irregular-spark'}); + _ -> ok + end. + +determine_knocking(E, + {'working-state', engine, unsatisfactory}) when not ["{repair, _}"]; true -> - case ask_yn ('Does the tank have any gas in it (yes/no)? ') of - false -> eresye:assert (E, {repair, "Add gas."}); - _ -> ok - end. - - -determine_battery_state (E, - {'rotation-state', engine, 'does-not-rotate'}) -when not ["{'charge-state', battery, _}", "{repair, _}"]; true -> - case ask_yn ('Is the battery charged (yes/no)? ') of - true -> eresye:assert (E, {'charge-state', battery, charged}); - _ -> eresye:assert (E, {repair, "Charge the battery."}), - eresye:assert (E, {'charge-state', battery, dead}) - end. - + case ask_yn('Does the engine knock (yes/no)? ') of + true -> + eresye:assert(E, {repair, "Timing adjustment."}); + _ -> ok + end. + +determine_low_output(E, + {'working-state', engine, unsatisfactory}) + when not ["{symptom, engine, _}", "{repair, _}"]; + true -> + case + ask_yn('Is the output of the engine low (yes/no)? ') + of + true -> + eresye:assert(E, {symptom, engine, 'low-output'}); + _ -> + eresye:assert(E, {symptom, engine, 'not-low-output'}) + end. + +determine_gas_level(E, + {'working-state', engine, 'does-not-start'}, + {'rotation-state', engine, rotates}) + when not ["{repair, _}"]; true -> + case + ask_yn('Does the tank have any gas in it (yes/no)? ') + of + false -> eresye:assert(E, {repair, "Add gas."}); + _ -> ok + end. + +determine_battery_state(E, + {'rotation-state', engine, 'does-not-rotate'}) + when not + ["{'charge-state', battery, _}", "{repair, _}"]; + true -> + case ask_yn('Is the battery charged (yes/no)? ') of + true -> + eresye:assert(E, {'charge-state', battery, charged}); + _ -> + eresye:assert(E, {repair, "Charge the battery."}), + eresye:assert(E, {'charge-state', battery, dead}) + end. + +determine_point_surface_state_1(E, + {'working-state', engine, 'does-not-start'}, + {'spark-state', engine, 'irregular-spark'}) + when not ["{repair, _}"]; true -> + dpss(E). -determine_point_surface_state_1 (E, - {'working-state', engine, 'does-not-start'}, - {'spark-state', engine, 'irregular-spark'}) +determine_point_surface_state_2(E, + {symptom, engine, 'low-output'}) when not ["{repair, _}"]; true -> - dpss (E). -determine_point_surface_state_2 (E, - {symptom, engine, 'low-output'}) + dpss(E). + +dpss(E) -> + case + ask_question('What is the surface state of the points (normal/burned/contaminated)? ') + of + [$b, $u, $r, $n, $e, $d | _] -> + eresye:assert(E, {repair, "Replace the points."}); + [$c, $o, $n, $t, $a, $m, $i, $n, $a, $t, $e, $d | _] -> + eresye:assert(E, {repair, "Clean the points."}); + _ -> ok + end. + +determine_conductivity_test(E, + {'working-state', engine, 'does-not-start'}, + {'spark-state', engine, 'does-not-spark'}, + {'charge-state', battery, charged}) when not ["{repair, _}"]; true -> - dpss (E). - -dpss (E) -> - case ask_question ('What is the surface state of the points (normal/burned/contaminated)? ') of - [$b,$u,$r,$n,$e,$d | _] -> - eresye:assert (E, {repair, "Replace the points."}); - [$c,$o,$n,$t,$a,$m,$i,$n,$a,$t,$e,$d | _] -> - eresye:assert (E, {repair, "Clean the points."}); - _ -> ok - end. - - -determine_conductivity_test (E, - {'working-state', engine, 'does-not-start'}, - {'spark-state', engine, 'does-not-spark'}, - {'charge-state', battery, charged}) + case + ask_yn('Is the conductivity test for the ignition coil positive (yes/no)? ') + of + true -> + eresye:assert(E, + {repair, "Repair the distributor lead wire."}); + _ -> + eresye:assert(E, {repair, "Replace the ignition coil."}) + end. + +no_repairs(E, {start, _}) when not ["{repair, _}"]; true -> - case ask_yn ('Is the conductivity test for the ignition coil positive (yes/no)? ') of - true -> eresye:assert (E, {repair, "Repair the distributor lead wire."}); - _ -> eresye:assert (E, {repair, "Replace the ignition coil."}) - end. - - -no_repairs (E, {start, _}) when not ["{repair, _}"]; true -> - eresye:assert (E, {repair, "Take your car to a mechanic."}). - - -print_repair (_, {repair, X}, {start, Pid}) -> - io:format ("Suggested Repair: ~p~n", [X]), - Pid ! ok. - - - - -start () -> - eresye:start (auto), - %% Rules with high priority (10) - [eresye:add_rule (auto, {?MODULE, X}, 10) || - X <- [normal_engine_state_conclusions, - unsatisfactory_engine_state_conclusions, - print_repair]], - %% Rules with normal priority (0) - [eresye:add_rule (auto, {?MODULE, X}) || - X <- [determine_engine_state, - determine_rotation_state, - determine_sluggishness, - determine_misfiring, - determine_knocking, - determine_low_output, - determine_gas_level, - determine_battery_state, - determine_point_surface_state_1, - determine_point_surface_state_2, - determine_conductivity_test]], - %% Rules with low priority (-10) - eresye:add_rule (auto, {?MODULE, no_repairs}, -10), - eresye:assert (auto, {start, self ()}), - receive - _ -> ok - end, - eresye:stop (auto). - + eresye:assert(E, + {repair, "Take your car to a mechanic."}). + +print_repair(_, {repair, X}, {start, Pid}) -> + io:format("Suggested Repair: ~p~n", [X]), Pid ! ok. + +start() -> + eresye:start(auto), + %% Rules with high priority (10) + [eresye:add_rule(auto, {?MODULE, X}, 10) + || X + <- [normal_engine_state_conclusions, + unsatisfactory_engine_state_conclusions, print_repair]], + %% Rules with normal priority (0) + [eresye:add_rule(auto, {?MODULE, X}) + || X + <- [determine_engine_state, determine_rotation_state, + determine_sluggishness, determine_misfiring, + determine_knocking, determine_low_output, + determine_gas_level, determine_battery_state, + determine_point_surface_state_1, + determine_point_surface_state_2, + determine_conductivity_test]], + %% Rules with low priority (-10) + eresye:add_rule(auto, {?MODULE, no_repairs}, -10), + eresye:assert(auto, {start, self()}), + receive _ -> ok end, + eresye:stop(auto). diff --git a/examples/eresye/cannibals.erl b/examples/eresye/cannibals.erl index 87842e4..80423f6 100644 --- a/examples/eresye/cannibals.erl +++ b/examples/eresye/cannibals.erl @@ -1,25 +1,25 @@ -% -% cannibals.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% +%% +%% cannibals.erl +%% +%% ------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% %% ====================================================== %% Cannibals and Missionaries Problem %% @@ -36,194 +36,201 @@ %% To execute, type 'cannibals:start().' %% ====================================================== --module (cannibals). --compile ([export_all]). - --record (status, {'search-depth', - 'parent', - 'shore-1-missionaries', - 'shore-1-cannibals', - 'shore-2-missionaries', - 'shore-2-cannibals', - 'boat-location', - 'last-move'}). - - --record (moves, {id, 'moves-list'}). - - --define (INITIAL_MISSIONARIES, 3). --define (INITIAL_CANNIBALS, 3). - -for (Min, Max) when Min > Max -> []; -for (Min, Max) -> lists:seq (Min, Max). - -shore_1_move (Engine, - #status {'boat-location' = 'shore-1'} = Node, - {'boat-can-host', Limit}) -> - Num = Node#status.'search-depth', - S1M = Node#status.'shore-1-missionaries', - S1C = Node#status.'shore-1-cannibals', - S2M = Node#status.'shore-2-missionaries', - S2C = Node#status.'shore-2-cannibals', - - MaxMissionaries = lists:min ([S1M, Limit]), - - lists:foreach ( - fun (Missionaries) -> - MinCannibals = lists:max ([0, 1 - Missionaries]), - MaxCannibals = lists:min ([S1C, Limit - Missionaries]), - - %%io:format ("Shore 1 ~p,~p~n", [MinCannibals, MaxCannibals]), - - lists:foreach ( - fun (Cannibals) -> - NewNode = - #status { 'search-depth' = Num + 1, - 'parent' = Node, - 'shore-1-missionaries' = S1M - Missionaries, - 'shore-1-cannibals' = S1C - Cannibals, - 'shore-2-missionaries' = Missionaries + S2M, - 'shore-2-cannibals' = Cannibals + S2C, - 'boat-location' = 'shore-2', - 'last-move' = move_string (Missionaries, - Cannibals, - "shore-2")}, - eresye:assert (Engine, NewNode) - end, - for (MinCannibals, MaxCannibals)) - end, - for (0, MaxMissionaries)). - - -shore_2_move (Engine, - #status {'boat-location' = 'shore-2'} = Node, - {'boat-can-host', Limit}) -> - Num = Node#status.'search-depth', - S1M = Node#status.'shore-1-missionaries', - S1C = Node#status.'shore-1-cannibals', - S2M = Node#status.'shore-2-missionaries', - S2C = Node#status.'shore-2-cannibals', - - MaxMissionaries = lists:min ([S2M, Limit]), - - lists:foreach ( - fun (Missionaries) -> - MinCannibals = lists:max ([0, 1 - Missionaries]), - MaxCannibals = lists:min ([S2C, Limit - Missionaries]), - - %%io:format ("Shore 2 ~p,~p~n", [MinCannibals, MaxCannibals]), - - lists:foreach ( - fun (Cannibals) -> - NewNode = - #status { 'search-depth' = Num + 1, - 'parent' = Node, - 'shore-1-missionaries' = S1M + Missionaries, - 'shore-1-cannibals' = S1C + Cannibals, - 'shore-2-missionaries' = S2M - Missionaries, - 'shore-2-cannibals' = S2C - Cannibals, - 'boat-location' = 'shore-1', - 'last-move' = move_string (Missionaries, - Cannibals, - "shore-1")}, - eresye:assert (Engine, NewNode) - end, - for (MinCannibals, MaxCannibals)) - end, - for (0, MaxMissionaries)). - - - -cannibals_eat_missionaries (Engine, - #status {'shore-1-missionaries' = S1M, - 'shore-1-cannibals' = S1C, - 'shore-2-missionaries' = S2M, - 'shore-2-cannibals' = S2C} = Node) -> - if - ((S2C > S2M) and (S2M =/= 0)) or ((S1C > S1M) and (S1M =/= 0)) -> - %%io:format ("Invalid ~p~n", [Node]), - eresye:retract (Engine, Node); - true -> ok - end. - - -circular_path (Engine, - #status {'search-depth' = SD1, - 'boat-location' = BL, - 'shore-1-missionaries' = S1M, - 'shore-1-cannibals' = S1C, - 'shore-2-missionaries' = S2M, - 'shore-2-cannibals' = S2C}, - #status {'search-depth' = SD2, - 'boat-location' = BL, - 'shore-1-missionaries' = S1M, - 'shore-1-cannibals' = S1C, - 'shore-2-missionaries' = S2M, - 'shore-2-cannibals' = S2C} = Node) -> - if - SD1 < SD2 -> eresye:retract (Engine, Node); - true -> ok - end. - - -recognize_solution (Engine, - #status {parent = Parent, - 'shore-2-missionaries' = M, - 'shore-2-cannibals' = C, - 'last-move' = Move} = Node) -> - if - (M == ?INITIAL_MISSIONARIES) and (C == ?INITIAL_CANNIBALS) -> - eresye:retract (Engine, Node), - eresye:assert (Engine, #moves { id = Parent, 'moves-list' = Move}); - true -> ok - end. - -move_string (0, 1, Shore) -> - lists:concat (["Move 1 cannibal to ", Shore]); -move_string (0, N, Shore) -> - lists:concat (["Move ", N, " cannibals to ", Shore]); -move_string (1, 0, Shore) -> - lists:concat (["Move 1 missionary to ", Shore]); -move_string (1, 1, Shore) -> - lists:concat (["Move 1 missionary and 1 cannibal to ", Shore]); -move_string (1, N, Shore) -> - lists:concat (["Move 1 missionary and ", N, " cannibals to ", Shore]); -move_string (M, 0, Shore) -> - lists:concat (["Move ", M ," missionaries to ", Shore]); -move_string (M, 1, Shore) -> - lists:concat (["Move ", M, " missionaries and 1 cannibal to ", Shore]); -move_string (M, N, Shore) -> - lists:concat (["Move ", M, " missionaries and ", N, " cannibals to ", - Shore]). - - -print_solution (#status { parent = 'no-parent' }) -> - ok; -print_solution (S) -> - print_solution (S#status.parent), - io:format ("~p~n", [S#status.'last-move']). - - -start () -> - eresye:start (cannibals), - eresye:add_rule (cannibals, {cannibals, shore_1_move}), - eresye:add_rule (cannibals, {cannibals, shore_2_move}), - eresye:add_rule (cannibals, {cannibals, cannibals_eat_missionaries}, 10), - eresye:add_rule (cannibals, {cannibals, circular_path}, 10), - eresye:add_rule (cannibals, {cannibals, recognize_solution}), - eresye:assert (cannibals, - #status {'search-depth' = 1, - 'parent' = 'no-parent', +-module(cannibals). + +-compile([export_all]). + +-record(status, + {'search-depth', parent, 'shore-1-missionaries', + 'shore-1-cannibals', 'shore-2-missionaries', + 'shore-2-cannibals', 'boat-location', 'last-move'}). + +-record(moves, {id, 'moves-list'}). + +-define(INITIAL_MISSIONARIES, 3). + +-define(INITIAL_CANNIBALS, 3). + +for(Min, Max) when Min > Max -> []; +for(Min, Max) -> lists:seq(Min, Max). + +shore_1_move(Engine, + #status{'boat-location' = 'shore-1'} = Node, + {'boat-can-host', Limit}) -> + Num = Node#status.'search-depth', + S1M = Node#status.'shore-1-missionaries', + S1C = Node#status.'shore-1-cannibals', + S2M = Node#status.'shore-2-missionaries', + S2C = Node#status.'shore-2-cannibals', + MaxMissionaries = lists:min([S1M, Limit]), + lists:foreach(fun (Missionaries) -> + MinCannibals = lists:max([0, 1 - Missionaries]), + MaxCannibals = lists:min([S1C, Limit - Missionaries]), + %%io:format ("Shore 1 ~p,~p~n", [MinCannibals, MaxCannibals]), + lists:foreach(fun (Cannibals) -> + NewNode = #status{'search-depth' + = Num + 1, + parent = Node, + 'shore-1-missionaries' + = + S1M - + Missionaries, + 'shore-1-cannibals' + = + S1C - + Cannibals, + 'shore-2-missionaries' + = + Missionaries + + S2M, + 'shore-2-cannibals' + = + Cannibals + + S2C, + 'boat-location' + = + 'shore-2', + 'last-move' = + move_string(Missionaries, + Cannibals, + "shore-2")}, + eresye:assert(Engine, NewNode) + end, + for(MinCannibals, MaxCannibals)) + end, + for(0, MaxMissionaries)). + +shore_2_move(Engine, + #status{'boat-location' = 'shore-2'} = Node, + {'boat-can-host', Limit}) -> + Num = Node#status.'search-depth', + S1M = Node#status.'shore-1-missionaries', + S1C = Node#status.'shore-1-cannibals', + S2M = Node#status.'shore-2-missionaries', + S2C = Node#status.'shore-2-cannibals', + MaxMissionaries = lists:min([S2M, Limit]), + lists:foreach(fun (Missionaries) -> + MinCannibals = lists:max([0, 1 - Missionaries]), + MaxCannibals = lists:min([S2C, Limit - Missionaries]), + %%io:format ("Shore 2 ~p,~p~n", [MinCannibals, MaxCannibals]), + lists:foreach(fun (Cannibals) -> + NewNode = #status{'search-depth' + = Num + 1, + parent = Node, + 'shore-1-missionaries' + = + S1M + + Missionaries, + 'shore-1-cannibals' + = + S1C + + Cannibals, + 'shore-2-missionaries' + = + S2M - + Missionaries, + 'shore-2-cannibals' + = + S2C - + Cannibals, + 'boat-location' + = + 'shore-1', + 'last-move' = + move_string(Missionaries, + Cannibals, + "shore-1")}, + eresye:assert(Engine, NewNode) + end, + for(MinCannibals, MaxCannibals)) + end, + for(0, MaxMissionaries)). + +cannibals_eat_missionaries(Engine, + #status{'shore-1-missionaries' = S1M, + 'shore-1-cannibals' = S1C, + 'shore-2-missionaries' = S2M, + 'shore-2-cannibals' = S2C} = + Node) -> + if (S2C > S2M) and (S2M =/= 0) or + (S1C > S1M) and (S1M =/= 0) -> + %%io:format ("Invalid ~p~n", [Node]), + eresye:retract(Engine, Node); + true -> ok + end. + +circular_path(Engine, + #status{'search-depth' = SD1, 'boat-location' = BL, + 'shore-1-missionaries' = S1M, 'shore-1-cannibals' = S1C, + 'shore-2-missionaries' = S2M, + 'shore-2-cannibals' = S2C}, + #status{'search-depth' = SD2, 'boat-location' = BL, + 'shore-1-missionaries' = S1M, 'shore-1-cannibals' = S1C, + 'shore-2-missionaries' = S2M, + 'shore-2-cannibals' = S2C} = + Node) -> + if SD1 < SD2 -> eresye:retract(Engine, Node); + true -> ok + end. + +recognize_solution(Engine, + #status{parent = Parent, 'shore-2-missionaries' = M, + 'shore-2-cannibals' = C, 'last-move' = Move} = + Node) -> + if (M == (?INITIAL_MISSIONARIES)) and + (C == (?INITIAL_CANNIBALS)) -> + eresye:retract(Engine, Node), + eresye:assert(Engine, + #moves{id = Parent, 'moves-list' = Move}); + true -> ok + end. + +move_string(0, 1, Shore) -> + lists:concat(["Move 1 cannibal to ", Shore]); +move_string(0, N, Shore) -> + lists:concat(["Move ", N, " cannibals to ", Shore]); +move_string(1, 0, Shore) -> + lists:concat(["Move 1 missionary to ", Shore]); +move_string(1, 1, Shore) -> + lists:concat(["Move 1 missionary and 1 cannibal to ", + Shore]); +move_string(1, N, Shore) -> + lists:concat(["Move 1 missionary and ", N, + " cannibals to ", Shore]); +move_string(M, 0, Shore) -> + lists:concat(["Move ", M, " missionaries to ", Shore]); +move_string(M, 1, Shore) -> + lists:concat(["Move ", M, + " missionaries and 1 cannibal to ", Shore]); +move_string(M, N, Shore) -> + lists:concat(["Move ", M, " missionaries and ", N, + " cannibals to ", Shore]). + +print_solution(#status{parent = 'no-parent'}) -> ok; +print_solution(S) -> + print_solution(S#status.parent), + io:format("~p~n", [S#status.'last-move']). + +start() -> + eresye:start(cannibals), + eresye:add_rule(cannibals, {cannibals, shore_1_move}), + eresye:add_rule(cannibals, {cannibals, shore_2_move}), + eresye:add_rule(cannibals, + {cannibals, cannibals_eat_missionaries}, 10), + eresye:add_rule(cannibals, {cannibals, circular_path}, + 10), + eresye:add_rule(cannibals, + {cannibals, recognize_solution}), + eresye:assert(cannibals, + #status{'search-depth' = 1, parent = 'no-parent', 'shore-1-missionaries' = ?INITIAL_MISSIONARIES, 'shore-2-missionaries' = 0, 'shore-1-cannibals' = ?INITIAL_CANNIBALS, - 'shore-2-cannibals' = 0, - 'boat-location' = 'shore-1', - 'last-move' = 'No move.'}), - eresye:assert (cannibals, {'boat-can-host', 2}), - P = eresye:wait (cannibals, #moves {id = '_', 'moves-list'= '_'}), - print_solution (P#moves.id), - io:format ("~p~n", [P#moves.'moves-list']), - eresye:stop (cannibals). - + 'shore-2-cannibals' = 0, 'boat-location' = 'shore-1', + 'last-move' = 'No move.'}), + eresye:assert(cannibals, {'boat-can-host', 2}), + P = eresye:wait(cannibals, + #moves{id = '_', 'moves-list' = '_'}), + print_solution(P#moves.id), + io:format("~p~n", [P#moves.'moves-list']), + eresye:stop(cannibals). diff --git a/examples/eresye/journal.erl b/examples/eresye/journal.erl index eaa60ac..5888daf 100644 --- a/examples/eresye/journal.erl +++ b/examples/eresye/journal.erl @@ -1,98 +1,87 @@ --module (journal). --include ("journal.hrl"). --export ([is_class/1, is_a/2, 'journal'/1,'international-journal'/1,'national-journal'/1, childof/1]). +-module(journal). -is_class ('journal') -> true; -is_class ('international-journal') -> true; -is_class ('national-journal') -> true; -is_class ('IEEE-journal') -> true; -is_class ('ACM-journal') -> true; -is_class ('italian-journal') -> true; -is_class (_) -> false. +-include("journal.hrl"). -is_a ('international-journal','journal') -> true; -is_a ('national-journal','journal') -> true; -is_a ('IEEE-journal','international-journal') -> true; -is_a ('IEEE-journal','journal') -> true; -is_a ('ACM-journal','international-journal') -> true; -is_a ('ACM-journal','journal') -> true; -is_a ('italian-journal','national-journal') -> true; -is_a ('italian-journal','journal') -> true; -is_a (_,_) -> false. +-export([childof/1, 'international-journal'/1, is_a/2, + is_class/1, journal/1, 'national-journal'/1]). -childof ('journal') -> ['international-journal', - 'national-journal', - 'IEEE-journal', - 'ACM-journal', - 'italian-journal']; -childof ('international-journal') -> ['IEEE-journal','ACM-journal']; -childof ('national-journal') -> ['italian-journal']; -childof ('IEEE-journal') -> []; -childof ('ACM-journal') -> []; -childof ('italian-journal') -> []; -childof (_) -> exit (undef_class). +is_class(journal) -> true; +is_class('international-journal') -> true; +is_class('national-journal') -> true; +is_class('IEEE-journal') -> true; +is_class('ACM-journal') -> true; +is_class('italian-journal') -> true; +is_class(_) -> false. -'journal' (X = #'international-journal'{}) -> - #'journal'{ - 'title' = X#'international-journal'.'title', - 'main_topic' = X#'international-journal'.'main_topic', - 'publisher' = X#'international-journal'.'publisher', - 'type' = X#'international-journal'.'type', - 'impact_factor' = X#'international-journal'.'impact_factor'}; +is_a('international-journal', journal) -> true; +is_a('national-journal', journal) -> true; +is_a('IEEE-journal', 'international-journal') -> true; +is_a('IEEE-journal', journal) -> true; +is_a('ACM-journal', 'international-journal') -> true; +is_a('ACM-journal', journal) -> true; +is_a('italian-journal', 'national-journal') -> true; +is_a('italian-journal', journal) -> true; +is_a(_, _) -> false. -'journal' (X = #'national-journal'{}) -> - #'journal'{ - 'title' = X#'national-journal'.'title', - 'main_topic' = X#'national-journal'.'main_topic', - 'publisher' = X#'national-journal'.'publisher', - 'type' = X#'national-journal'.'type', - 'impact_factor' = X#'national-journal'.'impact_factor'}; +childof(journal) -> + ['international-journal', 'national-journal', + 'IEEE-journal', 'ACM-journal', 'italian-journal']; +childof('international-journal') -> + ['IEEE-journal', 'ACM-journal']; +childof('national-journal') -> ['italian-journal']; +childof('IEEE-journal') -> []; +childof('ACM-journal') -> []; +childof('italian-journal') -> []; +childof(_) -> exit(undef_class). -'journal' (X = #'IEEE-journal'{}) -> - #'journal'{ - 'title' = X#'IEEE-journal'.'title', - 'main_topic' = X#'IEEE-journal'.'main_topic', - 'publisher' = X#'IEEE-journal'.'publisher', - 'type' = X#'IEEE-journal'.'type', - 'impact_factor' = X#'IEEE-journal'.'impact_factor'}; +journal(X = #'international-journal'{}) -> + #journal{title = X#'international-journal'.title, + main_topic = X#'international-journal'.main_topic, + publisher = X#'international-journal'.publisher, + type = X#'international-journal'.type, + impact_factor = + X#'international-journal'.impact_factor}; +journal(X = #'national-journal'{}) -> + #journal{title = X#'national-journal'.title, + main_topic = X#'national-journal'.main_topic, + publisher = X#'national-journal'.publisher, + type = X#'national-journal'.type, + impact_factor = X#'national-journal'.impact_factor}; +journal(X = #'IEEE-journal'{}) -> + #journal{title = X#'IEEE-journal'.title, + main_topic = X#'IEEE-journal'.main_topic, + publisher = X#'IEEE-journal'.publisher, + type = X#'IEEE-journal'.type, + impact_factor = X#'IEEE-journal'.impact_factor}; +journal(X = #'ACM-journal'{}) -> + #journal{title = X#'ACM-journal'.title, + main_topic = X#'ACM-journal'.main_topic, + publisher = X#'ACM-journal'.publisher, + type = X#'ACM-journal'.type, + impact_factor = X#'ACM-journal'.impact_factor}; +journal(X = #'italian-journal'{}) -> + #journal{title = X#'italian-journal'.title, + main_topic = X#'italian-journal'.main_topic, + publisher = X#'italian-journal'.publisher, + type = X#'italian-journal'.type, + impact_factor = X#'italian-journal'.impact_factor}. -'journal' (X = #'ACM-journal'{}) -> - #'journal'{ - 'title' = X#'ACM-journal'.'title', - 'main_topic' = X#'ACM-journal'.'main_topic', - 'publisher' = X#'ACM-journal'.'publisher', - 'type' = X#'ACM-journal'.'type', - 'impact_factor' = X#'ACM-journal'.'impact_factor'}; - -'journal' (X = #'italian-journal'{}) -> - #'journal'{ - 'title' = X#'italian-journal'.'title', - 'main_topic' = X#'italian-journal'.'main_topic', - 'publisher' = X#'italian-journal'.'publisher', - 'type' = X#'italian-journal'.'type', - 'impact_factor' = X#'italian-journal'.'impact_factor'}. - -'international-journal' (X = #'IEEE-journal'{}) -> - #'international-journal'{ - 'title' = X#'IEEE-journal'.'title', - 'main_topic' = X#'IEEE-journal'.'main_topic', - 'publisher' = X#'IEEE-journal'.'publisher', - 'type' = X#'IEEE-journal'.'type', - 'impact_factor' = X#'IEEE-journal'.'impact_factor'}; - -'international-journal' (X = #'ACM-journal'{}) -> - #'international-journal'{ - 'title' = X#'ACM-journal'.'title', - 'main_topic' = X#'ACM-journal'.'main_topic', - 'publisher' = X#'ACM-journal'.'publisher', - 'type' = X#'ACM-journal'.'type', - 'impact_factor' = X#'ACM-journal'.'impact_factor'}. - -'national-journal' (X = #'italian-journal'{}) -> - #'national-journal'{ - 'title' = X#'italian-journal'.'title', - 'main_topic' = X#'italian-journal'.'main_topic', - 'publisher' = X#'italian-journal'.'publisher', - 'type' = X#'italian-journal'.'type', - 'impact_factor' = X#'italian-journal'.'impact_factor'}. +'international-journal'(X = #'IEEE-journal'{}) -> + #'international-journal'{title = X#'IEEE-journal'.title, + main_topic = X#'IEEE-journal'.main_topic, + publisher = X#'IEEE-journal'.publisher, + type = X#'IEEE-journal'.type, + impact_factor = X#'IEEE-journal'.impact_factor}; +'international-journal'(X = #'ACM-journal'{}) -> + #'international-journal'{title = X#'ACM-journal'.title, + main_topic = X#'ACM-journal'.main_topic, + publisher = X#'ACM-journal'.publisher, + type = X#'ACM-journal'.type, + impact_factor = X#'ACM-journal'.impact_factor}. +'national-journal'(X = #'italian-journal'{}) -> + #'national-journal'{title = X#'italian-journal'.title, + main_topic = X#'italian-journal'.main_topic, + publisher = X#'italian-journal'.publisher, + type = X#'italian-journal'.type, + impact_factor = X#'italian-journal'.impact_factor}. diff --git a/examples/eresye/journal_sample.erl b/examples/eresye/journal_sample.erl index 5dd3de3..91fbc62 100644 --- a/examples/eresye/journal_sample.erl +++ b/examples/eresye/journal_sample.erl @@ -1,153 +1,134 @@ -% -% journal_sample.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (journal_sample). --compile ([export_all]). --include ("journal.hrl"). - - --define (AddDefaultRule (Fun, Class), - Fun (_,_,_,#Class{}) -> ok; - Fun (E, T, I, Y) -> Fun (E, T, I, journal:Class (Y))). - - -ask_question (Prompt) -> - lists:reverse (tl(lists:reverse (io:get_line (Prompt)))). - - -national_journal (_, {topic, Topic}, {ifactor, MinimumIF}, - #'national-journal' { main_topic = Topic, - impact_factor = IF} = J) - when IF >= MinimumIF -> - io:format ("The journal is ~p~n", [J]); -?AddDefaultRule (national_journal, 'national-journal'). - - -intl_journal (_, {topic, Topic}, {ifactor, MinimumIF}, - #'international-journal' { main_topic = Topic, - impact_factor = IF} = J) - when IF >= MinimumIF -> - io:format ("The journal is ~p~n", [J]); -?AddDefaultRule (intl_journal, 'international-journal'). - - -ieee_journal (_, {topic, Topic}, {ifactor, MinimumIF}, - #'IEEE-journal' { main_topic = Topic, - impact_factor = IF} = J) - when IF >= MinimumIF -> - io:format ("The journal is ~p~n", [J]); -?AddDefaultRule (ieee_journal, 'IEEE-journal'). - - -acm_journal (_, {topic, Topic}, {ifactor, MinimumIF}, - #'ACM-journal' { main_topic = Topic, - impact_factor = IF} = J) - when IF >= MinimumIF -> - io:format ("The journal is ~p~n", [J]); -?AddDefaultRule (acm_journal, 'ACM-journal'). - - -get_journal_type (Engine, {any_publisher}) -> - T = ask_question ('Select the type (i)nternational/(n)ational): '), - case T of - "i" -> - eresye:add_rule (Engine, {journal_sample, intl_journal, 1}, 8); - "n" -> - eresye:add_rule (Engine, {journal_sample, national_journal, 1}, 8) - end. - - -get_publisher (Engine, {start, _}) - when not ["{publisher_selected}"]; true -> - Pub = ask_question ('Select the publisher (ieee/acm/any): '), - case Pub of - "ieee" -> - eresye:add_rule (Engine, {journal_sample, ieee_journal, 1}, 8), - eresye:assert (Engine, {publisher_selected}); - "acm" -> - eresye:add_rule (Engine, {journal_sample, acm_journal, 1}, 8), - eresye:assert (Engine, {publisher_selected}); - _ -> - eresye:assert (Engine, [{publisher_selected}, {any_publisher}]) - end. - - -get_if (Engine, {start, _}) when not ["{ifactor, _}"]; true-> - IF = ask_question ('What is your minimum impact factor: '), - eresye:assert (Engine, {ifactor, list_to_float (IF)}). - -get_topics (Engine, {start, _} = X) when not ["{topic, end_of_list}"]; true-> - Topic = ask_question ('Enter topic of your paper ("q" to end): '), - case Topic of - "q" -> eresye:assert (Engine, {topic, end_of_list}); - _ -> eresye:assert (Engine, {topic, list_to_atom (Topic)}), - eresye:retract (Engine, X), - eresye:assert (Engine, X) - end. - -final_rule (_, {start, Pid}) -> - Pid ! ok. - - -start () -> - eresye:start (js, journal), - - eresye:add_rule (js, {journal_sample, get_topics}, 10), - eresye:add_rule (js, {journal_sample, get_if}, 9), - eresye:add_rule (js, {journal_sample, get_publisher}, 9), - eresye:add_rule (js, {journal_sample, get_journal_type}, 9), - eresye:add_rule (js, {journal_sample, final_rule}, 1), - - eresye:assert (js, - [#'IEEE-journal' { title = 'Trans. on Soft. Eng.', - main_topic = 'any', - impact_factor = 0.6}, - #'IEEE-journal' { title = 'Trans. on PAMI', - main_topic = 'artificial intelligence', - impact_factor = 0.8}, - #'IEEE-journal' { title = 'Trans. on Parallel and ...', - main_topic = 'any', - impact_factor = 0.9}, - #'IEEE-journal' { title = 'Trans. on Mobile Computing', - main_topic = 'mobile systems', - impact_factor = 0.7}, - #'IEEE-journal' { title = 'Internet Computing', - main_topic = 'internet', - impact_factor = 0.9}, - #'ACM-journal' { title = 'Transaction on Internet Computing', - main_topic = 'internet', - impact_factor = 0.92}, - #'ACM-journal' { title = 'TOPLAS', - main_topic = 'programming languages', - impact_factor = 0.92}, - #'italian-journal' { title = 'Intelligenza Artificiale', - publisher = 'AI*IA', - main_topic = 'artificial intelligence', - impact_factor = 0.2}]), - eresye:assert (js, {start, self ()}), - receive - _ -> ok - end, - eresye:get_rete (js), - eresye:stop (js). - - +%% +%%journal_sample.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(journal_sample). + +-compile([export_all]). + +-include("journal.hrl"). + +- define ( AddDefaultRule ( Fun , Class ) , Fun ( _ , _ , _ , # Class { } ) -> ok ; Fun ( E , T , I , Y ) -> Fun ( E , T , I , journal : Class ( Y ) ) ) . + + +ask_question(Prompt) -> + lists:reverse(tl(lists:reverse(io:get_line(Prompt)))). + +national_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'national-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( national_journal , 'national-journal' ) . + + +intl_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'international-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( intl_journal , 'international-journal' ) . + + +ieee_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'IEEE-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( ieee_journal , 'IEEE-journal' ) . + + +acm_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'ACM-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( acm_journal , 'ACM-journal' ) . + + +get_journal_type(Engine, {any_publisher}) -> + T = + ask_question('Select the type (i)nternational/(n)ational): '), + case T of + "i" -> + eresye:add_rule(Engine, + {journal_sample, intl_journal, 1}, 8); + "n" -> + eresye:add_rule(Engine, + {journal_sample, national_journal, 1}, 8) + end. + +get_publisher(Engine, {start, _}) + when not ["{publisher_selected}"]; true -> + Pub = + ask_question('Select the publisher (ieee/acm/any): '), + case Pub of + "ieee" -> + eresye:add_rule(Engine, + {journal_sample, ieee_journal, 1}, 8), + eresye:assert(Engine, {publisher_selected}); + "acm" -> + eresye:add_rule(Engine, + {journal_sample, acm_journal, 1}, 8), + eresye:assert(Engine, {publisher_selected}); + _ -> + eresye:assert(Engine, + [{publisher_selected}, {any_publisher}]) + end. + +get_if(Engine, {start, _}) + when not ["{ifactor, _}"]; true -> + IF = + ask_question('What is your minimum impact factor: '), + eresye:assert(Engine, {ifactor, list_to_float(IF)}). + +get_topics(Engine, {start, _} = X) + when not ["{topic, end_of_list}"]; true -> + Topic = + ask_question('Enter topic of your paper ("q" to end): '), + case Topic of + "q" -> eresye:assert(Engine, {topic, end_of_list}); + _ -> + eresye:assert(Engine, {topic, list_to_atom(Topic)}), + eresye:retract(Engine, X), + eresye:assert(Engine, X) + end. + +final_rule(_, {start, Pid}) -> Pid ! ok. + +start() -> + eresye:start(js, journal), + eresye:add_rule(js, {journal_sample, get_topics}, 10), + eresye:add_rule(js, {journal_sample, get_if}, 9), + eresye:add_rule(js, {journal_sample, get_publisher}, 9), + eresye:add_rule(js, {journal_sample, get_journal_type}, + 9), + eresye:add_rule(js, {journal_sample, final_rule}, 1), + eresye:assert(js, + [#'IEEE-journal'{title = 'Trans. on Soft. Eng.', + main_topic = any, + impact_factor = 5.99999999999999977796e-1}, + #'IEEE-journal'{title = 'Trans. on PAMI', + main_topic = 'artificial intelligence', + impact_factor = 8.0e-1}, + #'IEEE-journal'{title = 'Trans. on Parallel and ...', + main_topic = any, impact_factor = 9.0e-1}, + #'IEEE-journal'{title = 'Trans. on Mobile Computing', + main_topic = 'mobile systems', + impact_factor = 6.99999999999999955591e-1}, + #'IEEE-journal'{title = 'Internet Computing', + main_topic = internet, + impact_factor = 9.0e-1}, + #'ACM-journal'{title = + 'Transaction on Internet Computing', + main_topic = internet, + impact_factor = 9.2e-1}, + #'ACM-journal'{title = 'TOPLAS', + main_topic = 'programming languages', + impact_factor = 9.2e-1}, + #'italian-journal'{title = 'Intelligenza Artificiale', + publisher = 'AI*IA', + main_topic = 'artificial intelligence', + impact_factor = 2.0e-1}]), + eresye:assert(js, {start, self()}), + receive _ -> ok end, + eresye:get_rete(js), + eresye:stop(js). diff --git a/examples/eresye/phil.erl b/examples/eresye/phil.erl index 3035ad4..3ba50f9 100644 --- a/examples/eresye/phil.erl +++ b/examples/eresye/phil.erl @@ -1,73 +1,70 @@ -% -% phil.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (phil). --compile ([export_all]). +%% +%%phil.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(phil). --define (N_PHIL, 5). +-compile([export_all]). -start () -> - eresye:start (restaurant), - phil_spawn (0). +-define(N_PHIL, 5). -phil_spawn (?N_PHIL) -> ok; -phil_spawn (N) -> - eresye:assert (restaurant, {fork, N}), - spawn (phil, philosopher, [N, init]), - if - N < (?N_PHIL - 1) -> - eresye:assert (restaurant, {room_ticket, N}); - true -> - ok - end, - phil_spawn (N + 1). +start() -> eresye:start(restaurant), phil_spawn(0). -philosopher (N, init) -> - new_seed (), - philosopher (N, ok); -philosopher (N, X) -> - think (N), - Ticket = eresye:wait_and_retract (restaurant, {room_ticket, '_'}), - eresye:wait_and_retract (restaurant, {fork, N}), - eresye:wait_and_retract (restaurant, {fork, (N + 1) rem ?N_PHIL}), - eat (N), - eresye:assert (restaurant, {fork, N}), - eresye:assert (restaurant, {fork, (N + 1) rem ?N_PHIL}), - eresye:assert (restaurant, Ticket), - philosopher (N, X). +phil_spawn(?N_PHIL) -> ok; +phil_spawn(N) -> + eresye:assert(restaurant, {fork, N}), + spawn(phil, philosopher, [N, init]), + if N < (?N_PHIL) - 1 -> + eresye:assert(restaurant, {room_ticket, N}); + true -> ok + end, + phil_spawn(N + 1). -think (N) -> - io:format ("~w: thinking ...~n", [N]), - timer:sleep (random:uniform (10) * 1000). +philosopher(N, init) -> new_seed(), philosopher(N, ok); +philosopher(N, X) -> + think(N), + Ticket = eresye:wait_and_retract(restaurant, + {room_ticket, '_'}), + eresye:wait_and_retract(restaurant, {fork, N}), + eresye:wait_and_retract(restaurant, + {fork, (N + 1) rem (?N_PHIL)}), + eat(N), + eresye:assert(restaurant, {fork, N}), + eresye:assert(restaurant, + {fork, (N + 1) rem (?N_PHIL)}), + eresye:assert(restaurant, Ticket), + philosopher(N, X). -eat (N) -> - io:format ("~w: eating ...~n", [N]), - timer:sleep (random:uniform (10) * 1000). +think(N) -> + io:format("~w: thinking ...~n", [N]), + timer:sleep(random:uniform(10) * 1000). +eat(N) -> + io:format("~w: eating ...~n", [N]), + timer:sleep(random:uniform(10) * 1000). new_seed() -> - {_,_,X} = erlang:now(), - {H,M,S} = time(), - H1 = H * X rem 32767, - M1 = M * X rem 32767, - S1 = S * X rem 32767, - put(random_seed, {H1,M1,S1}). + {_, _, X} = erlang:now(), + {H, M, S} = time(), + H1 = H * X rem 32767, + M1 = M * X rem 32767, + S1 = S * X rem 32767, + put(random_seed, {H1, M1, S1}). diff --git a/examples/eresye/prodcons.erl b/examples/eresye/prodcons.erl index d5975bb..3cc254a 100644 --- a/examples/eresye/prodcons.erl +++ b/examples/eresye/prodcons.erl @@ -1,52 +1,52 @@ -% -% prodcons.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (prodcons). +%% +%%prodcons.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(prodcons). --compile (export_all). +-compile(export_all). -start () -> - eresye:start (pc), - spawn (prodcons, cons_1, [1]), - spawn (prodcons, cons_1, [2]), - spawn (prodcons, cons_1, [3]), - spawn (prodcons, prod, [0]), - ok. +start() -> + eresye:start(pc), + spawn(prodcons, cons_1, [1]), + spawn(prodcons, cons_1, [2]), + spawn(prodcons, cons_1, [3]), + spawn(prodcons, prod, [0]), + ok. -prod (20) -> ok; -prod (Index) -> - eresye:assert (pc, {item, Index}), - prod (Index + 1). +prod(20) -> ok; +prod(Index) -> + eresye:assert(pc, {item, Index}), prod(Index + 1). -cons (20) -> ok;%eres:stop (pc); -cons (Index) -> - Fact = eresye:wait_and_retract (pc, {item, fun (X) -> X == Index end}), - %%eres:retract (pc, Fact), - io:format ("Consumer ~p~n", [Fact]), - cons (Index + 1). +cons(20) -> ok;%eres:stop (pc); +cons(Index) -> + Fact = eresye:wait_and_retract(pc, + {item, fun (X) -> X == Index end}), + %%eres:retract (pc, Fact), + io:format("Consumer ~p~n", [Fact]), + cons(Index + 1). -cons_1 (N) -> - Fact = eresye:wait_and_retract (pc, {item, '_'}), - %%eres:retract (pc, Fact), - io:format ("~w: Consumer ~p~n", [N, Fact]), - timer:sleep (random:uniform(500)), - cons_1 (N). +cons_1(N) -> + Fact = eresye:wait_and_retract(pc, {item, '_'}), + %%eres:retract (pc, Fact), + io:format("~w: Consumer ~p~n", [N, Fact]), + timer:sleep(random:uniform(500)), + cons_1(N). diff --git a/examples/eresye/relatives.erl b/examples/eresye/relatives.erl index 4daf8e0..412ae5c 100644 --- a/examples/eresye/relatives.erl +++ b/examples/eresye/relatives.erl @@ -1,103 +1,87 @@ -% -% relatives.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (relatives). --compile ([export_all]). +%% +%%relatives.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(relatives). + +-compile([export_all]). %% %% if (X is female) and (X is Y's parent) then (X is Y's mother) %% -mother (Engine, {female, X}, {parent, X, Y}) -> - eresye:assert (Engine, {mother, X, Y}). - +mother(Engine, {female, X}, {parent, X, Y}) -> + eresye:assert(Engine, {mother, X, Y}). %% %% if (X is male) and (X is Y's parent) then (X is Y's father) %% -father (Engine, {male, X}, {parent, X, Y}) -> - eresye:assert (Engine, {father, X, Y}). - - +father(Engine, {male, X}, {parent, X, Y}) -> + eresye:assert(Engine, {father, X, Y}). %% %% if (Y and Z have the same parent X) and (Z is female) %% then (Z is Y's sister) %% -sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> - eresye:assert (Engine, {sister, Z, Y}). - - +sister(Engine, {parent, X, Y}, {parent, X, Z}, + {female, Z}) + when Y =/= Z -> + eresye:assert(Engine, {sister, Z, Y}). %% %% if (Y and Z have the same parent X) and (Z is male) %% then (Z is Y's brother) %% -brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> - eresye:assert (Engine, {brother, Z, Y}). - +brother(Engine, {parent, X, Y}, {parent, X, Z}, + {male, Z}) + when Y =/= Z -> + eresye:assert(Engine, {brother, Z, Y}). %% %% if (X is Y's father) and (Y is Z's parent) %% then (X is Z's grandfather) %% -grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandfather, X, Z}). - +grandfather(Engine, {father, X, Y}, {parent, Y, Z}) -> + eresye:assert(Engine, {grandfather, X, Z}). %% %% if (X is Y's mother) and (Y is Z's parent) %% then (X is Z's grandmother) %% -grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandmother, X, Z}). - - - -start () -> - eresye:start (relatives), - lists:foreach (fun (X) -> - eresye:add_rule (relatives, {?MODULE, X}) - end, - [mother, father, - brother, sister, - grandfather, grandmother]), - - eresye:assert (relatives, - [{male, bob}, - {male, corrado}, - {male, mark}, - {male, caesar}, - {female, alice}, - {female, sara}, - {female, jane}, - {female, anna}, - {parent, jane, bob}, - {parent, corrado, bob}, - {parent, jane, mark}, - {parent, corrado, mark}, - {parent, jane, alice}, - {parent, corrado, alice}, - {parent, bob, caesar}, - {parent, bob, anna}, - {parent, sara, casear}, - {parent, sara, anna}]), - ok. +grandmother(Engine, {mother, X, Y}, {parent, Y, Z}) -> + eresye:assert(Engine, {grandmother, X, Z}). + +start() -> + eresye:start(relatives), + lists:foreach(fun (X) -> + eresye:add_rule(relatives, {?MODULE, X}) + end, + [mother, father, brother, sister, grandfather, + grandmother]), + eresye:assert(relatives, + [{male, bob}, {male, corrado}, {male, mark}, + {male, caesar}, {female, alice}, {female, sara}, + {female, jane}, {female, anna}, {parent, jane, bob}, + {parent, corrado, bob}, {parent, jane, mark}, + {parent, corrado, mark}, {parent, jane, alice}, + {parent, corrado, alice}, {parent, bob, caesar}, + {parent, bob, anna}, {parent, sara, casear}, + {parent, sara, anna}]), + ok. diff --git a/examples/eresye/sample.erl b/examples/eresye/sample.erl index 412a1da..d991603 100644 --- a/examples/eresye/sample.erl +++ b/examples/eresye/sample.erl @@ -1,70 +1,70 @@ -% -% sample.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (sample). --export ([rule/4, rule1/3, rule2/4, start/0, start1/0, start2/0]). +%% +%%sample.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(sample). + +-export([rule/4, rule1/3, rule2/4, start/0, start1/0, + start2/0]). -include("sample.hrl"). -rule (Engine, {hello, world}, {ciao, X}, {X, 10}) -> - io:format ("Hit!\n"), - ok. +rule(Engine, {hello, world}, {ciao, X}, {X, 10}) -> + io:format("Hit!\n"), ok. -rule1 (Engine, {hello, world}, {ciao, X} = F) -> - io:format ("Hit 1!\n"), - eresye:assert (Engine, {test}), - eresye:retract (Engine, F), - ok; +rule1(Engine, {hello, world}, {ciao, X} = F) -> + io:format("Hit 1!\n"), + eresye:assert(Engine, {test}), + eresye:retract(Engine, F), + ok; +rule1(Engine, {hello, world}, {test}) -> + io:format("Hit 2!\n"), ok. -rule1 (Engine, {hello, world}, {test}) -> - io:format ("Hit 2!\n"), - ok. +rule2(Engine, {hello, world}, #sample_record{a = Z} = X, + {mondo, Z}) -> + io:format("Hit 3! ~p\n", [X]), ok. -rule2 (Engine, {hello, world}, #sample_record { a = Z } = X, {mondo, Z}) -> - io:format ("Hit 3! ~p\n", [X]), - ok. +start() -> + eresye:start(myengine), + %% Z = fun (Engine, Fact) -> + %% io:format ("FUN!~p~n", [Fact]) + %% end, + %% gen_server:call (myengine, {add_rule, + %% {Z, 0}, + %% {["{ciao,mondo}"], []}}), + eresye:add_rule(myengine, {sample, rule2}), + eresye:assert(myengine, [{ciao, mondo}, {mondo, 20}]), + eresye:assert(myengine, {hello, world}), + eresye:assert(myengine, {ok, world}), + eresye:assert(myengine, #sample_record{a = 10, b = 50}), + %%eresye:add_rule (myengine, {sample, rule}), + %%eresye:add_rule (myengine, {sample, rule1}), + ok. -start () -> - eresye:start (myengine), -%% Z = fun (Engine, Fact) -> -%% io:format ("FUN!~p~n", [Fact]) -%% end, -%% gen_server:call (myengine, {add_rule, -%% {Z, 0}, -%% {["{ciao,mondo}"], []}}), - eresye:add_rule (myengine, {sample, rule2}), - eresye:assert (myengine, [{ciao, mondo}, {mondo, 20}]), - eresye:assert (myengine, {hello, world}), - eresye:assert (myengine, {ok, world}), - eresye:assert (myengine, #sample_record { a = 10, b = 50}), - %%eresye:add_rule (myengine, {sample, rule}), - %%eresye:add_rule (myengine, {sample, rule1}), - ok. -% spawn (sample, start2, []). +%% spawn (sample, start2, []). -start1 () -> - eresye:retract (myengine, {test}), - eresye:assert (myengine, {test}). +start1() -> + eresye:retract(myengine, {test}), + eresye:assert(myengine, {test}). -start2 () -> - F = eresye:wait (myengine, {ok, '_'}), - io:format ("Got it ~p~n", [F]). +start2() -> + F = eresye:wait(myengine, {ok, '_'}), + io:format("Got it ~p~n", [F]). diff --git a/examples/eresye/sieve.erl b/examples/eresye/sieve.erl index 9c89ccc..338440e 100644 --- a/examples/eresye/sieve.erl +++ b/examples/eresye/sieve.erl @@ -1,52 +1,53 @@ -% -% sieve.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (sieve). --compile ([export_all]). +%% +%%sieve.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(sieve). -remove_multiple (Engine, {X}, {Y}) when ((X rem Y) == 0) and (X =/= Y)-> - eresye:retract (Engine, {X}). +-compile([export_all]). -final_rule (Engine, {is, started} = X) - when not ["{is, finished}"];true -> - eresye:retract (Engine, X), - eresye:assert (Engine, {is, finished}). +remove_multiple(Engine, {X}, {Y}) + when (X rem Y == 0) and (X =/= Y) -> + eresye:retract(Engine, {X}). -start () -> - eresye:start (sieve), - eresye:assert (sieve, - [{X} || X <- lists:seq (2, 100)]), - eresye:assert (sieve, {is, started}), - eresye:add_rule (sieve, {sieve, remove_multiple}, 2), - eresye:add_rule (sieve, {sieve, final_rule}, 1), - Start = now(), - eresye:wait_and_retract (sieve, {is, finished}), - End = now(), - io:format ("KB: ~p~n", [eresye:get_kb (sieve)]), - io:format ("Rules fired: ~p~n", [{ok, R} = eresye:get_rules_fired (sieve)]), - D = timer:now_diff(End, Start), - io:format ("Time = ~p sec, ~p rules/sec, rule execution time ~p msec~n", - [D / 1000000.0, - R / (D / 1000000.0), - (D / 1000.0) / R]), - eresye:stop (sieve), - ok. +final_rule(Engine, {is, started} = X) + when not ["{is, finished}"]; true -> + eresye:retract(Engine, X), + eresye:assert(Engine, {is, finished}). + +start() -> + eresye:start(sieve), + eresye:assert(sieve, [{X} || X <- lists:seq(2, 100)]), + eresye:assert(sieve, {is, started}), + eresye:add_rule(sieve, {sieve, remove_multiple}, 2), + eresye:add_rule(sieve, {sieve, final_rule}, 1), + Start = now(), + eresye:wait_and_retract(sieve, {is, finished}), + End = now(), + io:format("KB: ~p~n", [eresye:get_kb(sieve)]), + io:format("Rules fired: ~p~n", + [{ok, R} = eresye:get_rules_fired(sieve)]), + D = timer:now_diff(End, Start), + io:format("Time = ~p sec, ~p rules/sec, rule execution " + "time ~p msec~n", + [D / 1.0e+6, R / (D / 1.0e+6), D / 1.0e+3 / R]), + eresye:stop(sieve), + ok. diff --git a/examples/eresye/wine.erl b/examples/eresye/wine.erl index f44df76..860de69 100644 --- a/examples/eresye/wine.erl +++ b/examples/eresye/wine.erl @@ -1,60 +1,45 @@ --module (wine). --include ("wine.hrl"). --export ([is_class/1, is_a/2, 'wine'/1,'redwine'/1, childof/1]). - -is_class ('wine_grape') -> true; -is_class ('wine') -> true; -is_class ('redwine') -> true; -is_class ('whitewine') -> true; -is_class ('Chianti') -> true; -is_class (_) -> false. - -is_a ('redwine','wine') -> true; -is_a ('whitewine','wine') -> true; -is_a ('Chianti','redwine') -> true; -is_a ('Chianti','wine') -> true; -is_a (_,_) -> false. - -childof ('wine_grape') -> []; -childof ('wine') -> [redwine,whitewine,'Chianti']; -childof ('redwine') -> ['Chianti']; -childof ('whitewine') -> []; -childof ('Chianti') -> []; -childof (_) -> exit (undef_class). - -'wine' (X = #'redwine'{}) -> - #'wine'{ - 'name' = X#'redwine'.'name', - 'body' = X#'redwine'.'body', - 'color' = X#'redwine'.'color', - 'flavor' = X#'redwine'.'flavor', - 'grape' = X#'redwine'.'grape', - 'sugar' = X#'redwine'.'sugar'}; - -'wine' (X = #'whitewine'{}) -> - #'wine'{ - 'name' = X#'whitewine'.'name', - 'body' = X#'whitewine'.'body', - 'color' = X#'whitewine'.'color', - 'flavor' = X#'whitewine'.'flavor', - 'grape' = X#'whitewine'.'grape', - 'sugar' = X#'whitewine'.'sugar'}; - -'wine' (X = #'Chianti'{}) -> - #'wine'{ - 'name' = X#'Chianti'.'name', - 'body' = X#'Chianti'.'body', - 'color' = X#'Chianti'.'color', - 'flavor' = X#'Chianti'.'flavor', - 'grape' = X#'Chianti'.'grape', - 'sugar' = X#'Chianti'.'sugar'}. - -'redwine' (X = #'Chianti'{}) -> - #'redwine'{ - 'name' = X#'Chianti'.'name', - 'body' = X#'Chianti'.'body', - 'color' = X#'Chianti'.'color', - 'flavor' = X#'Chianti'.'flavor', - 'grape' = X#'Chianti'.'grape', - 'sugar' = X#'Chianti'.'sugar'}. - +-module(wine). + +-include("wine.hrl"). + +-export([childof/1, is_a/2, is_class/1, redwine/1, + wine/1]). + +is_class(wine_grape) -> true; +is_class(wine) -> true; +is_class(redwine) -> true; +is_class(whitewine) -> true; +is_class('Chianti') -> true; +is_class(_) -> false. + +is_a(redwine, wine) -> true; +is_a(whitewine, wine) -> true; +is_a('Chianti', redwine) -> true; +is_a('Chianti', wine) -> true; +is_a(_, _) -> false. + +childof(wine_grape) -> []; +childof(wine) -> [redwine, whitewine, 'Chianti']; +childof(redwine) -> ['Chianti']; +childof(whitewine) -> []; +childof('Chianti') -> []; +childof(_) -> exit(undef_class). + +wine(X = #redwine{}) -> + #wine{name = X#redwine.name, body = X#redwine.body, + color = X#redwine.color, flavor = X#redwine.flavor, + grape = X#redwine.grape, sugar = X#redwine.sugar}; +wine(X = #whitewine{}) -> + #wine{name = X#whitewine.name, body = X#whitewine.body, + color = X#whitewine.color, flavor = X#whitewine.flavor, + grape = X#whitewine.grape, sugar = X#whitewine.sugar}; +wine(X = #'Chianti'{}) -> + #wine{name = X#'Chianti'.name, body = X#'Chianti'.body, + color = X#'Chianti'.color, flavor = X#'Chianti'.flavor, + grape = X#'Chianti'.grape, sugar = X#'Chianti'.sugar}. + +redwine(X = #'Chianti'{}) -> + #redwine{name = X#'Chianti'.name, + body = X#'Chianti'.body, color = X#'Chianti'.color, + flavor = X#'Chianti'.flavor, grape = X#'Chianti'.grape, + sugar = X#'Chianti'.sugar}. diff --git a/examples/eresye/wine_sample.erl b/examples/eresye/wine_sample.erl index 9c8b847..cb1f6dc 100644 --- a/examples/eresye/wine_sample.erl +++ b/examples/eresye/wine_sample.erl @@ -1,45 +1,42 @@ -% -% wine_sample.erl -% -% ------------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (wine_sample). +%% +%%wine_sample.erl +%% +%%------------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(wine_sample). --compile (export_all). --include ("wine.hrl"). +-compile(export_all). -start () -> - eresye:start (wine, wine), - eresye:add_rule (wine, {wine_sample, rule, 1}), - %eresye:assert (wine, #wine {name = "Vino"}), - eresye:assert (wine, #'Chianti' {}), - eresye:assert (wine, #'wine_grape' {}), - ok. +-include("wine.hrl"). -stop () -> - eresye:stop (wine). +start() -> + eresye:start(wine, wine), + eresye:add_rule(wine, {wine_sample, rule, 1}), + %%eresye:assert (wine, #wine {name = "Vino"}), + eresye:assert(wine, #'Chianti'{}), + eresye:assert(wine, #wine_grape{}), + ok. + +stop() -> eresye:stop(wine). %% rule (Engine, #wine{name = 'Vino'} = W) -> %% io:format ("~p~n", [W]); -rule (Engine, #wine{} = W) -> - io:format ("~p~n", [W]); - -rule (Engine, W) -> - io:format ("~p~n", [W]). +rule(Engine, #wine{} = W) -> io:format("~p~n", [W]); +rule(Engine, W) -> io:format("~p~n", [W]). diff --git a/examples/jade/exat_agent.erl b/examples/jade/exat_agent.erl old mode 100755 new mode 100644 index 70532c7..b122490 --- a/examples/jade/exat_agent.erl +++ b/examples/jade/exat_agent.erl @@ -1,34 +1,39 @@ -module(exat_agent). + -export([extends/0]). --export([pattern/2,event/2,action/2,on_starting/1, - do_request/4,start/0]). + +-export([action/2, do_request/4, event/2, on_starting/1, + pattern/2, start/0]). -include_lib("exat/include/acl.hrl"). --include_lib("exat/include/fipa_ontology.hrl"). -extends()-> nil. +-include_lib("exat/include/fipa_ontology.hrl"). -pattern(Self, request)-> [#aclmessage{speechact='REQUEST'}]. +extends() -> nil. -event(Self, evt_request)-> {acl, request}. +pattern(Self, request) -> + [#aclmessage{speechact = 'REQUEST'}]. -action(Self, start)-> {evt_request, do_request}. +event(Self, evt_request) -> {acl, request}. -fellow_agent()-> #'agent-identifier'{ - name = "jadeagent@jadeplatform", - addresses = ["http://localhost:7778/acc"]}. +action(Self, start) -> {evt_request, do_request}. -on_starting(Self)-> - io:format("[Agent:~w] Starting\n", [object:agentof(Self)]), - acl:sendacl(#aclmessage{speechact = 'REQUEST', - content = "ping", sender = Self, - receiver = fellow_agent()}). +fellow_agent() -> + #'agent-identifier'{name = "jadeagent@jadeplatform", + addresses = ["http://localhost:7778/acc"]}. -do_request(Self, EventName, Message, ActionName)-> - io:format("[Agent:~w] Request received from agent ~p\n", - [object:agentof(Self), Message#aclmessage.sender]), - object:do(Self, start). +on_starting(Self) -> + io:format("[Agent:~w] Starting\n", + [object:agentof(Self)]), + acl:sendacl(#aclmessage{speechact = 'REQUEST', + content = "ping", sender = Self, + receiver = fellow_agent()}). -start()-> - agent:new(the_exat_agent,[{behaviour, exat_agent}]). +do_request(Self, EventName, Message, ActionName) -> + io:format("[Agent:~w] Request received from agent " + "~p\n", + [object:agentof(Self), Message#aclmessage.sender]), + object:do(Self, start). +start() -> + agent:new(the_exat_agent, [{behaviour, exat_agent}]). diff --git a/examples/original_exat/pingagent.erl b/examples/original_exat/pingagent.erl index 2bd21fa..e225b69 100644 --- a/examples/original_exat/pingagent.erl +++ b/examples/original_exat/pingagent.erl @@ -1,72 +1,69 @@ -% -% pingagent.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% -% -%------------------------------------------- -% THIS IS THE AGENTCITIES PING AGENT -%------------------------------------------- -% --module (pingagent). --export ([extends/0, - pattern/2, - event/2, - action/2, - on_starting/1, - get_ping_proc/4, - start/0]). --include ("acl.hrl"). +%% +%%pingagent.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +%% +%%------------------------------------------- +%%THIS IS THE AGENTCITIES PING AGENT +%%------------------------------------------- +%% +-module(pingagent). + +-export([action/2, event/2, extends/0, get_ping_proc/4, + on_starting/1, pattern/2, start/0]). -extends () -> nil. +-include("acl.hrl"). -action (Self, start) -> [{acl_event, get_ping_proc}]. +extends() -> nil. -event (Self, acl_event) -> {acl, all_pattern}. +action(Self, start) -> [{acl_event, get_ping_proc}]. -pattern (Self, all_pattern) -> [#aclmessage {}]. +event(Self, acl_event) -> {acl, all_pattern}. +pattern(Self, all_pattern) -> [#aclmessage{}]. %% %% %% -on_starting (Self) -> - logger:start ('PING-AGENT'). +on_starting(Self) -> logger:start('PING-AGENT'). %% %% get the ping message %% -get_ping_proc (Self, Event, Msg = #aclmessage {speechact = 'QUERY-REF', - content = "ping"}, - Action) -> - logger:log ('PING-AGENT', "Received PING MESSAGE"), - acl:reply (Msg, 'INFORM', "alive"); -%% +get_ping_proc(Self, Event, + Msg = #aclmessage{speechact = 'QUERY-REF', + content = "ping"}, + Action) -> + logger:log('PING-AGENT', "Received PING MESSAGE"), + acl:reply(Msg, 'INFORM', "alive"); %% %% -get_ping_proc (Self, Event, Msg, Action) -> - logger:log ('PING-AGENT', {"Received ~p, NOT UNDERSTOOD", [Msg]}), - acl:reply (Msg, 'NOT-UNDERSTOOD', Msg#aclmessage.content). %% +get_ping_proc(Self, Event, Msg, Action) -> + logger:log('PING-AGENT', + {"Received ~p, NOT UNDERSTOOD", [Msg]}), + acl:reply(Msg, 'NOT-UNDERSTOOD', + Msg#aclmessage.content).%% %% %% -start () -> - agent:new (pingagent, [{behaviour, pingagent}]). +start() -> + agent:new(pingagent, [{behaviour, pingagent}]). diff --git a/examples/original_exat/pingeragent.erl b/examples/original_exat/pingeragent.erl index 7aa914d..8800b8d 100644 --- a/examples/original_exat/pingeragent.erl +++ b/examples/original_exat/pingeragent.erl @@ -1,116 +1,114 @@ -% -% pingeragent.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% -% -%------------------------------------------- -% THIS IS THE AGENTCITIES PINGER AGENT -%------------------------------------------- -% --module (pingeragent). --export ([extends/0, - pattern/2, - event/2, - action/2, - on_starting/1, - send_ping_proc/4, - wait_pong_proc/4, - start/0]). --include ("acl.hrl"). --include ("fipa_ontology.hrl"). +%% +%%pingeragent.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +%% +%%------------------------------------------- +%%THIS IS THE AGENTCITIES PINGER AGENT +%%------------------------------------------- +%% +-module(pingeragent). -extends () -> nil. +-export([action/2, event/2, extends/0, on_starting/1, + pattern/2, send_ping_proc/4, start/0, + wait_pong_proc/4]). -action (Self, start) -> [{timeout_event, send_ping_proc}]; -action (Self, wait_pong) -> [{acl_event, wait_pong_proc}]. +-include("acl.hrl"). -event (Self, timeout_event) -> {timeout, to_value}; -event (Self, acl_event) -> {acl, all_pattern}. +-include("fipa_ontology.hrl"). -pattern (Self, to_value) -> 1000; -pattern (Self, all_pattern) -> [#aclmessage {}]. +extends() -> nil. +action(Self, start) -> + [{timeout_event, send_ping_proc}]; +action(Self, wait_pong) -> + [{acl_event, wait_pong_proc}]. + +event(Self, timeout_event) -> {timeout, to_value}; +event(Self, acl_event) -> {acl, all_pattern}. + +pattern(Self, to_value) -> 1000; +pattern(Self, all_pattern) -> [#aclmessage{}]. %% %% %% -on_starting (Self) -> - logger:start ('PINGER'), - case exat:get_argument ('destagent') of - {ok, [PingedAgent]} -> - {ID, ADR} = lists:splitwith (fun (X) -> X =/= $, end, PingedAgent), - AgentID = case ADR of - [] -> PingedAgent; - [$, | ADDR] -> #'agent-identifier' { name = ID, - addresses = [ADDR] } - end, - object:set (Self, 'destagent', AgentID); - _ -> - logger:log ('PINGER', {"Invalid destination agent. Use '-destagent name,mtp_address", []}), - object:set (Self, 'destagent', none) - end. - - +on_starting(Self) -> + logger:start('PINGER'), + case exat:get_argument(destagent) of + {ok, [PingedAgent]} -> + {ID, ADR} = lists:splitwith(fun (X) -> X =/= $, end, + PingedAgent), + AgentID = case ADR of + [] -> PingedAgent; + [$, | ADDR] -> + #'agent-identifier'{name = ID, addresses = [ADDR]} + end, + object:set(Self, destagent, AgentID); + _ -> + logger:log('PINGER', + {"Invalid destination agent. Use '-destagent " + "name,mtp_address", + []}), + object:set(Self, destagent, none) + end. %% %% get the ping message %% -send_ping_proc (Self, Event, _, Action) -> - Dest = object:get (Self, 'destagent'), - if - Dest == none -> object:stop (Self); - true -> - object:set (Self, 'timestamp', erlang:now ()), - acl:query_ref (#aclmessage { sender = Self, - receiver = Dest, - content = "ping" }), - object:do (Self, wait_pong) - end. +send_ping_proc(Self, Event, _, Action) -> + Dest = object:get(Self, destagent), + if Dest == none -> object:stop(Self); + true -> + object:set(Self, timestamp, erlang:now()), + acl:query_ref(#aclmessage{sender = Self, + receiver = Dest, content = "ping"}), + object:do(Self, wait_pong) + end. + %% %% %% - - %% %% wait the 'alive' message %% -wait_pong_proc (Self, Event, Msg = #aclmessage {speechact = 'INFORM'}, - Action) -> - T1 = erlang:now (), - T0 = object:get (Self, 'timestamp'), - Diff = timer:now_diff (T1, T0) / 1000.0, - logger:log ('PINGER', {"Received MESSAGE ~p, Elapsed ~p ms", - [Msg#aclmessage.content, Diff]}), - object:do (Self, start); +wait_pong_proc(Self, Event, + Msg = #aclmessage{speechact = 'INFORM'}, Action) -> + T1 = erlang:now(), + T0 = object:get(Self, timestamp), + Diff = timer:now_diff(T1, T0) / 1.0e+3, + logger:log('PINGER', + {"Received MESSAGE ~p, Elapsed ~p ms", + [Msg#aclmessage.content, Diff]}), + object:do(Self, start); %% %% %% -wait_pong_proc (Self, Event, Msg, Action) -> - logger:log ('PINGER', {"BAD MESSAGE ~p", [Msg#aclmessage.content]}), - object:do (Self, start). +wait_pong_proc(Self, Event, Msg, Action) -> + logger:log('PINGER', + {"BAD MESSAGE ~p", [Msg#aclmessage.content]}), + object:do(Self, start).%% %% -%% - %% -start () -> - agent:new (pingeragent, [{behaviour, pingeragent}]). +start() -> + agent:new(pingeragent, [{behaviour, pingeragent}]). diff --git a/examples/simple/simple_pingagent.erl b/examples/simple/simple_pingagent.erl index f178118..d799e71 100644 --- a/examples/simple/simple_pingagent.erl +++ b/examples/simple/simple_pingagent.erl @@ -2,59 +2,46 @@ -behaviour(simple_agent). --export([stop/0, start/0]). % API - --export([ - init/2, - handle_acl/2, - handle_call/3, - handle_cast/2, - handle_info/2, - terminate/2, - code_change/3 - ]). +-export([start/0, stop/0]). % API + +-export([code_change/3, handle_acl/2, handle_call/3, + handle_cast/2, handle_info/2, init/2, terminate/2]). -include("acl.hrl"). + -include("fipa_ontology.hrl"). -% API +%%API -start() -> - simple_agent:new(pingagent, ?MODULE, []). -stop() -> - simple_agent:stop(pingagent). +start() -> simple_agent:new(pingagent, ?MODULE, []). +stop() -> simple_agent:stop(pingagent). -% agents callback +%%agents callback handle_acl(#aclmessage{speechact = 'QUERY-REF', - sender = Sender, - content = "ping"} = Msg, State) -> - io:format("Got ping query from ~p: ~p~n~nInforming that I'm alive!~n~n", [Sender, Msg]), - spawn(fun() -> acl:reply(Msg, 'INFORM', "alive") end), + sender = Sender, content = "ping"} = + Msg, + State) -> + io:format("Got ping query from ~p: ~p~n~nInforming " + "that I'm alive!~n~n", + [Sender, Msg]), + spawn(fun () -> acl:reply(Msg, 'INFORM', "alive") end), {noreply, State}; - handle_acl(#aclmessage{} = Msg, State) -> {noreply, State}. - - %% gen_server callbacks -init(Name, _Params) -> - {ok, Name}. +init(Name, _Params) -> {ok, Name}. handle_call(Call, _From, State) -> {reply, {error, unknown_call}, State}. -handle_cast(_Call, State) -> - {noreply, State}. +handle_cast(_Call, State) -> {noreply, State}. -handle_info(Msg, State) -> - {noreply, State}. +handle_info(Msg, State) -> {noreply, State}. -code_change(_, _, _) -> - ok. +code_change(_, _, _) -> ok. -terminate(_, _) -> - ok. +terminate(_, _) -> ok. diff --git a/examples/simple/simple_pingeragent.erl b/examples/simple/simple_pingeragent.erl index 6914c0c..c7545b6 100644 --- a/examples/simple/simple_pingeragent.erl +++ b/examples/simple/simple_pingeragent.erl @@ -2,71 +2,56 @@ -behaviour(simple_agent). --export([stop/0, start/0]). % API - --export([ - init/2, - handle_acl/2, - handle_call/3, - handle_cast/2, - handle_info/2, - terminate/2, - code_change/3 - ]). +-export([start/0, stop/0]). % API + +-export([code_change/3, handle_acl/2, handle_call/3, + handle_cast/2, handle_info/2, init/2, terminate/2]). -include("acl.hrl"). + -include("fipa_ontology.hrl"). -% API +%%API start() -> - simple_agent:new(pingeragent, ?MODULE, [{"localhost", 7778, "pingagent"}]). -stop() -> - simple_agent:stop(pingeragent). + simple_agent:new(pingeragent, ?MODULE, + [{"localhost", 7778, "pingagent"}]). +stop() -> simple_agent:stop(pingeragent). -% agents callback +%%agents callback handle_acl(#aclmessage{speechact = 'INFORM', - content = "alive"} = Msg, {_, DestAgent} = State) -> - io:format("~p is alive, since I got: ~p~n~n", [DestAgent, Msg]), + content = "alive"} = + Msg, + {_, DestAgent} = State) -> + io:format("~p is alive, since I got: ~p~n~n", + [DestAgent, Msg]), {noreply, State}; - handle_acl(#aclmessage{} = Msg, State) -> {noreply, State}. - - %% gen_server callbacks init(Name, [DestAgent]) -> - timer:send_interval(500, ping), - {ok, {Name, DestAgent}}. + timer:send_interval(500, ping), {ok, {Name, DestAgent}}. handle_call(Call, _From, State) -> {reply, {error, unknown_call}, State}. -handle_cast(_Call, State) -> - {noreply, State}. - +handle_cast(_Call, State) -> {noreply, State}. handle_info(ping, {SelfName, DestAgent} = State) -> {Ip, Port, Name} = DestAgent, - Addr = lists:flatten(io_lib:format("http://~s:~b", [Ip, Port])), + Addr = lists:flatten(io_lib:format("http://~s:~b", + [Ip, Port])), Dest = #'agent-identifier'{name = Name, addresses = [Addr]}, PingMsg = #aclmessage{sender = SelfName, - receiver = Dest, - content = "ping"}, - spawn(fun() -> - Resp = acl:query_ref(PingMsg) - end), + receiver = Dest, content = "ping"}, + spawn(fun () -> Resp = acl:query_ref(PingMsg) end), {noreply, State}; +handle_info(Msg, State) -> {noreply, State}. -handle_info(Msg, State) -> - {noreply, State}. - -code_change(_, _, _) -> - ok. +code_change(_, _, _) -> ok. -terminate(_, _) -> - ok. +terminate(_, _) -> ok. diff --git a/src/acl.erl b/src/acl.erl index b95e0fc..22f7619 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -1,382 +1,323 @@ -% -% acl.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (acl). --export ([parse_message/1, - sl0_getcontent/1, - sl0_parse/1, - sl0_parsecontent/1, - sl0_getslot/2, - erlang_to_sl0/1, - - sendacl/1, - inform/1, - ask_if/1, - call_for_proposal/1, - propose/1, - accept_proposal/1, - reject_proposal/1, - refuse/1, - request/1, - query_if/1, - query_ref/1, - reply/3, - - ensure_list/1, - refinepattern/2, - refinepattern/4, - hexlify/1, - unhexlify/1]). - --author ('csanto@diit.unict.it'). --include ("object.hrl"). --include ("acl.hrl"). --include ("fipa_ontology.hrl"). - --define (ACL_REPRESENTATION, acl_erl_native). - - - - -erl_to_sl0 ([], Acc) -> - lists:flatten (lists:reverse ([ ")" | Acc])); - -erl_to_sl0 ([{Slotname, SlotValue} | Tail], Acc) -> - erl_to_sl0 (Tail, - [ " ", erlang_to_sl0 (SlotValue), " " , - atom_to_list (Slotname), ":" - | Acc]); - -erl_to_sl0 ([Head | Tail], Acc) -> - ZHead = if - is_atom (Head) -> atom_to_list (Head); - is_list (Head) -> erlang_to_sl0 (Head); - true -> Head - end, - erl_to_sl0 (Tail, [ " " , ZHead | Acc]); - -erl_to_sl0 (Value, Acc) when is_atom (Value) -> - atom_to_list (Value). - - -%%% -erlang_to_sl0 (ErlangSentence) when is_atom (ErlangSentence) -> - atom_to_list (ErlangSentence); -erlang_to_sl0 ([$#, $s, $# | Tail]) -> - Tail; -erlang_to_sl0 (ErlangSentence) -> - erl_to_sl0 (ErlangSentence, ["("]). - - -%%% -sl0_parse (M) -> - S = aclscanner:scan (M), - T = aclscanner:tokenize (S), - aclparser:parse (T). -%% returns {error, ErrorCond} or {ok, Terms} - -sl0_getslot (SearchedSlotname, []) -> ?ACL_ANY; -sl0_getslot (SearchedSlotname, [{SlotName, SlotValue} | MessageTail]) -when SlotName == SearchedSlotname -> - SlotValue; -sl0_getslot (SearchedSlotname, [_ | MessageTail]) -> - sl0_getslot (SearchedSlotname, MessageTail). - -sl0_getcontent (M) -> - atom_to_list (sl0_getslot (content, M)). - - -islowercase ([]) -> true; -islowercase ([H|T]) -> islowercase (H) and islowercase (T); -islowercase (H) when not is_list(H) -> (H >= $a) and (H =< $z). - -tolower (H) -> H + 32. - -lowcase ([]) -> []; -lowcase ([H | T]) when (H >= $A) and (H =< $Z) -> [tolower (H) | lowcase (T)]; -lowcase ([H | T]) -> [H | lowcase (T)]. - - - -parse_message (M) -> - {ok, [SpeechAct | Slots]} = sl0_parse (M), - LSpeechAct = list_to_atom (lowcase (atom_to_list (SpeechAct))), - Message = #aclmessage { speechact = LSpeechAct, - sender = translate_agent_identifier ( - sl0_getslot (sender, Slots)), - receiver = translate_receiver_agent_identifier ( - sl0_getslot (receiver, Slots)), - 'reply-to' = sl0_getslot ('reply-to', Slots), - content = sl0_getslot (content, Slots), - language = sl0_getslot (language, Slots), - encoding = sl0_getslot (encoding, Slots), - ontology = sl0_getslot (ontology, Slots), - protocol = sl0_getslot (protocol, Slots), - 'conversation-id' = sl0_getslot ('conversation-id', - Slots), - 'reply-with' = sl0_getslot ('reply-with', Slots), - 'in-reply-to' = sl0_getslot ('in-reply-to', Slots), - 'reply-by' = sl0_getslot ('reply-by',Slots) - }, - Message. - - -sl0_parsecontent (M) -> - sl0_parse (ensure_list (M#aclmessage.content)). - - -translate_agent_identifier (ID = ['agent-identifier' | _]) -> - sl_to_erlang_agent_identifier (ID); -translate_agent_identifier (ID) -> ID. - -translate_receiver_agent_identifier (['set' | Set]) -> - FIPA_ID_Set = [ sl_to_erlang_agent_identifier (X) || X <- Set]; -translate_receiver_agent_identifier (ID) -> - translate_agent_identifier (ID). - -sl_to_erlang_agent_identifier (['agent-identifier', - {name, Name}, - {addresses, Addresses}]) -> - [Adr | _] = sl_sequence_to_erlang (Addresses), - #'agent-identifier' { name = Name, addresses = Adr}. - - -erlang_to_erlang_sl_agent_identifier (AgentIdentifier) - when record (AgentIdentifier, 'agent-identifier') -> - ['agent-identifier', - {name, AgentIdentifier#'agent-identifier'.name}, - {addresses, ['sequence', - AgentIdentifier#'agent-identifier'.addresses]}]; -erlang_to_erlang_sl_agent_identifier (AgentIdentifier) -> - erl_sl0_to_atom (AgentIdentifier). - - -sl_sequence_to_erlang (['sequence' | X]) -> X. - -to_list (X) when is_atom (X) -> atom_to_list (X); -to_list (X) -> X. - -ensure_list (X) -> to_list (X). - -erl_sl0_to_atom (X) when is_list (X) -> list_to_atom (erlang_to_sl0 (X)); -erl_sl0_to_atom (X) -> X. - - -remove_nihils ([], Acc) -> - lists:reverse (Acc); - -remove_nihils ([{SlotName, ?ACL_ANY} | Tail], Acc) -> - remove_nihils (Tail, Acc); - -remove_nihils ([{SlotName, SlotValue} | Tail], Acc) -> - remove_nihils (Tail, [{SlotName, SlotValue} | Acc]). - -remove_nihils (List) -> - remove_nihils (List, []). - - -% -% Speech Act Library -% - -% if the ID is an object, get the associated agent -encode_agent_identifier (Identifier) when record (Identifier, object) -> - encode_agent_identifier (object:agentof (Identifier)); - -% if the ID is an atom (i.e. agent/process name), transform it into a string -encode_agent_identifier (Identifier) when is_atom (Identifier) -> - encode_agent_identifier (atom_to_list (Identifier)); - -% if the ID is a string, transform it into a #agent-identifier -encode_agent_identifier (Identifier) when is_list (Identifier) -> - case sl:isString (Identifier) of - true -> - {ID, HAP} = exat:split_agent_identifier (Identifier), - #'agent-identifier' { name = lists:flatten ([ID, "@", HAP]), - addresses = mtp:addresses ()}; - false -> - [ encode_agent_identifier (X) || X <- Identifier] - end; - -encode_agent_identifier (Default) -> Default. - - - - -sendacl (Message) -> - Sender = encode_agent_identifier (Message#aclmessage.sender), - R = encode_agent_identifier (Message#aclmessage.receiver), - Receivers = - if - is_list (R) -> R; - true -> [R] - end, - - %%io:format ("Sender ~w~n", [Sender]), - %%io:format ("Receivers ~w~n", [Receivers]), - - %% encode content - EncodedContent = "\"" ++ - case ontology_service:get_codec (Message#aclmessage.ontology) of - {ok, Codec} -> - SL = Codec:encode (Message#aclmessage.content), - sl:encode (SL); - _ -> Message#aclmessage.content - end ++ "\"", - - [_ | Temp] = tuple_to_list (Message#aclmessage { - sender = Sender, - receiver = Receivers, - content = EncodedContent }), - TransformedMessage = list_to_tuple (Temp), - [mtp:http_mtp_encode_and_send (X, Sender, TransformedMessage) - || X <- Receivers], - ok. - - -inform (Message) -> - sendacl (Message#aclmessage {speechact = 'INFORM'}). - -ask_if (Message) -> - sendacl (Message#aclmessage {speechact = 'ASK-IF'}). - -call_for_proposal (Message) -> - sendacl (Message#aclmessage {speechact = 'CFP'}). - -propose (Message) -> - sendacl (Message#aclmessage {speechact = 'PROPOSE'}). - -accept_proposal (Message) -> - sendacl (Message#aclmessage {speechact = 'ACCEPT-PROPOSAL'}). - -reject_proposal (Message) -> - sendacl (Message#aclmessage {speechact = 'REJECT-PROPOSAL'}). - -refuse (Message) -> - sendacl (Message#aclmessage {speechact = 'REFUSE'}). - -request (Message) -> - sendacl (Message#aclmessage {speechact = 'REQUEST'}). - -query_if (Message) -> - sendacl (Message#aclmessage {speechact = 'QUERY-IF'}). - -query_ref (Message) -> - sendacl (Message#aclmessage {speechact = 'QUERY-REF'}). - -reply (Request, NewSpeechAct, NewContent) -> - Receiver = - if - Request#aclmessage.'reply-to' == ?ACL_ANY -> - Request#aclmessage.sender; - true -> - Request#aclmessage.'reply-to' - end, - sendacl (Request#aclmessage - {speechact = NewSpeechAct, - sender = Request#aclmessage.receiver, - receiver = Receiver, - 'in-reply-to' = Request#aclmessage.'reply-with', - content = NewContent}). - -% -% pattern library -% -unify_atoms (?ACL_ANY, ?ACL_ANY) -> ?ACL_ANY; -unify_atoms (A1, ?ACL_ANY) -> A1; -unify_atoms (?ACL_ANY, A2) -> A2; -unify_atoms (A1, A2) -> A2. - -unify_patterns ([], [], Acc) -> - lists:reverse (Acc); -unify_patterns ( [H1 | T1], [H2 | T2] , Acc) -> - unify_patterns (T1, T2, [ unify_atoms (H1, H2) | Acc]). - -refinepattern (BasePattern, RefiningPattern) -> - LBasePattern = tuple_to_list (BasePattern), - LRefiningPattern = tuple_to_list (RefiningPattern), - L1 = length (LBasePattern), - L2 = length (LRefiningPattern), - if - L1 =/= L2 -> exit ({badarg,'pattern lengths differ'}); - true -> - list_to_tuple (unify_patterns (LBasePattern, LRefiningPattern, [])) - end. - - -refinepattern (Object, PatternName, Index, RefiningPattern) -> - PatternList = object:super (Object, pattern, [PatternName]), - lists:sublist (PatternList, Index - 1) ++ - [refinepattern (lists:nth (Index, PatternList), RefiningPattern)] ++ - lists:nthtail (Index, PatternList). - - -% -% acl utils -% -hexlify ([]) -> ""; -hexlify ([H | T]) -> - %[Z | _] = io_lib:format ("~.16B", [H]), - hexof (H) ++ hexlify (T). - -unhexlify ([]) -> ""; -unhexlify ([H1, H2 | T]) -> - Int = hexdigit (H1) * 16 + hexdigit (H2), - [Int | unhexlify (T)]. - -hexof (X) -> - Z = tohex (X div 16) ++ tohex (X rem 16), - Z. - -tohex (0) -> "0"; -tohex (1) -> "1"; -tohex (2) -> "2"; -tohex (3) -> "3"; -tohex (4) -> "4"; -tohex (5) -> "5"; -tohex (6) -> "6"; -tohex (7) -> "7"; -tohex (8) -> "8"; -tohex (9) -> "9"; -tohex (10) -> "A"; -tohex (11) -> "B"; -tohex (12) -> "C"; -tohex (13) -> "D"; -tohex (14) -> "E"; -tohex (15) -> "F". - -hexdigit ($0) -> 0; -hexdigit ($1) -> 1; -hexdigit ($2) -> 2; -hexdigit ($3) -> 3; -hexdigit ($4) -> 4; -hexdigit ($5) -> 5; -hexdigit ($6) -> 6; -hexdigit ($7) -> 7; -hexdigit ($8) -> 8; -hexdigit ($9) -> 9; -hexdigit ($A) -> 10; -hexdigit ($B) -> 11; -hexdigit ($C) -> 12; -hexdigit ($D) -> 13; -hexdigit ($E) -> 14; -hexdigit ($F) -> 15. +%% +%% acl.erl +%% +%% ---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(acl). + +-export([accept_proposal/1, ask_if/1, + call_for_proposal/1, ensure_list/1, erlang_to_sl0/1, + hexlify/1, inform/1, parse_message/1, propose/1, + query_if/1, query_ref/1, refinepattern/2, + refinepattern/4, refuse/1, reject_proposal/1, reply/3, + request/1, sendacl/1, sl0_getcontent/1, sl0_getslot/2, + sl0_parse/1, sl0_parsecontent/1, unhexlify/1]). + +-author('csanto@diit.unict.it'). + +-include("object.hrl"). + +-include("acl.hrl"). + +-include("fipa_ontology.hrl"). + +-define(ACL_REPRESENTATION, acl_erl_native). + +erl_to_sl0([], Acc) -> + lists:flatten(lists:reverse([")" | Acc])); +erl_to_sl0([{Slotname, SlotValue} | Tail], Acc) -> + erl_to_sl0(Tail, + [" ", erlang_to_sl0(SlotValue), " ", + atom_to_list(Slotname), ":" + | Acc]); +erl_to_sl0([Head | Tail], Acc) -> + ZHead = if is_atom(Head) -> atom_to_list(Head); + is_list(Head) -> erlang_to_sl0(Head); + true -> Head + end, + erl_to_sl0(Tail, [" ", ZHead | Acc]); +erl_to_sl0(Value, Acc) when is_atom(Value) -> + atom_to_list(Value). + +%%% +erlang_to_sl0(ErlangSentence) + when is_atom(ErlangSentence) -> + atom_to_list(ErlangSentence); +erlang_to_sl0([$#, $s, $# | Tail]) -> Tail; +erlang_to_sl0(ErlangSentence) -> + erl_to_sl0(ErlangSentence, ["("]). + +%%% +sl0_parse(M) -> + S = aclscanner:scan(M), + T = aclscanner:tokenize(S), + aclparser:parse(T). + +%% returns {error, ErrorCond} or {ok, Terms} + +sl0_getslot(SearchedSlotname, []) -> ?ACL_ANY; +sl0_getslot(SearchedSlotname, + [{SlotName, SlotValue} | MessageTail]) + when SlotName == SearchedSlotname -> + SlotValue; +sl0_getslot(SearchedSlotname, [_ | MessageTail]) -> + sl0_getslot(SearchedSlotname, MessageTail). + +sl0_getcontent(M) -> + atom_to_list(sl0_getslot(content, M)). + +tolower(H) -> H + 32. + +lowcase([]) -> []; +lowcase([H | T]) when (H >= $A) and (H =< $Z) -> + [tolower(H) | lowcase(T)]; +lowcase([H | T]) -> [H | lowcase(T)]. + +parse_message(M) -> + {ok, [SpeechAct | Slots]} = sl0_parse(M), + LSpeechAct = + list_to_atom(lowcase(atom_to_list(SpeechAct))), + Message = #aclmessage{speechact = LSpeechAct, + sender = + translate_agent_identifier(sl0_getslot(sender, + Slots)), + receiver = + translate_receiver_agent_identifier(sl0_getslot(receiver, + Slots)), + 'reply-to' = sl0_getslot('reply-to', Slots), + content = sl0_getslot(content, Slots), + language = sl0_getslot(language, Slots), + encoding = sl0_getslot(encoding, Slots), + ontology = sl0_getslot(ontology, Slots), + protocol = sl0_getslot(protocol, Slots), + 'conversation-id' = + sl0_getslot('conversation-id', Slots), + 'reply-with' = sl0_getslot('reply-with', Slots), + 'in-reply-to' = sl0_getslot('in-reply-to', Slots), + 'reply-by' = sl0_getslot('reply-by', Slots)}, + Message. + +sl0_parsecontent(M) -> + sl0_parse(ensure_list(M#aclmessage.content)). + +translate_agent_identifier(ID = ['agent-identifier' + | _]) -> + sl_to_erlang_agent_identifier(ID); +translate_agent_identifier(ID) -> ID. + +translate_receiver_agent_identifier([set | Set]) -> + FIPA_ID_Set = [sl_to_erlang_agent_identifier(X) + || X <- Set]; +translate_receiver_agent_identifier(ID) -> + translate_agent_identifier(ID). + +sl_to_erlang_agent_identifier(['agent-identifier', + {name, Name}, {addresses, Addresses}]) -> + [Adr | _] = sl_sequence_to_erlang(Addresses), + #'agent-identifier'{name = Name, addresses = Adr}. + +sl_sequence_to_erlang([sequence | X]) -> X. + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + +ensure_list(X) -> to_list(X). + +%% +%% Speech Act Library +%% + +%% if the ID is an object, get the associated agent +encode_agent_identifier(Identifier) + when is_record(Identifier, object) -> + encode_agent_identifier(object:agentof(Identifier)); +%% if the ID is an atom (i.e. agent/process name), transform it into a string +encode_agent_identifier(Identifier) + when is_atom(Identifier) -> + encode_agent_identifier(atom_to_list(Identifier)); +%% if the ID is a string, transform it into a #agent-identifier +encode_agent_identifier(Identifier) + when is_list(Identifier) -> + case sl:isString(Identifier) of + true -> + {ID, HAP} = exat:split_agent_identifier(Identifier), + #'agent-identifier'{name = + lists:flatten([ID, "@", HAP]), + addresses = mtp:addresses()}; + false -> [encode_agent_identifier(X) || X <- Identifier] + end; +encode_agent_identifier(Default) -> Default. + +sendacl(Message) -> + Sender = + encode_agent_identifier(Message#aclmessage.sender), + R = + encode_agent_identifier(Message#aclmessage.receiver), + Receivers = if is_list(R) -> R; + true -> [R] + end, + %%io:format ("Sender ~w~n", [Sender]), + %%io:format ("Receivers ~w~n", [Receivers]), + %% encode content + EncodedContent = "\"" ++ + case + ontology_service:get_codec(Message#aclmessage.ontology) + of + {ok, Codec} -> + SL = Codec:encode(Message#aclmessage.content), + sl:encode(SL); + _ -> Message#aclmessage.content + end + ++ "\"", + [_ | Temp] = tuple_to_list(Message#aclmessage{sender = + Sender, + receiver = Receivers, + content = EncodedContent}), + TransformedMessage = list_to_tuple(Temp), + [mtp:http_mtp_encode_and_send(X, Sender, + TransformedMessage) + || X <- Receivers], + ok. + +inform(Message) -> + sendacl(Message#aclmessage{speechact = 'INFORM'}). + +ask_if(Message) -> + sendacl(Message#aclmessage{speechact = 'ASK-IF'}). + +call_for_proposal(Message) -> + sendacl(Message#aclmessage{speechact = 'CFP'}). + +propose(Message) -> + sendacl(Message#aclmessage{speechact = 'PROPOSE'}). + +accept_proposal(Message) -> + sendacl(Message#aclmessage{speechact = + 'ACCEPT-PROPOSAL'}). + +reject_proposal(Message) -> + sendacl(Message#aclmessage{speechact = + 'REJECT-PROPOSAL'}). + +refuse(Message) -> + sendacl(Message#aclmessage{speechact = 'REFUSE'}). + +request(Message) -> + sendacl(Message#aclmessage{speechact = 'REQUEST'}). + +query_if(Message) -> + sendacl(Message#aclmessage{speechact = 'QUERY-IF'}). + +query_ref(Message) -> + sendacl(Message#aclmessage{speechact = 'QUERY-REF'}). + +reply(Request, NewSpeechAct, NewContent) -> + Receiver = if Request#aclmessage.'reply-to' == + (?ACL_ANY) -> + Request#aclmessage.sender; + true -> Request#aclmessage.'reply-to' + end, + sendacl(Request#aclmessage{speechact = NewSpeechAct, + sender = Request#aclmessage.receiver, + receiver = Receiver, + 'in-reply-to' = Request#aclmessage.'reply-with', + content = NewContent}). + +%% +%% pattern library +%% +unify_atoms(?ACL_ANY, ?ACL_ANY) -> ?ACL_ANY; +unify_atoms(A1, ?ACL_ANY) -> A1; +unify_atoms(?ACL_ANY, A2) -> A2; +unify_atoms(A1, A2) -> A2. + +unify_patterns([], [], Acc) -> lists:reverse(Acc); +unify_patterns([H1 | T1], [H2 | T2], Acc) -> + unify_patterns(T1, T2, [unify_atoms(H1, H2) | Acc]). + +refinepattern(BasePattern, RefiningPattern) -> + LBasePattern = tuple_to_list(BasePattern), + LRefiningPattern = tuple_to_list(RefiningPattern), + L1 = length(LBasePattern), + L2 = length(LRefiningPattern), + if L1 =/= L2 -> + exit({badarg, 'pattern lengths differ'}); + true -> + list_to_tuple(unify_patterns(LBasePattern, + LRefiningPattern, [])) + end. + +refinepattern(Object, PatternName, Index, + RefiningPattern) -> + PatternList = object:super(Object, pattern, + [PatternName]), + lists:sublist(PatternList, Index - 1) ++ + [refinepattern(lists:nth(Index, PatternList), + RefiningPattern)] + ++ lists:nthtail(Index, PatternList). + +%% +%% acl utils +%% +hexlify([]) -> ""; +hexlify([H | T]) -> + %%[Z | _] = io_lib:format ("~.16B", [H]), + hexof(H) ++ hexlify(T). + +unhexlify([]) -> ""; +unhexlify([H1, H2 | T]) -> + Int = hexdigit(H1) * 16 + hexdigit(H2), + [Int | unhexlify(T)]. + +hexof(X) -> Z = tohex(X div 16) ++ tohex(X rem 16), Z. + +tohex(0) -> "0"; +tohex(1) -> "1"; +tohex(2) -> "2"; +tohex(3) -> "3"; +tohex(4) -> "4"; +tohex(5) -> "5"; +tohex(6) -> "6"; +tohex(7) -> "7"; +tohex(8) -> "8"; +tohex(9) -> "9"; +tohex(10) -> "A"; +tohex(11) -> "B"; +tohex(12) -> "C"; +tohex(13) -> "D"; +tohex(14) -> "E"; +tohex(15) -> "F". + +hexdigit($0) -> 0; +hexdigit($1) -> 1; +hexdigit($2) -> 2; +hexdigit($3) -> 3; +hexdigit($4) -> 4; +hexdigit($5) -> 5; +hexdigit($6) -> 6; +hexdigit($7) -> 7; +hexdigit($8) -> 8; +hexdigit($9) -> 9; +hexdigit($A) -> 10; +hexdigit($B) -> 11; +hexdigit($C) -> 12; +hexdigit($D) -> 13; +hexdigit($E) -> 14; +hexdigit($F) -> 15. diff --git a/src/aclscan.erl b/src/aclscan.erl index 2aa135f..fa87294 100644 --- a/src/aclscan.erl +++ b/src/aclscan.erl @@ -1,78 +1,62 @@ -% -% aclscan.erl -% - New acl scanner -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (aclscan). --export ([scan/1]). - -scan ([], Acc, Tokens) -> - lists:reverse (Tokens); - - -scan ([$( | L], [], Tokens) -> - scan (L, [], ["(" | Tokens]); - -scan ([$( | L], Acc, Tokens) -> - scan (L, [], ["(" | [lists:reverse (Acc) | Tokens]]); - - -scan ([$) | L], [], Tokens) -> - scan (L, [], [")" | Tokens]); - -scan ([$) | L], Acc, Tokens) -> - scan (L, [], [")" | [lists:reverse (Acc) | Tokens]]); - - -scan ([$: | L], [], Tokens) -> - scan (L, [], [":" | Tokens]); - -scan ([$: | L], Acc, Tokens) -> - scan (L, [], [":" | [lists:reverse (Acc) | Tokens]]); - - -scan ([$" | L], Acc, Tokens) -> - [Data, Tail] = toquote (L), - scan (Tail, [], [Data | [lists:reverse (Acc) | Tokens]]); - - -scan ([$ | L], Acc, Tokens) -> - scan (L, [], [lists:reverse (Acc) | Tokens]); - - -scan ([$\\ , H | L], Acc, Tokens) -> - scan (L, [H | Acc], Tokens); - - -scan ([H|L], Acc, Tokens) -> - scan (L, [H | Acc], Tokens). - -toquote ([]) -> [[], []]; -toquote ([$" | T]) -> [[], T]; -toquote ([$\\ , H | T]) -> [Data, Tail] = toquote (T), [[H | Data], Tail]; -toquote ([H | T]) -> [Data, Tail] = toquote (T), [[H | Data], Tail]. - -remove_empty ([]) -> []; -remove_empty ([ [] | T]) -> remove_empty (T); -remove_empty ([ H | T]) -> [H | remove_empty (T)]. - -scan (Message) -> - remove_empty (scan (Message, [], [])). +%% +%% aclscan.erl +%% - New acl scanner +%% +%% ---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(aclscan). + +-export([scan/1]). + +scan([], Acc, Tokens) -> lists:reverse(Tokens); +scan([$( | L], [], Tokens) -> + scan(L, [], ["(" | Tokens]); +scan([$( | L], Acc, Tokens) -> + scan(L, [], ["(", lists:reverse(Acc) | Tokens]); +scan([$) | L], [], Tokens) -> + scan(L, [], [")" | Tokens]); +scan([$) | L], Acc, Tokens) -> + scan(L, [], [")", lists:reverse(Acc) | Tokens]); +scan([$: | L], [], Tokens) -> + scan(L, [], [":" | Tokens]); +scan([$: | L], Acc, Tokens) -> + scan(L, [], [":", lists:reverse(Acc) | Tokens]); +scan([$" | L], Acc, Tokens) -> + [Data, Tail] = toquote(L), + scan(Tail, [], [Data, lists:reverse(Acc) | Tokens]); +scan([$\s | L], Acc, Tokens) -> + scan(L, [], [lists:reverse(Acc) | Tokens]); +scan([$\\, H | L], Acc, Tokens) -> + scan(L, [H | Acc], Tokens); +scan([H | L], Acc, Tokens) -> + scan(L, [H | Acc], Tokens). + +toquote([]) -> [[], []]; +toquote([$" | T]) -> [[], T]; +toquote([$\\, H | T]) -> + [Data, Tail] = toquote(T), [[H | Data], Tail]; +toquote([H | T]) -> + [Data, Tail] = toquote(T), [[H | Data], Tail]. + +remove_empty([]) -> []; +remove_empty([[] | T]) -> remove_empty(T); +remove_empty([H | T]) -> [H | remove_empty(T)]. + +scan(Message) -> remove_empty(scan(Message, [], [])). diff --git a/src/aclscanner.erl b/src/aclscanner.erl index a2c2fd7..b5064b5 100644 --- a/src/aclscanner.erl +++ b/src/aclscanner.erl @@ -1,112 +1,82 @@ -% -% aclscanner -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (aclscanner). --export ([scan/1,tokenize/1,skiptoquote/2,token/1]). - -accumulate (L) -> - [Tokens, Acc] = L, - if - length (Acc) == 0 -> [Tokens, []]; - true -> [Tokens ++ [Acc], []] - end. - -skiptoquote ([], Acc) -> - [Acc, ""]; - -skiptoquote ([$"], Acc) -> - [Acc, ""]; - -skiptoquote ([$"|T], Acc) -> - [Acc, T]; - -skiptoquote ([H|T], Acc) -> - skiptoquote (T, Acc ++ [H]). - -scan ([], L) -> - accumulate (L); - -scan ([32], L) -> - accumulate (L); - -scan ([$(], L) -> - [Tokens, Acc] = accumulate (L), - [Tokens ++ ["("], []]; - -scan ([$)], L) -> - [Tokens, Acc] = accumulate (L), - [Tokens ++ [")"], []]; - -scan ([L], L2) -> - [Tokens, Acc] = L2, - [Tokens ++ [Acc ++ [L]], []]; - -scan ([$(|T], L) -> - [Tokens, Acc] = accumulate (L), - scan (T, [Tokens ++ ["("], []]); - -scan ([$)|T], L) -> - [Tokens, Acc] = accumulate (L), - scan (T, [Tokens ++ [")"], []]); - -scan ([$ , $:|T], L) -> - [Tokens, Acc] = accumulate (L), - scan (T, [Tokens ++ [":"], []]); - -%scan ([$ |T], L) -> -% [Tokens, Acc] = accumulate (L), -% scan (T, [Tokens ++ [" "], []]); - -scan ([H|T], L) -> - [Tokens, Acc] = L, - case H of - 32 -> - L2 = accumulate (L), - T2 = T; - 34 -> - [Tokens2, Acc2] = accumulate (L), - [H2,T2] = skiptoquote (T,[]), - L2 = [Tokens2 ++ [H2], []]; - Other -> - L2 = [Tokens, Acc ++ [H]], - T2 = T - end, - scan (T2, L2). - -scan (P) -> - [Tokens, Acc] = scan (P, [[],[]]), - Tokens. - -token (X) -> - case X of - [$(] -> {'(',1}; - [$)] -> {')',1}; - [$:] -> {':',1}; - [$ ] -> {' ',1}; - Other -> {atom, list_to_atom (X),1} - end. - -tokenize ([L]) -> - [token (L),{'$end',1}]; - -tokenize ([H|T]) -> - [token (H)] ++ tokenize (T). +%% +%%aclscanner +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(aclscanner). + +-export([scan/1, skiptoquote/2, token/1, tokenize/1]). + +accumulate(L) -> + [Tokens, Acc] = L, + if length(Acc) == 0 -> [Tokens, []]; + true -> [Tokens ++ [Acc], []] + end. + +skiptoquote([], Acc) -> [Acc, ""]; +skiptoquote([$"], Acc) -> [Acc, ""]; +skiptoquote([$" | T], Acc) -> [Acc, T]; +skiptoquote([H | T], Acc) -> skiptoquote(T, Acc ++ [H]). + +scan([], L) -> accumulate(L); +scan([32], L) -> accumulate(L); +scan([$(], L) -> + [Tokens, Acc] = accumulate(L), [Tokens ++ ["("], []]; +scan([$)], L) -> + [Tokens, Acc] = accumulate(L), [Tokens ++ [")"], []]; +scan([L], L2) -> + [Tokens, Acc] = L2, [Tokens ++ [Acc ++ [L]], []]; +scan([$( | T], L) -> + [Tokens, Acc] = accumulate(L), + scan(T, [Tokens ++ ["("], []]); +scan([$) | T], L) -> + [Tokens, Acc] = accumulate(L), + scan(T, [Tokens ++ [")"], []]); +scan([$\s, $: | T], L) -> + [Tokens, Acc] = accumulate(L), + scan(T, [Tokens ++ [":"], []]); +%%scan ([$ |T], L) -> +%% [Tokens, Acc] = accumulate (L), +%% scan (T, [Tokens ++ [" "], []]); +scan([H | T], L) -> + [Tokens, Acc] = L, + case H of + 32 -> L2 = accumulate(L), T2 = T; + 34 -> + [Tokens2, Acc2] = accumulate(L), + [H2, T2] = skiptoquote(T, []), + L2 = [Tokens2 ++ [H2], []]; + Other -> L2 = [Tokens, Acc ++ [H]], T2 = T + end, + scan(T2, L2). + +scan(P) -> [Tokens, Acc] = scan(P, [[], []]), Tokens. + +token(X) -> + case X of + [$(] -> {'(', 1}; + [$)] -> {')', 1}; + [$:] -> {':', 1}; + [$\s] -> {' ', 1}; + Other -> {atom, list_to_atom(X), 1} + end. + +tokenize([L]) -> [token(L), {'$end', 1}]; +tokenize([H | T]) -> [token(H)] ++ tokenize(T). diff --git a/src/agent.erl b/src/agent.erl index c73f74d..94cf7be 100644 --- a/src/agent.erl +++ b/src/agent.erl @@ -19,139 +19,121 @@ %% You should have received a copy of the GNU General Public License %% along with this program. If not, see - -module(agent). + -behaviour(gen_server). + -include("object.hrl"). + -include("acl.hrl"). + -include("fipa_ontology.hrl"). --export([new/2, - behave/2, - get_behaviour/1, - set_behaviour/2, - join/1, - stop/1, - kill/1, - set_rational/3, - get_mind/1, - get_acl_semantics/1, - set_property/3, - get_property/2, - send_message/4, - get_message/1, - match_message/2, - init/1, - handle_call/3, - handle_cast/2, - terminate/2]). + +-export([behave/2, get_acl_semantics/1, get_behaviour/1, + get_message/1, get_mind/1, get_property/2, + handle_call/3, handle_cast/2, init/1, join/1, kill/1, + match_message/2, new/2, send_message/4, set_behaviour/2, + set_property/3, set_rational/3, stop/1, terminate/2]). -define(AGENT_BEHAVIOURS, '__AGENT_BEHAVIOURS'). --define(AGENT_DETACHED_BEHAVIOURS, '__AGENT_DETACHED_BEHAVIOURS'). + +-define(AGENT_DETACHED_BEHAVIOURS, + '__AGENT_DETACHED_BEHAVIOURS'). new(AgentName) -> - gen_server:start({local, AgentName}, - agent, + gen_server:start({local, AgentName}, agent, [AgentName, [], - dict:store(?AGENT_DETACHED_BEHAVIOURS, [], - dict:new()), - []], []), + dict:store(?AGENT_DETACHED_BEHAVIOURS, [], dict:new()), + []], + []), ok. new(AgentName, Parameters) -> new(AgentName), Rationality = prop(Parameters, rationality), Behaviour = prop(Parameters, behaviour), - if - Rationality =/= nil -> + if Rationality =/= nil -> {Mind, Semantics} = Rationality, agent:set_rational(AgentName, Mind, Semantics); - true -> nil + true -> nil end, - if - Behaviour =/= nil -> + if Behaviour =/= nil -> agent:set_behaviour(AgentName, Behaviour); - true -> nil + true -> nil end, ok. - prop([], _) -> nil; -prop([{Key,Value}|T], Key) -> Value; -prop([_|T], Key) -> prop(T, Key). - +prop([{Key, Value} | T], Key) -> Value; +prop([_ | T], Key) -> prop(T, Key). %% %% MAIN CALLS %% behave(AgentOrObject, Behaviour) -> Agent = extract_agent_identifier(AgentOrObject), - CurrentBehaviour = get_behaviour(Agent), - - % BehaviourObject = object:new(Behaviour), - % set_property(Agent, ?AGENT_BEHAVIOUR, BehaviourObject), - % object:bind(BehaviourObject, Agent), - % object:start(BehaviourObject), - % object:join(BehaviourObject), - % object:delete(BehaviourObject), + %% BehaviourObject = object:new(Behaviour), + %% set_property(Agent, ?AGENT_BEHAVIOUR, BehaviourObject), + %% object:bind(BehaviourObject, Agent), + %% object:start(BehaviourObject), + %% object:join(BehaviourObject), + %% object:delete(BehaviourObject), set_behaviour(Agent, Behaviour), join(Agent), - - set_property(Agent, ?AGENT_BEHAVIOURS, CurrentBehaviour), + set_property(Agent, ?AGENT_BEHAVIOURS, + CurrentBehaviour), ok. get_behaviour(Agent) -> get_property(Agent, ?AGENT_BEHAVIOURS). - -set_behaviour(Agent, Behaviours) when is_list(Behaviours) -> - BehaviourObjectList = create_behaviours(Agent, Behaviours, []), - set_property(Agent, ?AGENT_BEHAVIOURS, BehaviourObjectList), +set_behaviour(Agent, Behaviours) + when is_list(Behaviours) -> + BehaviourObjectList = create_behaviours(Agent, + Behaviours, []), + set_property(Agent, ?AGENT_BEHAVIOURS, + BehaviourObjectList), start_behaviours(BehaviourObjectList), ok; - -set_behaviour(Agent, Behaviour) when is_atom(Behaviour) -> +set_behaviour(Agent, Behaviour) + when is_atom(Behaviour) -> set_behaviour(Agent, [Behaviour]). - -start_behaviours([]) -> - ok; - -start_behaviours([{BehaviourObject, detached} | Tail]) -> - object:start(BehaviourObject), - start_behaviours(Tail); - +start_behaviours([]) -> ok; +start_behaviours([{BehaviourObject, detached} + | Tail]) -> + object:start(BehaviourObject), start_behaviours(Tail); start_behaviours([BehaviourObject | Tail]) -> - object:start(BehaviourObject), - start_behaviours(Tail). - -create_behaviours(_, [], Acc) -> - Acc; + object:start(BehaviourObject), start_behaviours(Tail). -create_behaviours(Agent, [{BehaviourName, detached} | Tail], Acc) -> +create_behaviours(_, [], Acc) -> Acc; +create_behaviours(Agent, + [{BehaviourName, detached} | Tail], Acc) -> BehaviourObject = object:new(BehaviourName), object:bind(BehaviourObject, Agent), - DetachedBehaviours = get_property(Agent, ?AGENT_DETACHED_BEHAVIOURS), + DetachedBehaviours = get_property(Agent, + ?AGENT_DETACHED_BEHAVIOURS), set_property(Agent, ?AGENT_DETACHED_BEHAVIOURS, [BehaviourObject | DetachedBehaviours]), - create_behaviours(Agent, Tail, [{BehaviourObject, detached} | Acc]); - + create_behaviours(Agent, Tail, + [{BehaviourObject, detached} | Acc]); create_behaviours(Agent, [BehaviourName | Tail], Acc) -> BehaviourObject = object:new(BehaviourName), object:bind(BehaviourObject, Agent), create_behaviours(Agent, Tail, [BehaviourObject | Acc]). - - join(Agent) -> - BehaviourObject = get_property(Agent, ?AGENT_BEHAVIOURS), + BehaviourObject = get_property(Agent, + ?AGENT_BEHAVIOURS), join_list(BehaviourObject), set_property(Agent, ?AGENT_BEHAVIOURS, nil), ok. join_list(nil) -> ok; join_list([]) -> ok; -join_list([{BehaviourObject, detached} | Tail]) -> join_list(Tail); +join_list([{BehaviourObject, detached} | Tail]) -> + join_list(Tail); join_list([BehaviourObject | Tail]) -> object:join(BehaviourObject), object:delete(BehaviourObject), @@ -165,104 +147,97 @@ get_property(Agent, Property) -> get_message(Agent) -> gen_server:cast(Agent, [getmessage, self()]), - receive - X -> X - end. + receive X -> X end. match_message(Agent, Pattern) -> - gen_server:cast(Agent, [match_message, Pattern, self()]), - receive - X -> X - end. + gen_server:cast(Agent, + [match_message, Pattern, self()]), + receive X -> X end. send_message(nil, ReceiverAgent, Mode, Message) -> gen_server:call(ReceiverAgent, [Mode, Message]), ok; - -send_message(SenderAgent, ReceiverAgent, Mode, Message) -> +send_message(SenderAgent, ReceiverAgent, Mode, + Message) -> SenderAgentName = extract_agent_identifier(SenderAgent), - %io:format("name = ~w\n", [SenderAgentName]), + %%io:format("name = ~w\n", [SenderAgentName]), R = agent:get_property(SenderAgentName, rationality), - CanSend = - if - R == nil -> true; - true -> - [Engine, Semantics] = R, - %%io:format("Semantics = ~w,~w,~w\n", - %% [Engine, Semantics, SenderAgentName]), - object:call(Semantics, is_feasible, - [SenderAgentName, Engine, Message]) - end, - %io:format("Cansend = ~w\n", [CanSend]), - if - CanSend -> perform_message_sending(ReceiverAgent, [Mode, Message]), ok; + CanSend = if R == nil -> true; + true -> + [Engine, Semantics] = R, + %%io:format("Semantics = ~w,~w,~w\n", + %% [Engine, Semantics, SenderAgentName]), + object:call(Semantics, is_feasible, + [SenderAgentName, Engine, Message]) + end, + %%io:format("Cansend = ~w\n", [CanSend]), + if CanSend -> + perform_message_sending(ReceiverAgent, [Mode, Message]), + ok; %%% FIXME!!!! This is not for a distributed environment????? - true -> error + true -> error end. - extract_agent_identifier(AgentOrObject) - when record(AgentOrObject, 'agent-identifier') -> + when is_record(AgentOrObject, 'agent-identifier') -> AgentOrObject#'agent-identifier'.name; extract_agent_identifier(AgentOrObject) - when record(AgentOrObject, object) -> + when is_record(AgentOrObject, object) -> extract_agent_identifier(object:agentof(AgentOrObject)); extract_agent_identifier(AgentOrObject) -> AgentOrObject. - - perform_message_sending(ReceiverAgent, [Mode, Message]) - when record(ReceiverAgent, 'agent-identifier') -> + when is_record(ReceiverAgent, 'agent-identifier') -> mtp:http_mtp_encode_and_send(Message); -perform_message_sending(ReceiverAgent, [Mode, Message]) -> +perform_message_sending(ReceiverAgent, + [Mode, Message]) -> gen_server:call(ReceiverAgent, [Mode, Message]). - - -set_rational(AgentOrObject, EngineName, SemanticsClass) -> +set_rational(AgentOrObject, EngineName, + SemanticsClass) -> SemanticsObject = object:new(SemanticsClass), %% io:format("Semantic Object = ~w\n", [SemanticsObject]), Agent = extract_agent_identifier(AgentOrObject), - set_property(Agent, rationality, [EngineName, SemanticsObject]). + set_property(Agent, rationality, + [EngineName, SemanticsObject]). get_mind(AgentOrObject) -> Agent = extract_agent_identifier(AgentOrObject), %%io:format("Agent = ~w\n", [Agent]), - [EngineName, SemanticsObject] = get_property(Agent, rationality), + [EngineName, SemanticsObject] = get_property(Agent, + rationality), EngineName. get_acl_semantics(AgentOrObject) -> Agent = extract_agent_identifier(AgentOrObject), Semantics = get_property(Agent, rationality), - if - Semantics == nil -> nil; - true -> - [EngineName, SemanticsObject] = get_property(Agent, rationality), + if Semantics == nil -> nil; + true -> + [EngineName, SemanticsObject] = get_property(Agent, + rationality), SemanticsObject end. - stop(Agent) -> agent:join(Agent), Semantics = get_acl_semantics(Agent), - if - Semantics =/= nil -> object:delete(Semantics); - true -> nil + if Semantics =/= nil -> object:delete(Semantics); + true -> nil end, gen_server:cast(Agent, stop), ok. kill(Agent) -> - BehaviourObject = get_property(Agent, ?AGENT_BEHAVIOURS), + BehaviourObject = get_property(Agent, + ?AGENT_BEHAVIOURS), kill_list(BehaviourObject), - DetachedBehaviourObject = get_property(Agent, ?AGENT_DETACHED_BEHAVIOURS), + DetachedBehaviourObject = get_property(Agent, + ?AGENT_DETACHED_BEHAVIOURS), kill_list(DetachedBehaviourObject), set_property(Agent, ?AGENT_BEHAVIOURS, nil), Semantics = get_acl_semantics(Agent), - if - Semantics =/= nil -> - object:delete(Semantics); - true -> nil + if Semantics =/= nil -> object:delete(Semantics); + true -> nil end, gen_server:cast(Agent, stop), ok. @@ -270,11 +245,9 @@ kill(Agent) -> kill_list(nil) -> ok; kill_list([]) -> ok; kill_list([{BehaviourObject, detached} | Tail]) -> - object:delete(BehaviourObject), - kill_list(Tail); + object:delete(BehaviourObject), kill_list(Tail); kill_list([BehaviourObject | Tail]) -> - object:delete(BehaviourObject), - kill_list(Tail). + object:delete(BehaviourObject), kill_list(Tail). %% %% CALLBACKS @@ -284,7 +257,7 @@ kill_list([BehaviourObject | Tail]) -> %% Initialize %% init(State) -> - [ AgentName | _ ] = State, + [AgentName | _] = State, ams:register_agent(AgentName), {ok, State}. @@ -292,7 +265,7 @@ init(State) -> %% Terminate %% terminate(normal, State) -> - [ AgentName | _ ] = State, + [AgentName | _] = State, ams:de_register_agent(AgentName), ok. @@ -302,99 +275,90 @@ terminate(normal, State) -> handle_call([get_property, PropertyName], From, [AgentName, AclQueue, AgentDict, ProcessQueue]) -> Value = a__get_prop(AgentDict, PropertyName), - {reply, Value, [AgentName, AclQueue, AgentDict, ProcessQueue]}; - - + {reply, Value, + [AgentName, AclQueue, AgentDict, ProcessQueue]}; %% %% Sets a property %% -handle_call([set_property, PropertyName, PropertyValue], From, - [AgentName, AclQueue, AgentDict, ProcessQueue]) -> - A1 = a__set_prop(AgentDict, PropertyName, PropertyValue), +handle_call([set_property, PropertyName, PropertyValue], + From, [AgentName, AclQueue, AgentDict, ProcessQueue]) -> + A1 = a__set_prop(AgentDict, PropertyName, + PropertyValue), {reply, ok, [AgentName, AclQueue, A1, ProcessQueue]}; - - - %% %% Receives an ACL message in String format %% handle_call([acl, Acl], From, [AgentName, AclQueue, AgentDict, ProcessQueue]) -> - %io:format("[Agent] Received ACL=~s\n", [Acl]), - case catch(acl:parse_message(Acl)) of + %%io:format("[Agent] Received ACL=~s\n", [Acl]), + case catch acl:parse_message(Acl) of {'EXIT', Reason} -> - %io:format("[Agent] Error in ACL parsing\n"), + %%io:format("[Agent] Error in ACL parsing\n"), R = [AgentName, AclQueue, AgentDict, ProcessQueue]; ParsedMessage -> - %io:format("[Agent] ACL parsed OK\n"), - {AclQueue1, ProcessQueue1} = - perform_re(AgentName, AgentDict, - ParsedMessage, AclQueue, ProcessQueue), + %%io:format("[Agent] ACL parsed OK\n"), + {AclQueue1, ProcessQueue1} = perform_re(AgentName, + AgentDict, ParsedMessage, + AclQueue, ProcessQueue), R = [AgentName, AclQueue1, AgentDict, ProcessQueue1] end, {reply, ok, R}; - %% %% Receives an ACL message in Erlang format %% handle_call([acl_erl_native, Acl], From, [AgentName, AclQueue, AgentDict, ProcessQueue]) -> %%io:format("[Agent] Received ACL=~w\n", [Acl]), - {AclQueue1, ProcessQueue1} = - perform_re(AgentName, AgentDict, - Acl, AclQueue, ProcessQueue), - {reply, ok, [AgentName, AclQueue1, AgentDict, ProcessQueue1]}. - + {AclQueue1, ProcessQueue1} = perform_re(AgentName, + AgentDict, Acl, AclQueue, + ProcessQueue), + {reply, ok, + [AgentName, AclQueue1, AgentDict, ProcessQueue1]}. %% %% Retrieves a message from the queue(or waits for the message) %% handle_cast([getmessage, From], [AgentName, AclQueue, AgentDict, ProcessQueue]) -> - if - length(AclQueue) > 0 -> - ProcessQueue1 = ProcessQueue, + if length(AclQueue) > 0 -> + ProcessQueue1 = ProcessQueue, [Message | AclQueue1] = AclQueue, - catch(From ! Message); - true -> + catch From ! Message; + true -> ProcessQueue1 = ProcessQueue ++ [{nil, From}], AclQueue1 = AclQueue end, - {noreply, [AgentName, AclQueue1, AgentDict, ProcessQueue1]}; - + {noreply, + [AgentName, AclQueue1, AgentDict, ProcessQueue1]}; %% %% Retrieves a matching message from the queue %% (or waits for a matching message) %% handle_cast([match_message, Pattern, From], [AgentName, AclQueue, AgentDict, ProcessQueue]) -> - {Sent, NewAclQueue} = find_matching_message(AclQueue, Pattern, From, []), - if - Sent -> - AclQueue1 = NewAclQueue, - ProcessQueue1 = ProcessQueue; - true -> + {Sent, NewAclQueue} = find_matching_message(AclQueue, + Pattern, From, []), + if Sent -> + AclQueue1 = NewAclQueue, ProcessQueue1 = ProcessQueue; + true -> ProcessQueue1 = ProcessQueue ++ [{Pattern, From}], AclQueue1 = AclQueue end, - % if - % length(AclQueue) > 0 -> - % ProcessQueue1 = ProcessQueue, - % [Message | AclQueue1] = AclQueue, - % catch(From ! Message); - % true -> - % ProcessQueue1 = ProcessQueue ++ [{Pattern, From}], - % AclQueue1 = AclQueue - % end, - {noreply, [AgentName, AclQueue1, AgentDict, ProcessQueue1]}; - - + %% if + %% length(AclQueue) > 0 -> + %% ProcessQueue1 = ProcessQueue, + %% [Message | AclQueue1] = AclQueue, + %% catch(From ! Message); + %% true -> + %% ProcessQueue1 = ProcessQueue ++ [{Pattern, From}], + %% AclQueue1 = AclQueue + %% end, + {noreply, + [AgentName, AclQueue1, AgentDict, ProcessQueue1]}; %% %% Stops the agent process %% -handle_cast(stop, State) -> - {stop, normal, State}. - +handle_cast(stop, State) -> {stop, normal, State}. %% %% OTHER FUNCTIONS @@ -408,90 +372,71 @@ a__get_prop(AgentDict, Property) -> Other -> nil end. - %% %% finds a matching message and sends it %% find_matching_message([], Pattern, Process, NewQueue) -> {false, lists:reverse(NewQueue)}; - -find_matching_message([Message | MessageTail], Pattern, Process, NewQueue) -> +find_matching_message([Message | MessageTail], Pattern, + Process, NewQueue) -> Match = match_lib:match_acl(Pattern, Message), - if - Match -> catch(Process ! Message), - {true, lists:reverse(NewQueue) ++ MessageTail}; - true -> - find_matching_message(MessageTail, - Pattern, Process, - [ Message | NewQueue ]) - end. - - -%% -%% forwards a message checking if the receiving process is still alive -%% -do_forward(Message, Process) -> - case is_process_alive(Process) of - true -> catch(Process ! Message), - true; - _ -> false + if Match -> + catch Process ! Message, + {true, lists:reverse(NewQueue) ++ MessageTail}; + true -> + find_matching_message(MessageTail, Pattern, Process, + [Message | NewQueue]) end. %% %% forwards a message to the process requesting a match %% -forward_to_maching_process(Message, [], NewProcessQueue) -> +forward_to_maching_process(Message, [], + NewProcessQueue) -> {false, lists:reverse(NewProcessQueue)}; - forward_to_maching_process(Message, [{nil, Process} | ProcessQueueTail], NewProcessQueue) -> - catch(Process ! Message), - {true, lists:reverse(NewProcessQueue) ++ ProcessQueueTail}; - + catch Process ! Message, + {true, + lists:reverse(NewProcessQueue) ++ ProcessQueueTail}; forward_to_maching_process(Message, [{Pattern, Process} | ProcessQueueTail], NewProcessQueue) -> Match = match_lib:match_acl(Pattern, Message), - if - Match -> catch(Process ! Message), - {true, lists:reverse(NewProcessQueue) ++ ProcessQueueTail}; - true -> - forward_to_maching_process(Message, - ProcessQueueTail, + if Match -> + catch Process ! Message, + {true, + lists:reverse(NewProcessQueue) ++ ProcessQueueTail}; + true -> + forward_to_maching_process(Message, ProcessQueueTail, [{Pattern, Process} | NewProcessQueue]) end. - - forward_or_enqueue(AclQueue, ProcessQueue, Message) -> {Forwarded, NewProcessQueue} = forward_to_maching_process(Message, ProcessQueue, []), - if - Forwarded -> - {AclQueue1, ProcessQueue1} = {AclQueue, NewProcessQueue}; - true -> + if Forwarded -> + {AclQueue1, ProcessQueue1} = {AclQueue, + NewProcessQueue}; + true -> ProcessQueue1 = ProcessQueue, AclQueue1 = AclQueue ++ [Message] end, {AclQueue1, ProcessQueue1}. - -perform_re(Agent, AgentDict, Message, AclQueue, ProcessQueue) -> +perform_re(Agent, AgentDict, Message, AclQueue, + ProcessQueue) -> R = a__get_prop(AgentDict, rationality), - CanEnqueue = - if - R == nil -> true; - true -> - [Engine, Semantics] = R, - %% io:format("Semantics = ~w\n", [Semantics]), - object:call(Semantics, rational_effect, [Agent, Engine, Message]), - true - end, - if - CanEnqueue -> + CanEnqueue = if R == nil -> true; + true -> + [Engine, Semantics] = R, + %% io:format("Semantics = ~w\n", [Semantics]), + object:call(Semantics, rational_effect, + [Agent, Engine, Message]), + true + end, + if CanEnqueue -> forward_or_enqueue(AclQueue, ProcessQueue, Message); - true -> - {AclQueue, ProcessQueue} + true -> {AclQueue, ProcessQueue} end. - diff --git a/src/ams.erl b/src/ams.erl index 9625fff..de8d252 100644 --- a/src/ams.erl +++ b/src/ams.erl @@ -34,32 +34,28 @@ %% -module(ams). --export([extends/0, - pattern/2, - event/2, - action/2, - request_proc/4]). --export([start_link/0, - register_agent/1, - de_register_agent/1, - get_registered_agents/0]). +-export([action/2, event/2, extends/0, pattern/2, + request_proc/4]). + +-export([de_register_agent/1, get_registered_agents/0, + register_agent/1, start_link/0]). -include("acl.hrl"). + -include("fipa_ontology.hrl"). extends() -> nil. -pattern(Self, request) -> [#aclmessage {speechact = 'REQUEST', - ontology = "FIPA-Agent-Management", - protocol = "fipa-request"}]. +pattern(Self, request) -> + [#aclmessage{speechact = 'REQUEST', + ontology = "FIPA-Agent-Management", + protocol = "fipa-request"}]. event(Self, request_event) -> {acl, request}. action(Self, start) -> [{request_event, request_proc}]. - - request_proc(Self, EventName, Message, ActionName) -> %%io:format("Received msg ~w\n", [Message]), Content = Message#aclmessage.content, @@ -69,60 +65,47 @@ request_proc(Self, EventName, Message, ActionName) -> %%io:format("Reply ~w~n", [ContentReply]), acl:reply(Message, 'INFORM', ContentReply). - - -prepare_reply([Content = #action { '1' = #'get-description'{} }]) -> - logger:log('AMS',"get-description"), - APService = #'ap-service' { name = "fipa.mts.mtp.http.std", - type = "fipa.mts.mtp.http.std", - addresses = mtp:addresses()}, - APDescription = #'ap-description' { name = exat:current_platform(), - 'ap-services' = [APService]}, - Result = #result { - '0' = Content, - '1' = [APDescription]}, +prepare_reply([Content = #action{'1' = + #'get-description'{}}]) -> + logger:log('AMS', "get-description"), + APService = #'ap-service'{name = + "fipa.mts.mtp.http.std", + type = "fipa.mts.mtp.http.std", + addresses = mtp:addresses()}, + APDescription = #'ap-description'{name = + exat:current_platform(), + 'ap-services' = [APService]}, + Result = #result{'0' = Content, '1' = [APDescription]}, [Result]; - - - -prepare_reply([Content = #action {'1' = #'search'{ - '0' = #'ams-agent-description' { } - } }]) -> - logger:log('AMS',"search ams-agent-description"), - Agents = [#'agent-identifier' - { name = X, - addresses = mtp:addresses() } +prepare_reply([Content = #action{'1' = + #search{'0' = + #'ams-agent-description'{}}}]) -> + logger:log('AMS', "search ams-agent-description"), + Agents = [#'agent-identifier'{name = X, + addresses = mtp:addresses()} || X <- ams:get_registered_agents()], - Descriptions = - [#'ams-agent-description' { name = X, - ownership = "NONE", - state = "active" } - || X <- Agents], + Descriptions = [#'ams-agent-description'{name = X, + ownership = "NONE", + state = "active"} + || X <- Agents], %%io:format("DS ~w~n", [Descriptions]), - Result = #result { - '0' = Content, - '1' = Descriptions}, + Result = #result{'0' = Content, '1' = Descriptions}, [Result]. - - - %%==================================================================== %% Func: start_link/0 %% Returns: {ok, Pid}. %%==================================================================== start_link() -> logger:start('AMS'), - logger:log('AMS',"Staring AMS."), + logger:log('AMS', "Staring AMS."), ontology_service:register_codec("FIPA-Agent-Management", - fipa_ontology_sl_codec), + fipa_ontology_sl_codec), agent:new(ams, [{behaviour, ams}]), [BehaviourObject] = agent:get_behaviour(ams), Pid = object:executorof(BehaviourObject), {ok, Pid}. - - %%==================================================================== %% Func: register_agent/1 %% Returns: ok. @@ -130,8 +113,6 @@ start_link() -> register_agent(AgentName) -> eresye:assert(agent_registry, {agent, AgentName}). - - %%==================================================================== %% Func: de_register_agent/1 %% Returns: ok. @@ -139,15 +120,14 @@ register_agent(AgentName) -> de_register_agent(AgentName) -> eresye:retract(agent_registry, {agent, AgentName}). - - %%==================================================================== %% Func: get_registered_agents/0 %% Returns: [string()]. %%==================================================================== get_registered_agents() -> - AgentList = eresye:query_kb(agent_registry, {agent, '_'}), - AgentLocalNames = [ X || {_, X} <- AgentList ], + AgentList = eresye:query_kb(agent_registry, + {agent, '_'}), + AgentLocalNames = [X || {_, X} <- AgentList], PlatformName = exat:current_platform(), - [ lists:flatten([atom_to_list(X), "@", PlatformName]) - || X <- AgentLocalNames ]. + [lists:flatten([atom_to_list(X), "@", PlatformName]) + || X <- AgentLocalNames]. diff --git a/src/envelope.erl b/src/envelope.erl index 17ff23e..dc44b6b 100644 --- a/src/envelope.erl +++ b/src/envelope.erl @@ -1,118 +1,118 @@ -%% +%% %% envelope.erl -%% +%% %% ---------------------------------------------------------------------- -%% +%% %% eXAT, an erlang eXperimental Agent Tool %% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -%% +%% %% This program is free software: you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation, either version 3 of the License, or %% (at your option) any later version. -%% +%% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. -%% +%% %% You should have received a copy of the GNU General Public License %% along with this program. If not, see -%% -%% --module (envelope). --include_lib ("xmerl/include/xmerl.hrl"). --include ("acl.hrl"). --include ("fipa_ontology.hrl"). --export ([make_xml_envelope/4, - make_xml_envelope/3, - parse_xml_envelope/1, - test/0]). +%% +%% +-module(envelope). -make_xml_envelope (To, From, Length, AclRepr) -> - XmlTo = {'agent-identifier', [], - [ {name, [], [binary_to_list(iolist_to_binary(To#'agent-identifier'.name))]}, - {addresses, [], [ {url, [], [X]} || - X <- To#'agent-identifier'.addresses] } - ]}, - XmlFrom = {'agent-identifier', [], - [ {name, [], [binary_to_list(iolist_to_binary(From#'agent-identifier'.name))]}, - {addresses, [], [ {url, [], [X]} || - X <- From#'agent-identifier'.addresses] }] - }, - Envelope = {envelope, [], - [ {params, [{index, 1}], - [{to, [], [XmlTo]}, - {from, [], [XmlFrom]}, - {'acl-representation', [], [AclRepr]}, - {'payload-length', [], [integer_to_list (Length)]}, - {'payload-encoding', [], ["US-ASCII"]}, - {'intended-receiver', [], [XmlTo]} - ]}]}, - - lists:flatten (xmerl:export_simple ([Envelope], xmerl_xml)). +-include_lib("xmerl/include/xmerl.hrl"). +-include("acl.hrl"). +-include("fipa_ontology.hrl"). -make_xml_envelope (To, From, Length) -> - make_xml_envelope (To, From, Length, "fipa.acl.rep.string.std"). +-export([make_xml_envelope/3, make_xml_envelope/4, + parse_xml_envelope/1, test/0]). - -get_xml_element (XML = #xmlElement {name = Key}, Key) -> +make_xml_envelope(To, From, Length, AclRepr) -> + XmlTo = {'agent-identifier', [], + [{name, [], + [binary_to_list(iolist_to_binary(To#'agent-identifier'.name))]}, + {addresses, [], + [{url, [], [X]} + || X <- To#'agent-identifier'.addresses]}]}, + XmlFrom = {'agent-identifier', [], + [{name, [], + [binary_to_list(iolist_to_binary(From#'agent-identifier'.name))]}, + {addresses, [], + [{url, [], [X]} + || X <- From#'agent-identifier'.addresses]}]}, + Envelope = {envelope, [], + [{params, [{index, 1}], + [{to, [], [XmlTo]}, {from, [], [XmlFrom]}, + {'acl-representation', [], [AclRepr]}, + {'payload-length', [], [integer_to_list(Length)]}, + {'payload-encoding', [], ["US-ASCII"]}, + {'intended-receiver', [], [XmlTo]}]}]}, + lists:flatten(xmerl:export_simple([Envelope], + xmerl_xml)). + +make_xml_envelope(To, From, Length) -> + make_xml_envelope(To, From, Length, + "fipa.acl.rep.string.std"). + +get_xml_element(XML = #xmlElement{name = Key}, Key) -> {ok, XML}; -get_xml_element (XML, Key) when record (XML, xmlElement) -> - get_xml_element (XML#xmlElement.content, Key); -get_xml_element ([], _) -> - {error, nil}; -get_xml_element ([XMLH | XMLT], Key) -> - case get_xml_element (XMLH, Key) of +get_xml_element(XML, Key) + when is_record(XML, xmlElement) -> + get_xml_element(XML#xmlElement.content, Key); +get_xml_element([], _) -> {error, nil}; +get_xml_element([XMLH | XMLT], Key) -> + case get_xml_element(XMLH, Key) of {ok, Data} -> {ok, Data}; - _ -> get_xml_element (XMLT, Key) + _ -> get_xml_element(XMLT, Key) end; -get_xml_element (_,_) -> {error, nil}. +get_xml_element(_, _) -> {error, nil}. - -get_xml_text (XML) -> +get_xml_text(XML) -> [Content | _] = XML#xmlElement.content, Text = Content#xmlText.value, Text. -parse_xml_envelope (XmlEnvelope) -> - {Envelope, _} = xmerl_scan:string (XmlEnvelope), - - {ok, XTo} = get_xml_element (Envelope, 'to'), - {ok, XToAgentID} = get_xml_element (XTo, 'agent-identifier'), - {ok, XToAgentName} = get_xml_element (XToAgentID, 'name'), - {ok, XToAgentAddress} = get_xml_element (XToAgentID, 'addresses'), - {ok, XToURL} = get_xml_element (XToAgentAddress, 'url'), - ToAgentName = get_xml_text (XToAgentName), - ToURL = get_xml_text (XToURL), - - {ok, XFrom} = get_xml_element (Envelope, 'from'), - {ok, XFromAgentID} = get_xml_element (XFrom, 'agent-identifier'), - {ok, XFromAgentName} = get_xml_element (XFromAgentID, 'name'), - {ok, XFromAgentAddress} = get_xml_element (XFromAgentID, 'addresses'), - {ok, XFromURL} = get_xml_element (XFromAgentAddress, 'url'), - FromAgentName = get_xml_text (XFromAgentName), - FromURL = get_xml_text (XFromURL), - - {ok, XACLRepresentation} = get_xml_element (Envelope, 'acl-representation'), - ACLRepresentation = get_xml_text (XACLRepresentation), - +parse_xml_envelope(XmlEnvelope) -> + {Envelope, _} = xmerl_scan:string(XmlEnvelope), + {ok, XTo} = get_xml_element(Envelope, to), + {ok, XToAgentID} = get_xml_element(XTo, + 'agent-identifier'), + {ok, XToAgentName} = get_xml_element(XToAgentID, name), + {ok, XToAgentAddress} = get_xml_element(XToAgentID, + addresses), + {ok, XToURL} = get_xml_element(XToAgentAddress, url), + ToAgentName = get_xml_text(XToAgentName), + ToURL = get_xml_text(XToURL), + {ok, XFrom} = get_xml_element(Envelope, from), + {ok, XFromAgentID} = get_xml_element(XFrom, + 'agent-identifier'), + {ok, XFromAgentName} = get_xml_element(XFromAgentID, + name), + {ok, XFromAgentAddress} = get_xml_element(XFromAgentID, + addresses), + {ok, XFromURL} = get_xml_element(XFromAgentAddress, + url), + FromAgentName = get_xml_text(XFromAgentName), + FromURL = get_xml_text(XFromURL), + {ok, XACLRepresentation} = get_xml_element(Envelope, + 'acl-representation'), + ACLRepresentation = get_xml_text(XACLRepresentation), %io:format ("From ~s[~s]~n", [FromAgentName, FromURL]), %io:format ("To ~s[~s]~n", [ToAgentName, ToURL]), %io:format ("Repr ~s~n", [ACLRepresentation]), - - {#'agent-identifier' {name = list_to_atom (ToAgentName), - addresses = ToURL}, - #'agent-identifier' {name = list_to_atom (FromAgentName), - addresses = FromURL}, + {#'agent-identifier'{name = list_to_atom(ToAgentName), + addresses = ToURL}, + #'agent-identifier'{name = list_to_atom(FromAgentName), + addresses = FromURL}, ACLRepresentation}. -test () -> - make_xml_envelope (#'agent-identifier' {name = pippo, - addresses = "http://a:80/acc"}, - #'agent-identifier' {name = pluto, - addresses = "http://b:80/acc"}, - 100). - +test() -> + make_xml_envelope(#'agent-identifier'{name = pippo, + addresses = "http://a:80/acc"}, + #'agent-identifier'{name = pluto, + addresses = "http://b:80/acc"}, + 100). diff --git a/src/eresye.erl b/src/eresye.erl index 9eec7e5..db9bb2b 100644 --- a/src/eresye.erl +++ b/src/eresye.erl @@ -21,9 +21,9 @@ %% along with this program. If not, see %% %% --module (eresye). +-module(eresye). --behaviour (gen_server). +-behaviour(gen_server). %%==================================================================== %% Include files @@ -33,33 +33,18 @@ %% External exports %%==================================================================== --export ([start/1, - start/2, - start_link/1, - stop/1, - assert/2, - retract/2, - retract_match/2, - retract_select/2, - add_rule/2, - add_rule/3, - remove_rule/2, - wait/2, - wait_and_retract/2, - get_rete/1, - get_ontology/1, - get_kb/1, - get_rules_fired/1, - query_kb/2]). +-export([add_rule/2, add_rule/3, assert/2, get_kb/1, + get_ontology/1, get_rete/1, get_rules_fired/1, + query_kb/2, remove_rule/2, retract/2, retract_match/2, + retract_select/2, start/1, start/2, start_link/1, + stop/1, wait/2, wait_and_retract/2]). %%==================================================================== %% Internal exports %%==================================================================== --export ([init/1, - handle_call/3, - terminate/2, - code_change/3]). +-export([code_change/3, handle_call/3, init/1, + terminate/2]). %%==================================================================== %% External functions @@ -68,243 +53,223 @@ %% Func: start/1 %% Arguments: Engine Name %%==================================================================== -start (EngineName) -> - gen_server:start ({local, EngineName}, ?MODULE, [EngineName, nil], []). +start(EngineName) -> + gen_server:start({local, EngineName}, ?MODULE, + [EngineName, nil], []). %%==================================================================== %% Func: start/2 %% Arguments: Engine Name, Ontology %%==================================================================== -start (EngineName, Ontology) -> - gen_server:start ({local, EngineName}, ?MODULE, [EngineName, Ontology], []). +start(EngineName, Ontology) -> + gen_server:start({local, EngineName}, ?MODULE, + [EngineName, Ontology], []). %%==================================================================== %% Func: start_link/1 %% Arguments: Engine Name %%==================================================================== -start_link (EngineName) -> - gen_server:start_link ({local, EngineName}, ?MODULE, - [EngineName, nil], []). - +start_link(EngineName) -> + gen_server:start_link({local, EngineName}, ?MODULE, + [EngineName, nil], []). %%==================================================================== %% Func: stop/1 %% Arguments: Engine Name %%==================================================================== -stop (EngineName) -> - gen_server:call (EngineName, {stop}). - +stop(EngineName) -> gen_server:call(EngineName, {stop}). %%==================================================================== %% Func: assert/2 %% Arguments: EngineName, FactToAssert or FactList %%==================================================================== -assert (EngineName, Fact) when is_list (Fact) -> - [assert (EngineName, F) || F <- Fact], - ok; -assert (EngineName, Fact) when is_tuple (Fact) -> - gen_server:call (EngineName, {assert, Fact}). - - +assert(EngineName, Fact) when is_list(Fact) -> + [assert(EngineName, F) || F <- Fact], ok; +assert(EngineName, Fact) when is_tuple(Fact) -> + gen_server:call(EngineName, {assert, Fact}). %%==================================================================== %% Func: retract/2 %% Arguments: EngineName, FactToRetract or FactList %%==================================================================== -retract (EngineName, Fact) when is_list (Fact) -> - [retract (EngineName, F) || F <- Fact]; -retract (EngineName, Fact) when is_tuple (Fact) -> - gen_server:call (EngineName, {retract, Fact}). - +retract(EngineName, Fact) when is_list(Fact) -> + [retract(EngineName, F) || F <- Fact]; +retract(EngineName, Fact) when is_tuple(Fact) -> + gen_server:call(EngineName, {retract, Fact}). retract_match(EngineName, MS) -> - gen_server:call (EngineName, {retract_match, MS}). + gen_server:call(EngineName, {retract_match, MS}). retract_select(EngineName, MS) -> - gen_server:call (EngineName, {retract_select, MS}). - + gen_server:call(EngineName, {retract_select, MS}). %%==================================================================== %% Func: add_rule/2 %% Arguments: EngineName, Rule %%==================================================================== -add_rule (Name, Fun) -> - add_rule (Name, Fun, 0). - +add_rule(Name, Fun) -> add_rule(Name, Fun, 0). %%==================================================================== %% Func: add_rule/3 %% Arguments: EngineName, Rule, Salience %%==================================================================== -add_rule (Name, {Module, Fun, ClauseID}, Salience) -> - add_rule (Name, {Module, Fun}, ClauseID, Salience); -add_rule (Name, {Module, Fun}, Salience) -> - add_rule (Name, {Module, Fun}, 0, Salience). - -add_rule (Name, Fun, ClauseID, Salience) -> - Ontology = get_ontology (Name), - case get_conds (Fun, Ontology, ClauseID) of +add_rule(Name, {Module, Fun, ClauseID}, Salience) -> + add_rule(Name, {Module, Fun}, ClauseID, Salience); +add_rule(Name, {Module, Fun}, Salience) -> + add_rule(Name, {Module, Fun}, 0, Salience). + +add_rule(Name, Fun, ClauseID, Salience) -> + Ontology = get_ontology(Name), + case get_conds(Fun, Ontology, ClauseID) of error -> error; CondsList -> - lists:foreach ( - fun (X)-> - case X of - {error, Msg} -> - io:format(">> add_rule->get_conds error!!!~n~w:~s~n",[Fun, Msg]); - {PConds, NConds} -> + lists:foreach(fun (X) -> + case X of + {error, Msg} -> + io:format(">> add_rule->get_conds error!!!~n~w:~s~n", + [Fun, Msg]); + {PConds, NConds} -> % io:format(">> PConds=~p~n",[PConds]), % io:format(">> NConds=~p~n",[NConds]), - gen_server:call (Name, {add_rule, - {Fun, Salience}, - {PConds, NConds}}) - end - end, CondsList), + gen_server:call(Name, + {add_rule, + {Fun, Salience}, + {PConds, NConds}}) + end + end, + CondsList), ok end. - %%==================================================================== %% Func: remove_rule/2 %% Arguments: EngineName, Rule %%==================================================================== -remove_rule (Name, Rule) -> - gen_server:call (Name, {remove_rule, Rule}). - +remove_rule(Name, Rule) -> + gen_server:call(Name, {remove_rule, Rule}). %%==================================================================== %% Func: wait/2 %% Arguments: EngineName, PatternToMatch %%==================================================================== -wait (Name, Pattern) -> - wait_retract (Name, Pattern, false). +wait(Name, Pattern) -> + wait_retract(Name, Pattern, false). %%==================================================================== %% Func: wait_and_retract/2 %% Arguments: EngineName, PatternToMatch %%==================================================================== -wait_and_retract (Name, Pattern) -> - wait_retract (Name, Pattern, true). - - -wait_retract (Name, Pattern, NeedRetract) when is_tuple (Pattern) -> - PList = tuple_to_list (Pattern), - SList = [term_to_list (X) || X <- PList], - FunList = [if - is_function (X) -> X; - true -> fun (_) -> true end - end || X <- PList], +wait_and_retract(Name, Pattern) -> + wait_retract(Name, Pattern, true). + +wait_retract(Name, Pattern, NeedRetract) + when is_tuple(Pattern) -> + PList = tuple_to_list(Pattern), + SList = [term_to_list(X) || X <- PList], + FunList = [if is_function(X) -> X; + true -> fun (_) -> true end + end + || X <- PList], %%io:format ("SList = ~p~n", [SList]), - [_ | DList] = lists:foldl (fun (X, Sum) -> - lists:concat ([Sum, ",", X]) - end, - [], SList), - PidHash = erlang:phash2 (self ()), - ClientCondition = lists:flatten ( - io_lib:format ("{client, ~p, Pid, FunList}", [PidHash]) - ), + [_ | DList] = lists:foldl(fun (X, Sum) -> + lists:concat([Sum, ",", X]) + end, + [], SList), + PidHash = erlang:phash2(self()), + ClientCondition = + lists:flatten(io_lib:format("{client, ~p, Pid, FunList}", + [PidHash])), FinalPattern = [ClientCondition, - lists:concat (["{", DList, "}"])], - RetractString = if - NeedRetract -> "eresye:retract (Engine, Pattern__),"; - true -> "" + lists:concat(["{", DList, "}"])], + RetractString = if NeedRetract -> + "eresye:retract (Engine, Pattern__),"; + true -> "" end, - SFun = lists:flatten ( - io_lib:format ( - "fun (Engine, {client, ~p, Pid, FunList} = X, Pattern__) -> " - "FunPatPairs = lists:zip (FunList, tuple_to_list (Pattern__)), " - "FunEval = [F(X) || {F, X} <- FunPatPairs], " - "A = lists:foldr (fun (X,Y) -> X and Y end, true, FunEval), " - "if A -> eresye:retract (Engine, X), ~s Pid ! Pattern__; " - " true -> nil end " - "end.", [PidHash, RetractString])), + SFun = + lists:flatten(io_lib:format("fun (Engine, {client, ~p, Pid, FunList} " + "= X, Pattern__) -> FunPatPairs = lists:zip " + "(FunList, tuple_to_list (Pattern__)), " + "FunEval = [F(X) || {F, X} <- FunPatPairs], " + "A = lists:foldr (fun (X,Y) -> X and " + "Y end, true, FunEval), if A -> eresye:retract " + "(Engine, X), ~s Pid ! Pattern__; " + "true -> nil end end.", + [PidHash, RetractString])), %%io:format ("Fun = ~p~n", [SFun]), %%io:format ("Pattern = ~p~n", [FinalPattern]), - Fun = evaluate (SFun), - gen_server:call (Name, {add_rule, - {Fun, 0}, - {FinalPattern, []}}), + Fun = evaluate(SFun), + gen_server:call(Name, + {add_rule, {Fun, 0}, {FinalPattern, []}}), %%io:format ("Rete is ~p~n", [eresye:get_rete (Name)]), - eresye:assert (Name, {client, PidHash, self (), FunList}), - receive - Pat -> Pat - end, + eresye:assert(Name, {client, PidHash, self(), FunList}), + receive Pat -> Pat end, %% if %% NeedRetract -> eresye:retract (Name, Pat); %% true -> ok %% end, - gen_server:call (Name, {remove_rule, Fun}), + gen_server:call(Name, {remove_rule, Fun}), Pat. - -term_to_list (X) when is_integer (X) -> integer_to_list (X); -term_to_list (X) when is_atom (X) -> atom_to_list (X); -term_to_list (X) when is_function (X) -> "_"; -term_to_list (X) -> X. - +term_to_list(X) when is_integer(X) -> + integer_to_list(X); +term_to_list(X) when is_atom(X) -> atom_to_list(X); +term_to_list(X) when is_function(X) -> "_"; +term_to_list(X) -> X. %%==================================================================== %% Func: get_ontology/1 %% Arguments: EngineName %%==================================================================== -get_ontology (Name) -> - gen_server:call (Name, {get_ontology}). - +get_ontology(Name) -> + gen_server:call(Name, {get_ontology}). %%==================================================================== %% Func: get_rete/1 %% Arguments: EngineName %%==================================================================== -get_rete (Name) -> - gen_server:call (Name, {get_rete}). - +get_rete(Name) -> gen_server:call(Name, {get_rete}). %%==================================================================== %% Func: get_rules_fired/1 %% Arguments: EngineName %%==================================================================== -get_rules_fired (Name) -> - gen_server:call (Name, {get_rules_fired}). - +get_rules_fired(Name) -> + gen_server:call(Name, {get_rules_fired}). %%==================================================================== %% Func: get_kb/1 %% Arguments: EngineName %%==================================================================== -get_kb (Name) -> - [KB | _] = gen_server:call (Name, {get_rete}), - KB. - +get_kb(Name) -> + [KB | _] = gen_server:call(Name, {get_rete}), KB. %%==================================================================== %% Func: query_kb/2 %% Arguments: EngineName, Pattern %%==================================================================== -query_kb (Name, Pattern) when is_tuple (Pattern) -> - PList = tuple_to_list (Pattern), - PatternSize = length (PList), - FunList = [if - is_function (X) -> X; - X == '_' -> fun (_) -> true end; - true -> fun (Z) -> Z == X end - end || X <- PList], +query_kb(Name, Pattern) when is_tuple(Pattern) -> + PList = tuple_to_list(Pattern), + PatternSize = length(PList), + FunList = [if is_function(X) -> X; + X == '_' -> fun (_) -> true end; + true -> fun (Z) -> Z == X end + end + || X <- PList], MatchFunction = fun (P) -> - FunPatPairs = lists:zip (FunList, tuple_to_list (P)), + FunPatPairs = lists:zip(FunList, tuple_to_list(P)), FunEval = [F(X) || {F, X} <- FunPatPairs], - MatchResult = lists:foldr (fun (X, Y) -> - X and Y - end, - true, - FunEval), + MatchResult = lists:foldr(fun (X, Y) -> X and Y end, + true, FunEval), MatchResult end, - KB = lists:filter (fun (X) -> - size (X) == PatternSize - end, get_kb (Name)), - lists:filter (MatchFunction, KB); + KB = [V1 + || V1 <- get_kb(Name), query_kb_1(V1, PatternSize)], + lists:filter(MatchFunction, KB); %% -query_kb (Name, F) when is_function (F) -> - lists:filter (F, get_kb (Name)). +query_kb(Name, F) when is_function(F) -> + lists:filter(F, get_kb(Name)). +query_kb_1(X, PatternSize) -> size(X) == PatternSize. %%==================================================================== %% Callback functions @@ -312,108 +277,97 @@ query_kb (Name, F) when is_function (F) -> %%==================================================================== %% Func: init/1 %%==================================================================== -init ([EngineName, Ontology]) -> +init([EngineName, Ontology]) -> %% EngineState = [Kb, Alfa, Join, Agenda, State] - EngineState = [ [], - [], - eresye_tree_list:new (), - eresye_agenda:start (EngineName), - Ontology ], + EngineState = [[], [], eresye_tree_list:new(), + eresye_agenda:start(EngineName), Ontology], {ok, EngineState}. - %%==================================================================== %% Func: handle_call/3 %%==================================================================== -handle_call ({stop}, _, State) -> +handle_call({stop}, _, State) -> {stop, normal, ok, State}; - -handle_call ({assert, Fact}, _, State) -> - NewState = assert_fact (State, Fact), +handle_call({assert, Fact}, _, State) -> + NewState = assert_fact(State, Fact), {reply, ok, NewState}; - -handle_call ({retract, Fact}, _, State) -> - NewState = retract_fact (State, Fact), +handle_call({retract, Fact}, _, State) -> + NewState = retract_fact(State, Fact), {reply, ok, NewState}; - -handle_call ({retract_match, MS}, _, State) -> +handle_call({retract_match, MS}, _, State) -> MS2 = [{MS, [], ['$_']}], - NewState = retract_facts (State, MS2), + NewState = retract_facts(State, MS2), {reply, ok, NewState}; - -handle_call ({retract_select, MS}, _, State) -> - NewState = retract_facts (State, MS), +handle_call({retract_select, MS}, _, State) -> + NewState = retract_facts(State, MS), {reply, ok, NewState}; - -handle_call ({add_rule, {Fun, Salience}, {PConds, NConds}}, _, State) -> +handle_call({add_rule, {Fun, Salience}, + {PConds, NConds}}, + _, State) -> %%io:format ("Addrule ~p: ~p~n", [Fun, {PConds, NConds}]), Rule = {Fun, Salience}, [_, _, Join | _] = State, - Root = eresye_tree_list:get_root (Join), + Root = eresye_tree_list:get_root(Join), case NConds of [] -> - NewState = make_struct (State, Rule, PConds, [], Root, nil); + NewState = make_struct(State, Rule, PConds, [], Root, + nil); _ -> - {R1, Np_node} = make_struct (State, Rule, NConds, [], Root, ng), - Root1 = eresye_tree_list:refresh (Root, lists:nth (3, R1)), - NewState = make_struct (R1, Rule, PConds, [], Root1, {Np_node, NConds}) + {R1, Np_node} = make_struct(State, Rule, NConds, [], + Root, ng), + Root1 = eresye_tree_list:refresh(Root, + lists:nth(3, R1)), + NewState = make_struct(R1, Rule, PConds, [], Root1, + {Np_node, NConds}) end, {reply, ok, NewState}; - -handle_call ({remove_rule, Fun}, _, EngineState) -> +handle_call({remove_rule, Fun}, _, EngineState) -> [Kb, Alfa, Join, Agenda, State] = EngineState, - Agenda1 = eresye_agenda:deleteRule (Agenda, Fun), + Agenda1 = eresye_agenda:deleteRule(Agenda, Fun), R1 = [Kb, Alfa, Join, Agenda1, State], - R2 = remove_prod (R1, Fun), + R2 = remove_prod(R1, Fun), {reply, ok, R2}; - -handle_call ({get_rules_fired}, _, State) -> +handle_call({get_rules_fired}, _, State) -> [_, _, _, Agenda, _] = State, - {reply, eresye_agenda:getRulesFired (Agenda), State}; - -handle_call ({get_rete}, _, State) -> + {reply, eresye_agenda:getRulesFired(Agenda), State}; +handle_call({get_rete}, _, State) -> {reply, State, State}; - -handle_call ({get_ontology}, _, State) -> +handle_call({get_ontology}, _, State) -> [_, _, _, _, Ontology] = State, {reply, Ontology, State}. %%==================================================================== %% Func: code_change/3 %%==================================================================== -code_change (OldVsn, State, Extra) -> {ok, State}. +code_change(OldVsn, State, Extra) -> {ok, State}. %%==================================================================== %% Func: terminate/2 %%==================================================================== -terminate (Reason, EngineState) -> - [ _, _, _, AgendaPid, _] = EngineState, - gen_server:call (AgendaPid, {stop}), +terminate(Reason, EngineState) -> + [_, _, _, AgendaPid, _] = EngineState, + gen_server:call(AgendaPid, {stop}), %%io:format ("Terminating...~p~n", [self ()]), ok. - %%==================================================================== %% Internal functions %%==================================================================== %% inizializza la nuova alfa-memory con i fatti presenti %% nella Knowledge Base che soddisfano la condizione Cond -initialize_alfa (_, _, []) -> - nil; -initialize_alfa (Cond, Tab, [Fact | Other_fact]) -> +initialize_alfa(_, _, []) -> nil; +initialize_alfa(Cond, Tab, [Fact | Other_fact]) -> %%io:format ("ALPHA ~p,~p~n", [Cond, Fact]), - Fun = prepare_match_alpha_fun (Cond), + Fun = prepare_match_alpha_fun(Cond), %%io:format ("Fun ~p~n", [Fun]), - case Fun (Fact) of + case Fun(Fact) of Fact -> - ets:insert (Tab, Fact), - initialize_alfa (Cond, Tab, Other_fact); - false -> - initialize_alfa (Cond, Tab, Other_fact) + ets:insert(Tab, Fact), + initialize_alfa(Cond, Tab, Other_fact); + false -> initialize_alfa(Cond, Tab, Other_fact) end. - %% initialize_alfa (Cond, Tab, [Fact | Other_fact]) -> %% io:format ("ALPHA ~p,~p~n", [Cond, Fact]), %% Str = prepare_string (Cond, Fact), @@ -426,209 +380,210 @@ initialize_alfa (Cond, Tab, [Fact | Other_fact]) -> %% initialize_alfa (Cond, Tab, Other_fact) %% end. - - -prepare_match_alpha_fun (Cond) -> - FunString = lists:flatten (io_lib:format ("fun (~s = X__x__X) -> X__x__X;" - " (_) -> false end.", - [Cond])), +prepare_match_alpha_fun(Cond) -> + FunString = + lists:flatten(io_lib:format("fun (~s = X__x__X) -> X__x__X; (_) " + " -> false end.", + [Cond])), %%io:format ("Fun String ~p~n", [FunString]), - evaluate (FunString). + evaluate(FunString). - -get_conds ({Module, Func}, Ontology, ClauseID) -> +get_conds({Module, Func}, Ontology, ClauseID) -> File = lists:concat([Module, '.erl']), {File2, _} = filename:find_src(Module), - case epp:parse_file(File2 ++ ".erl", [".", "src", "include"], []) of + case epp:parse_file(File2 ++ ".erl", + [".", "src", "include"], []) + of {error, OpenError} -> - io:format(">> parse_file error!!!~n~w:~w~n", [{Module, Func}, OpenError]), + io:format(">> parse_file error!!!~n~w:~w~n", + [{Module, Func}, OpenError]), error; {ok, Form} -> - Records = get_records (Form, []), + Records = get_records(Form, []), %io:format (">> Records ~p~n", [Records]), - case search_fun (Form, Func, Records) of + case search_fun(Form, Func, Records) of {error, Msg} -> - io:format(">> search_fun error!!!~n~w:~s~n",[{Module,Func}, Msg]), + io:format(">> search_fun error!!!~n~w:~s~n", + [{Module, Func}, Msg]), error; {ok, CL} -> - ClauseList = - if - ClauseID > 0 -> [lists:nth (ClauseID, CL)]; - true -> CL - end, + ClauseList = if ClauseID > 0 -> + [lists:nth(ClauseID, CL)]; + true -> CL + end, %io:format ("Clauses ~p~n", [ClauseList]), - SolvedClauses = - if - Ontology == nil -> ClauseList; - true -> eresye_ontology_resolver:resolve_ontology (ClauseList, - Ontology) - end, + SolvedClauses = if Ontology == nil -> ClauseList; + true -> + eresye_ontology_resolver:resolve_ontology(ClauseList, + Ontology) + end, %io:format (">>> ~p~n", [SolvedClauses]), case read_clause(SolvedClauses, [], Records) of {error, Msg2} -> - io:format(">> read_clause error!!!~n~w:~s~n",[{Module,Func}, Msg2]), + io:format(">> read_clause error!!!~n~w:~s~n", + [{Module, Func}, Msg2]), error; CondsList -> CondsList end end end. - -get_records ([], Acc) -> lists:reverse (Acc); -get_records ([{attribute, _, record, {RecordName, RecordFields}} | Tail], - Acc) -> - NewAcc = [{RecordName, get_record_fields (RecordFields, [])} | Acc], - get_records (Tail, NewAcc); -get_records ([_ | Tail], Acc) -> - get_records (Tail, Acc). - - -get_record_fields ([], Acc) -> lists:reverse (Acc); -get_record_fields ([{record_field, _, - {atom, _, FieldName}, {atom, _, DefaultValue}} | Tail], - Acc) -> +get_records([], Acc) -> lists:reverse(Acc); +get_records([{attribute, _, record, + {RecordName, RecordFields}} + | Tail], + Acc) -> + NewAcc = [{RecordName, + get_record_fields(RecordFields, [])} + | Acc], + get_records(Tail, NewAcc); +get_records([_ | Tail], Acc) -> get_records(Tail, Acc). + +get_record_fields([], Acc) -> lists:reverse(Acc); +get_record_fields([{record_field, _, + {atom, _, FieldName}, {atom, _, DefaultValue}} + | Tail], + Acc) -> NewAcc = [{FieldName, DefaultValue} | Acc], - get_record_fields (Tail, NewAcc); -get_record_fields ([{record_field, _, {atom, _, FieldName}} | Tail], - Acc) -> + get_record_fields(Tail, NewAcc); +get_record_fields([{record_field, _, + {atom, _, FieldName}} + | Tail], + Acc) -> NewAcc = [{FieldName} | Acc], - get_record_fields (Tail, NewAcc). + get_record_fields(Tail, NewAcc). - -search_fun ([], _, RecordList) -> - {error,"Funzione non trovata"}; -search_fun ([{function, _, Func, _, ClauseList} | Other], Func, RecordList) -> +search_fun([], _, RecordList) -> + {error, "Funzione non trovata"}; +search_fun([{function, _, Func, _, ClauseList} | Other], + Func, RecordList) -> {ok, ClauseList}; %% read_clause(ClauseList, [], RecordList); -search_fun ([Tuple | Other], Func, RecordList) -> - search_fun (Other, Func, RecordList). - +search_fun([Tuple | Other], Func, RecordList) -> + search_fun(Other, Func, RecordList). - -read_clause([], CondsList, RecordList)-> - CondsList; -read_clause([Clause | OtherClause], CondsList, RecordList) -> +read_clause([], CondsList, RecordList) -> CondsList; +read_clause([Clause | OtherClause], CondsList, + RecordList) -> {clause, _, ParamList, GuardList, _} = Clause, %%PosConds = read_param (ParamList), - PosConds = read_parameters (ParamList, RecordList), + PosConds = read_parameters(ParamList, RecordList), %%io:format (">>> Positive conditions : ~p~n", [PosConds]), - NegConds = read_guard (GuardList), - CondsList1 = lists:append (CondsList,[{PosConds, NegConds}]), - read_clause (OtherClause, CondsList1, RecordList). - -read_guard ([]) -> - []; -read_guard ([[{op,_,'not', Conds}|_] | OtherGuard]) -> - Nc = get_neg_cond(Conds, []), - lists:reverse(Nc); -read_guard (Guard) -> - []. - -get_neg_cond ({nil,_}, Nc) -> - Nc; -get_neg_cond ({cons, _, {string, _, C}, OtherC}, Nc) -> - Nc1 = [C | Nc], - get_neg_cond(OtherC, Nc1); -get_neg_cond (X, Nc) -> - io:format(">> Negated Conditions must be a list of String~n"), + NegConds = read_guard(GuardList), + CondsList1 = CondsList ++ [{PosConds, NegConds}], + read_clause(OtherClause, CondsList1, RecordList). + +read_guard([]) -> []; +read_guard([[{op, _, 'not', Conds} | _] + | OtherGuard]) -> + Nc = get_neg_cond(Conds, []), lists:reverse(Nc); +read_guard(Guard) -> []. + +get_neg_cond({nil, _}, Nc) -> Nc; +get_neg_cond({cons, _, {string, _, C}, OtherC}, Nc) -> + Nc1 = [C | Nc], get_neg_cond(OtherC, Nc1); +get_neg_cond(X, Nc) -> + io:format(">> Negated Conditions must be a list " + "of String~n"), []. - -read_parameters ([{var, _, _} | Tail], RecordList) -> - P = extract_parameters (Tail, [], RecordList), +read_parameters([{var, _, _} | Tail], RecordList) -> + P = extract_parameters(Tail, [], RecordList), %%io:format ("read_parameters = ~p~n", [P]), - Conditions = [ build_string_condition (X, []) || X <- P], + Conditions = [build_string_condition(X, []) || X <- P], Conditions. - - - -extract_parameters ([], Acc, RecordList) -> - lists:reverse (Acc); - -extract_parameters ([{match, _, {tuple, _, Condition}, {var, _, _}} | Tail], - Acc, RecordList) -> - extract_parameters (Tail, [Condition | Acc], RecordList); - -extract_parameters ([{match, _, {var, _, _}, {tuple, _, Condition}} | Tail], - Acc, RecordList) -> - extract_parameters (Tail, [Condition | Acc], RecordList); - -extract_parameters ([{match, _, {record, _, _, _} = R, {var, _, _}} | Tail], - Acc, RecordList) -> - extract_parameters ([R | Tail], Acc, RecordList); - -extract_parameters ([{match, _, {var, _, _}, {record, _, _, _} = R} | Tail], - Acc, RecordList) -> - extract_parameters ([R | Tail], Acc, RecordList); - -extract_parameters ([{record, _, RecordName, Condition} | Tail], - Acc, RecordList) -> +extract_parameters([], Acc, RecordList) -> + lists:reverse(Acc); +extract_parameters([{match, _, {tuple, _, Condition}, + {var, _, _}} + | Tail], + Acc, RecordList) -> + extract_parameters(Tail, [Condition | Acc], RecordList); +extract_parameters([{match, _, {var, _, _}, + {tuple, _, Condition}} + | Tail], + Acc, RecordList) -> + extract_parameters(Tail, [Condition | Acc], RecordList); +extract_parameters([{match, _, {record, _, _, _} = R, + {var, _, _}} + | Tail], + Acc, RecordList) -> + extract_parameters([R | Tail], Acc, RecordList); +extract_parameters([{match, _, {var, _, _}, + {record, _, _, _} = R} + | Tail], + Acc, RecordList) -> + extract_parameters([R | Tail], Acc, RecordList); +extract_parameters([{record, _, RecordName, Condition} + | Tail], + Acc, RecordList) -> %%io:format ("Record: ~p~nCondition: ~p~n", [RecordName, Condition]), - RecordDefinition = get_record_def (RecordName, RecordList), + RecordDefinition = get_record_def(RecordName, + RecordList), %%io:format ("Record Definition: ~p~n", [RecordDefinition]), - RecordDefaults = make_record_default (RecordDefinition, []), + RecordDefaults = make_record_default(RecordDefinition, + []), %%io:format ("Record Defaults: ~p~n", [RecordDefaults]), - Pattern = [{atom, 0, RecordName} | - make_record_pattern (Condition, RecordDefaults, - RecordDefinition)], + Pattern = [{atom, 0, RecordName} + | make_record_pattern(Condition, RecordDefaults, + RecordDefinition)], %%io:format ("Record Pattern: ~p~n", [Pattern]), - extract_parameters (Tail, [Pattern | Acc], RecordList); - -extract_parameters ([{tuple, _, Condition} | Tail], Acc, RecordList) -> - extract_parameters (Tail, [Condition | Acc], RecordList). - - - - - -get_record_def (_, []) -> nil; -get_record_def (Name, [{Name, Definition} | Rest]) -> Definition; -get_record_def (Name, [_ | Rest]) -> get_record_def (Name, Rest). - - -make_record_default ([], Acc) -> - lists:reverse (Acc); -make_record_default ([{_} | Tail], Acc) -> - make_record_default (Tail, [{var, 0, '_'} | Acc]); -make_record_default ([{_, Value} | Tail], Acc) -> - make_record_default (Tail, [{atom, 0, Value} | Acc]). - - -make_record_pattern ([], Pattern, RecordDefinition) -> + extract_parameters(Tail, [Pattern | Acc], RecordList); +extract_parameters([{tuple, _, Condition} | Tail], Acc, + RecordList) -> + extract_parameters(Tail, [Condition | Acc], RecordList). + +get_record_def(_, []) -> nil; +get_record_def(Name, [{Name, Definition} | Rest]) -> + Definition; +get_record_def(Name, [_ | Rest]) -> + get_record_def(Name, Rest). + +make_record_default([], Acc) -> lists:reverse(Acc); +make_record_default([{_} | Tail], Acc) -> + make_record_default(Tail, [{var, 0, '_'} | Acc]); +make_record_default([{_, Value} | Tail], Acc) -> + make_record_default(Tail, [{atom, 0, Value} | Acc]). + +make_record_pattern([], Pattern, RecordDefinition) -> Pattern; -make_record_pattern ([{record_field, _, {atom, _, FieldName}, MatchValue} - | Tail], Pattern, RecordDefinition) -> - FieldPosition = get_record_field_pos (FieldName, RecordDefinition, 1), - NewPattern = - lists:sublist (Pattern, FieldPosition - 1) ++ +make_record_pattern([{record_field, _, + {atom, _, FieldName}, MatchValue} + | Tail], + Pattern, RecordDefinition) -> + FieldPosition = get_record_field_pos(FieldName, + RecordDefinition, 1), + NewPattern = lists:sublist(Pattern, FieldPosition - 1) + ++ [MatchValue] ++ - lists:sublist (Pattern, FieldPosition + 1, - length (Pattern) - FieldPosition), - make_record_pattern (Tail, NewPattern, RecordDefinition). - - -get_record_field_pos (Name, [], _) -> exit ({bad_record_field, Name}); -get_record_field_pos (Name, [{Name, _} | _], Index) -> Index; -get_record_field_pos (Name, [{Name} | _], Index) -> Index; -get_record_field_pos (Name, [_ | Tail], Index) -> - get_record_field_pos (Name, Tail, Index + 1). - -build_string_condition ([], Acc) -> - lists:concat (["{", tl (lists:flatten (lists:reverse (Acc))), "}"]); -build_string_condition ([{atom, _, Value} | Tail], Acc) -> - Term = lists:concat ([",'", atom_to_list (Value), "'"]), - build_string_condition (Tail, - [ Term | Acc]); -build_string_condition ([{integer, _, Value} | Tail], Acc) -> - Term = lists:concat ([",", integer_to_list (Value)]), - build_string_condition (Tail, - [ Term | Acc]); -build_string_condition ([{var, _, Value} | Tail], Acc) -> - Term = lists:concat ([",", atom_to_list (Value)]), - build_string_condition (Tail, - [ Term | Acc]). - + lists:sublist(Pattern, FieldPosition + 1, + length(Pattern) - FieldPosition), + make_record_pattern(Tail, NewPattern, RecordDefinition). + +get_record_field_pos(Name, [], _) -> + exit({bad_record_field, Name}); +get_record_field_pos(Name, [{Name, _} | _], Index) -> + Index; +get_record_field_pos(Name, [{Name} | _], Index) -> + Index; +get_record_field_pos(Name, [_ | Tail], Index) -> + get_record_field_pos(Name, Tail, Index + 1). + +build_string_condition([], Acc) -> + lists:concat(["{", + tl(lists:flatten(lists:reverse(Acc))), "}"]); +build_string_condition([{atom, _, Value} | Tail], + Acc) -> + Term = lists:concat([",'", atom_to_list(Value), "'"]), + build_string_condition(Tail, [Term | Acc]); +build_string_condition([{integer, _, Value} | Tail], + Acc) -> + Term = lists:concat([",", integer_to_list(Value)]), + build_string_condition(Tail, [Term | Acc]); +build_string_condition([{var, _, Value} | Tail], Acc) -> + Term = lists:concat([",", atom_to_list(Value)]), + build_string_condition(Tail, [Term | Acc]). %% read_param ([{var, _, EngineName} | {nil,_}]) -> % Non ci sono condizioni %% []; @@ -714,83 +669,86 @@ build_string_condition ([{var, _, Value} | Tail], Acc) -> %% lists:concat([S, ',', Str1]) %% end. - - %% P e' una lista contenente le condizioni precedenti a Cond %% della stessa produzione -make_struct (R, Rule, [], P, Cur_node, ng) -> +make_struct(R, Rule, [], P, Cur_node, ng) -> [Kb, Alfa, Join, Agenda, State] = R, %crea production node Key = {np_node, nil}, case eresye_tree_list:child(Key, Cur_node, Join) of false -> Value = [], - {Node, Join1} = eresye_tree_list:insert(Key, Value, Cur_node, Join), + {Node, Join1} = eresye_tree_list:insert(Key, Value, + Cur_node, Join), % io:format("Np_node=~w~n",[Node]), - {Join2, Agenda1} = update_new_node (Node, Cur_node, Join1, Agenda); - Node -> - Join2 = Join, - Agenda1 = Agenda + {Join2, Agenda1} = update_new_node(Node, Cur_node, + Join1, Agenda); + Node -> Join2 = Join, Agenda1 = Agenda end, {[Kb, Alfa, Join2, Agenda1, State], Node}; -make_struct (R, Rule, [], P, Cur_node, nil) -> +make_struct(R, Rule, [], P, Cur_node, nil) -> [Kb, Alfa, Join, Agenda, State] = R, %crea production node Key = {p_node, Rule}, case eresye_tree_list:child(Key, Cur_node, Join) of false -> Value = [], - {Node, Join1} = eresye_tree_list:insert(Key, Value, Cur_node, Join), - {Join2, Agenda1} = update_new_node (Node, Cur_node, Join1, Agenda); + {Node, Join1} = eresye_tree_list:insert(Key, Value, + Cur_node, Join), + {Join2, Agenda1} = update_new_node(Node, Cur_node, + Join1, Agenda); Node -> {Fun, Salience} = Rule, - Key1 =element(1, Node), + Key1 = element(1, Node), Sal = element(2, element(2, Key1)), - io:format(">> Rule (~w) already present ~n",[Fun]), - io:format(">> with salience = ~w~n",[Sal]), + io:format(">> Rule (~w) already present ~n", [Fun]), + io:format(">> with salience = ~w~n", [Sal]), io:format(">> To change salience use 'set_salience()'.~n"), Join2 = Join, Agenda1 = Agenda end, [Kb, Alfa, Join2, Agenda1, State]; -make_struct (R, Rule, [], P, Cur_node, {Nod, NConds}) -> +make_struct(R, Rule, [], P, Cur_node, {Nod, NConds}) -> [Kb, Alfa, Join, Agenda, State] = R, Id = eresye_tree_list:get_id(Nod), - {Cur_node1, Join1, Agenda1} = make_join_node (Join, - {old,{n_node, Id}}, - NConds, P, Cur_node, Agenda), + {Cur_node1, Join1, Agenda1} = make_join_node(Join, + {old, {n_node, Id}}, NConds, P, + Cur_node, Agenda), Nod1 = eresye_tree_list:refresh(Nod, Join1), - Join2 = eresye_tree_list:set_child(Cur_node1, Nod1, Join1), + Join2 = eresye_tree_list:set_child(Cur_node1, Nod1, + Join1), %crea production node Key = {p_node, Rule}, case eresye_tree_list:child(Key, Cur_node1, Join2) of false -> Value = [], - {Node, Join3} = eresye_tree_list:insert(Key, Value, Cur_node1, Join2), + {Node, Join3} = eresye_tree_list:insert(Key, Value, + Cur_node1, Join2), % io:format("P_node=~w~n",[Node]), Cur_node2 = eresye_tree_list:refresh(Cur_node1, Join3), - {Join4, Agenda2} = update_new_node (Node, Cur_node2, Join3, Agenda1); + {Join4, Agenda2} = update_new_node(Node, Cur_node2, + Join3, Agenda1); Node -> {Fun, Salience} = Rule, Key1 = element(1, Node), Sal = element(2, element(2, Key1)), - io:format(">> Rule (~w) already present ~n",[Fun]), - io:format(">> with salience = ~w~n",[Sal]), + io:format(">> Rule (~w) already present ~n", [Fun]), + io:format(">> with salience = ~w~n", [Sal]), io:format(">> To change salience use 'set_salience()'.~n"), Join4 = Join2, Agenda2 = Agenda1 end, [Kb, Alfa, Join4, Agenda2, State]; -make_struct (R, Rule, [Cond|T], P, Cur_node, Nod) -> +make_struct(R, Rule, [Cond | T], P, Cur_node, Nod) -> [Kb, Alfa, Join, Agenda, State] = R, {Alfa1, Tab} = add_alfa(R, Cond), - {Cur_node1, Join1, Agenda1} = make_join_node (Join, Tab, Cond, P, - Cur_node, Agenda), - P1 = lists:append(P, [Cond]), - make_struct([Kb, Alfa1, Join1, Agenda1, State], Rule, T, P1, Cur_node1, Nod). + {Cur_node1, Join1, Agenda1} = make_join_node(Join, Tab, + Cond, P, Cur_node, Agenda), + P1 = P ++ [Cond], + make_struct([Kb, Alfa1, Join1, Agenda1, State], Rule, T, + P1, Cur_node1, Nod). - -add_alfa (R, Cond)-> +add_alfa(R, Cond) -> [Kb, Alfa, Join, _, _] = R, case is_present(Cond, Alfa) of false -> @@ -801,72 +759,69 @@ add_alfa (R, Cond)-> Alfa1 = [{Cond, Tab, Alfa_fun} | Alfa], initialize_alfa(Cond, Tab, Kb), {Alfa1, {new, Tab}}; - {true, Tab} -> - {Alfa, {old, Tab}} + {true, Tab} -> {Alfa, {old, Tab}} end. - %% prepara una stringa del tipo Cond=Fact %% (es. "{X, on, Y}={b1, on, b3}." ) -prepare_string (Cond, Fact) -> +prepare_string(Cond, Fact) -> Fact1 = tuple_to_list(Fact), Str = lists:concat([Cond, "={"]), %%io:format ("F1 = ~p~n", [Fact1]), - Str1 = append_fact ([], Fact1, siend), + Str1 = append_fact([], Fact1, siend), Str2 = string:concat(Str, Str1). - - -append_fact (H, [Elem], Flag) when is_list(Elem) -> - H1 = lists:concat([H,"[", append_fact([], Elem, noend), "]}."]); -append_fact (H, [Elem], Flag) when is_tuple(Elem) -> +append_fact(H, [Elem], Flag) when is_list(Elem) -> + H1 = lists:concat([H, "[", append_fact([], Elem, noend), + "]}."]); +append_fact(H, [Elem], Flag) when is_tuple(Elem) -> Elem1 = tuple_to_list(Elem), - H1 = lists:concat([H,"{", append_fact([], Elem1, noend), "}}."]); -append_fact (H, [Elem], Flag) when is_integer (Elem) -> + H1 = lists:concat([H, "{", + append_fact([], Elem1, noend), "}}."]); +append_fact(H, [Elem], Flag) when is_integer(Elem) -> case Flag of - noend -> - lists:concat([H, Elem]); - Other -> - lists:concat([H, Elem, "}."]) + noend -> lists:concat([H, Elem]); + Other -> lists:concat([H, Elem, "}."]) end; -append_fact (H, [Elem], Flag) -> +append_fact(H, [Elem], Flag) -> case Flag of - noend -> - lists:concat([H, "'", Elem, "'"]); - Other -> - lists:concat([H, "'", Elem, "'}."]) + noend -> lists:concat([H, "'", Elem, "'"]); + Other -> lists:concat([H, "'", Elem, "'}."]) end; -append_fact (H, [Elem | Other_elem], Flag) when is_list(Elem) -> - H1 = lists:concat([H,"[", append_fact([], Elem, noend), "],"]), - append_fact (H1, Other_elem, Flag); -append_fact (H, [Elem | Other_elem], Flag) when is_tuple(Elem) -> +append_fact(H, [Elem | Other_elem], Flag) + when is_list(Elem) -> + H1 = lists:concat([H, "[", append_fact([], Elem, noend), + "],"]), + append_fact(H1, Other_elem, Flag); +append_fact(H, [Elem | Other_elem], Flag) + when is_tuple(Elem) -> Elem1 = tuple_to_list(Elem), - H1 = lists:concat([H,"{", append_fact([], Elem1, noend), "},"]), - append_fact (H1, Other_elem, Flag); -append_fact (H, [Elem | Other_elem], Flag) when is_integer(Elem) -> + H1 = lists:concat([H, "{", + append_fact([], Elem1, noend), "},"]), + append_fact(H1, Other_elem, Flag); +append_fact(H, [Elem | Other_elem], Flag) + when is_integer(Elem) -> H1 = lists:concat([H, Elem, ","]), - append_fact (H1, Other_elem, Flag); -append_fact (H, [Elem | Other_elem], Flag) -> - H1 = lists:concat([H,"'", Elem, "',"]), - append_fact (H1, Other_elem, Flag). + append_fact(H1, Other_elem, Flag); +append_fact(H, [Elem | Other_elem], Flag) -> + H1 = lists:concat([H, "'", Elem, "',"]), + append_fact(H1, Other_elem, Flag). - - -remove_prod (R, Fun) -> +remove_prod(R, Fun) -> [Kb, Alfa, Join, Agenda, State] = R, case eresye_tree_list:keysearch({p_node, Fun}, Join) of - false -> - R; + false -> R; Node -> Parent_node = eresye_tree_list:get_parent(Node, Join), Join1 = eresye_tree_list:remove_node(Node, Join), - Parent_node1 = eresye_tree_list:refresh(Parent_node, Join1), - R1 = remove_nodes (Parent_node1, [Kb, Alfa, Join1, Agenda, State]), - remove_prod (R1, Fun) + Parent_node1 = eresye_tree_list:refresh(Parent_node, + Join1), + R1 = remove_nodes(Parent_node1, + [Kb, Alfa, Join1, Agenda, State]), + remove_prod(R1, Fun) end. - -remove_nodes (Node, R) -> +remove_nodes(Node, R) -> [Kb, Alfa, Join, Agenda, State] = R, case eresye_tree_list:have_child(Node) of false -> @@ -874,21 +829,24 @@ remove_nodes (Node, R) -> false -> Parent_node = eresye_tree_list:get_parent(Node, Join), Join1 = eresye_tree_list:remove_node(Node, Join), - Parent_node1 = eresye_tree_list:refresh(Parent_node, Join1), + Parent_node1 = eresye_tree_list:refresh(Parent_node, + Join1), {First, _} = eresye_tree_list:get_key(Node), case First of {n_node, IdNp_node} -> ParentKey = eresye_tree_list:get_key(Parent_node1), % elimino tutti i nodi relativi alle condizioni negate Np_node = eresye_tree_list:get_node(IdNp_node, Join1), - Join2 = eresye_tree_list:remove_child(Node, Np_node, Join1), + Join2 = eresye_tree_list:remove_child(Node, Np_node, + Join1), R1 = [Kb, Alfa, Join2, Agenda, State], Np_node1 = eresye_tree_list:refresh(Np_node, Join2), R2 = remove_nodes(Np_node1, R1), % recupero il parent node del nodo n_node passato come argomento % il parent puo' avere adesso un altro id, ma ha la stessa key Join3 = lists:nth(3, R2), - Parent_node2 = eresye_tree_list:keysearch(ParentKey, Join3), + Parent_node2 = eresye_tree_list:keysearch(ParentKey, + Join3), remove_nodes(Parent_node2, R2); np_node -> R1 = [Kb, Alfa, Join1, Agenda, State], @@ -898,33 +856,27 @@ remove_nodes (Node, R) -> false -> ets:delete(Tab), Alfa1 = lists:keydelete(Tab, 2, Alfa); - true -> - Alfa1 = Alfa + true -> Alfa1 = Alfa end, R1 = [Kb, Alfa1, Join1, Agenda, State], remove_nodes(Parent_node1, R1) end; - true -> - R + true -> R end; - true -> - R + true -> R end. %% verifica se la condizione Cond e' gia' presente -is_present (Cond, []) -> - false; -is_present (Cond, [{C1, Tab, Alfa_fun} | Other_cond]) -> +is_present(Cond, []) -> false; +is_present(Cond, [{C1, Tab, Alfa_fun} | Other_cond]) -> case same_cond(Cond, C1) of true -> {true, Tab}; false -> is_present(Cond, Other_cond) end. - -same_cond (Cond1, Cond1) -> - true; -same_cond (Cond1, Cond2) -> +same_cond(Cond1, Cond1) -> true; +same_cond(Cond1, Cond2) -> C2 = parse_cond(Cond2), S1 = prepare_string(Cond1, C2), % io:format("S1=~s~n",[S1]), @@ -940,55 +892,54 @@ same_cond (Cond1, Cond2) -> false -> false end. - -parse_cond (L) -> - L1 = string:sub_string(L, 2, length(L)-1), +parse_cond(L) -> + L1 = string:sub_string(L, 2, length(L) - 1), list_to_tuple(to_elem(L1)). - -to_elem ([]) -> - []; +to_elem([]) -> []; %% l'elemento e' una tupla -to_elem (L) when hd(L)==${ -> +to_elem(L) when hd(L) == ${ -> ElemStr = string:sub_string(L, 2), {List, OtherStr} = to_elem(ElemStr), T = list_to_tuple(List), Other = to_elem(OtherStr), - E1=lists:append([T], Other), + E1 = [T] ++ Other, E1; -to_elem (L) when hd(L)==$[ -> +to_elem(L) when hd(L) == $[ -> ElemStr = string:sub_string(L, 2), {List, OtherStr} = to_elem(ElemStr), Other = to_elem(OtherStr), - Li = lists:append([List], Other), + Li = [List] ++ Other, Li; -to_elem (L) when hd(L)==$, -> - L1 = string:sub_string(L, 2), - to_elem(L1); -to_elem (L) -> +to_elem(L) when hd(L) == $, -> + L1 = string:sub_string(L, 2), to_elem(L1); +to_elem(L) -> Index1 = string:chr(L, $,), Index2 = string:chr(L, $}), Index3 = string:chr(L, $]), to_elem(Index1, Index2, Index3, L). + to_elem(I1, I2, I3, L) - when I2/=0, ((I2 + when I2 /= 0, (I2 < I1) or (I1 == 0), + (I2 < I3) or (I3 == 0) -> % l'elemento e' l'ultimo elemento di una tupla - ElemStr = string:sub_string(L, 1, I2-1), - OtherStr = string:sub_string(L, I2+1), + ElemStr = string:sub_string(L, 1, I2 - 1), + OtherStr = string:sub_string(L, I2 + 1), Elem = get_atom(ElemStr), {[Elem], OtherStr}; -to_elem (I1, I2, I3, L) - when I3/=0, ((I3 +to_elem(I1, I2, I3, L) + when I3 /= 0, (I3 < I1) or (I1 == 0), + (I3 < I2) or (I2 == 0) -> % l'elemento e' l'ultimo elemento di una lista - ElemStr = string:sub_string(L, 1, I3-1), - OtherStr = string:sub_string(L, I3+1), + ElemStr = string:sub_string(L, 1, I3 - 1), + OtherStr = string:sub_string(L, I3 + 1), Elem = get_atom(ElemStr), {[Elem], OtherStr}; -to_elem (I1, I2, I3, L) -> +to_elem(I1, I2, I3, L) -> case I1 == 0 of false -> - ElemStr = string:sub_string(L, 1, I1-1), - OtherStr = string:sub_string(L, I1+1); + ElemStr = string:sub_string(L, 1, I1 - 1), + OtherStr = string:sub_string(L, I1 + 1); true -> % e' l'ultimo elemento ElemStr = L, @@ -996,65 +947,55 @@ to_elem (I1, I2, I3, L) -> end, Elem = [get_atom(ElemStr)], case to_elem(OtherStr) of - {Other, Str} -> - E = lists:append(Elem, Other), - {E, Str}; - Other -> - A = lists:append(Elem, Other), - A + {Other, Str} -> E = Elem ++ Other, {E, Str}; + Other -> A = Elem ++ Other, A end. - %% Prende in ingresso una stringa del tipo L="{elem1,elem1,...elemM}" %% restituisce la tupla corrispondente ({elem1, elem2,...elemN}) %% trasformando le variabili in atomi (X->'X') -get_atom (X) when hd(X)==$' -> %' +get_atom(X) + when hd(X) == $' -> %' L = length(X), case lists:nth(L, X) of 39 -> - Sub = string:sub_string(X, 2, L-1), - list_to_atom(Sub); + Sub = string:sub_string(X, 2, L - 1), list_to_atom(Sub); Other -> - io:format(">> get_atom error (manca l'apice):~s~n",[X]) + io:format(">> get_atom error (manca l'apice):~s~n", [X]) end; -get_atom (X) -> - X1 = string:strip(X), - list_to_atom(X1). +get_atom(X) -> X1 = string:strip(X), list_to_atom(X1). - - - -evaluate (String) -> +evaluate(String) -> %%io:format ("FUN = ~p~n", [String]), - {ok, Tokens, _} = erl_scan:string (String), - {ok, Expr} = erl_parse:parse_exprs (Tokens), - case catch (erl_eval:exprs (Expr, erl_eval:new_bindings ())) of + {ok, Tokens, _} = erl_scan:string(String), + {ok, Expr} = erl_parse:parse_exprs(Tokens), + case catch erl_eval:exprs(Expr, erl_eval:new_bindings()) + of {'EXIT', _} -> false; {value, Value, Bindings} -> Value; _ -> false end. - -prepare_fun (Cond, []) -> - "nil."; -prepare_fun (Cond, [Cond1| T1]) when hd(Cond)==${ -> - Str = lists:concat(["F=fun(", Cond, ",[", Cond1, string_tail(T1, []), "])->true end."]), +prepare_fun(Cond, []) -> "nil."; +prepare_fun(Cond, [Cond1 | T1]) when hd(Cond) == ${ -> + Str = lists:concat(["F=fun(", Cond, ",[", Cond1, + string_tail(T1, []), "])->true end."]), %% io:format("ST=~s~n",[Str]), Str; -prepare_fun ([Cond|T], [Cond1| T1]) -> - Str = lists:concat(["F=fun([", Cond, string_tail(T,[]), "],[", Cond1, string_tail(T1, []), "])->true end."]), +prepare_fun([Cond | T], [Cond1 | T1]) -> + Str = lists:concat(["F=fun([", Cond, string_tail(T, []), + "],[", Cond1, string_tail(T1, []), "])->true end."]), % io:format("ST2=~s~n",[Str]), Str. -string_tail ([], Str) -> - Str; -string_tail ([C| OtherC], Str) -> +string_tail([], Str) -> Str; +string_tail([C | OtherC], Str) -> Str1 = lists:concat([Str, ",", C]), string_tail(OtherC, Str1). %% aggiorna il nuovo join_node inserendo eventuali token nella Beta-memory -update_new_node (Node, Parent_node, Join, Agenda) -> +update_new_node(Node, Parent_node, Join, Agenda) -> % io:format("Update-Node=~w~n",[Node]), % io:format("Parent=~w~n",[Parent_node]), case eresye_tree_list:is_root(Parent_node) of @@ -1064,51 +1005,53 @@ update_new_node (Node, Parent_node, Join, Agenda) -> [] -> case eresye_tree_list:get_key(Parent_node) of {{n_node, IdNp_node}, Join_fun} -> - Beta = eresye_tree_list:get_beta (Parent_node), - update_from_n_node (Parent_node, Beta, Join, Agenda); + Beta = eresye_tree_list:get_beta(Parent_node), + update_from_n_node(Parent_node, Beta, Join, Agenda); {Tab, _} -> %%Tab = element(1, element(1, Parent_node)), Fact_list = ets:tab2list(Tab), - update_new_node (Node, Parent_node, Join, Fact_list, Agenda) + update_new_node(Node, Parent_node, Join, Fact_list, + Agenda) end; [Child | Other_child] -> - Beta = eresye_tree_list:get_beta (Child), - Join1 = eresye_tree_list:update_beta (Beta, Node, Join), - case eresye_tree_list:get_key (Node) of + Beta = eresye_tree_list:get_beta(Child), + Join1 = eresye_tree_list:update_beta(Beta, Node, Join), + case eresye_tree_list:get_key(Node) of {p_node, Rule} -> - Agenda1 = update_agenda (Agenda, Beta, Rule); - Key -> - Agenda1 = Agenda + Agenda1 = update_agenda(Agenda, Beta, Rule); + Key -> Agenda1 = Agenda end, {Join1, Agenda1} end; - true -> - {Join, Agenda} + true -> {Join, Agenda} end. - -update_agenda (Agenda, [], Rule) -> - Agenda; -update_agenda (Agenda, [Tok| OtherTok], Rule) -> +update_agenda(Agenda, [], Rule) -> Agenda; +update_agenda(Agenda, [Tok | OtherTok], Rule) -> %%io:format ("UPDATE AGENDA ~p~n", [Rule]), Agenda1 = signal(Tok, plus, Rule, Agenda), update_agenda(Agenda1, OtherTok, Rule). - -update_new_node (Node, Parent_node, Join, [], Agenda) -> +update_new_node(Node, Parent_node, Join, [], Agenda) -> {Join, Agenda}; -update_new_node (Node, Parent_node, Join, [Fact | Other_fact], Agenda) -> +update_new_node(Node, Parent_node, Join, + [Fact | Other_fact], Agenda) -> Tok_list = right_act({Fact, plus}, Parent_node), - {Join1, Agenda1} = pass_tok(Tok_list, [Node], Join, Agenda), + {Join1, Agenda1} = pass_tok(Tok_list, [Node], Join, + Agenda), Node1 = eresye_tree_list:refresh(Node, Join1), - update_new_node (Node1, Parent_node, Join1, Other_fact, Agenda1). + update_new_node(Node1, Parent_node, Join1, Other_fact, + Agenda1). -update_from_n_node (Parent_node, [], Join, Agenda) -> +update_from_n_node(Parent_node, [], Join, Agenda) -> Join1 = eresye_tree_list:update_node(Parent_node, Join), {Join1, Agenda}; -update_from_n_node ( Parent_node, [Tok|OtherTok], Join, Agenda) -> - {Join1, Agenda1} = left_act({Tok, plus}, [Parent_node], Join, Agenda), - update_from_n_node(Parent_node, OtherTok, Join1, Agenda1). +update_from_n_node(Parent_node, [Tok | OtherTok], Join, + Agenda) -> + {Join1, Agenda1} = left_act({Tok, plus}, [Parent_node], + Join, Agenda), + update_from_n_node(Parent_node, OtherTok, Join1, + Agenda1). %% execute_rule (Rule, Args, State) -> %% callfunction (Rule, Args), @@ -1124,15 +1067,13 @@ update_from_n_node ( Parent_node, [Tok|OtherTok], Join, Agenda) -> %% 5000 -> throw ({timeout, Data}) %% end. - - - -signal (Token, Sign, {Fun, Salience}, Agenda) -> +signal(Token, Sign, {Fun, Salience}, Agenda) -> case Sign of plus -> % spawn(ser, callfunction, [self(), Fun, Token]), %io:format(">> New match for production ~w~n", [Fun]), - eresye_agenda:addActivation(Agenda, Fun,[self(), Token], Salience); + eresye_agenda:addActivation(Agenda, Fun, + [self(), Token], Salience); minus -> %io:format(">> Lost match for production ~w~n", [Fun]), ActivationId = eresye_agenda:getActivation(Agenda, @@ -1140,7 +1081,6 @@ signal (Token, Sign, {Fun, Salience}, Agenda) -> eresye_agenda:deleteActivation(Agenda, ActivationId) end. - %% callfunction (Fun ,Term) -> %% %io:format("callfunction~n"), %% case catch (apply (Fun, Term)) of @@ -1149,11 +1089,9 @@ signal (Token, Sign, {Fun, Salience}, Agenda) -> %% Other -> Other %% end. - %% end_processing (State) -> %% lists:delete(processing, State). - %%==================================================================== %% Fact Assertion/Retraction Functions %%==================================================================== @@ -1161,129 +1099,127 @@ signal (Token, Sign, {Fun, Salience}, Agenda) -> %% It also checks if the fact verifies any condition, %% if this is the case the fact is also inserted in the alpha-memory %%==================================================================== -assert_fact (R, Fact) -> +assert_fact(R, Fact) -> [Kb, Alfa, Join, Agenda, State] = R, - case lists:member (Fact, Kb) of + case lists:member(Fact, Kb) of false -> Kb1 = [Fact | Kb], - check_cond ([Kb1, Alfa, Join, Agenda, State], Alfa, {Fact, plus}); - true -> - R + check_cond([Kb1, Alfa, Join, Agenda, State], Alfa, + {Fact, plus}); + true -> R end. - -retract_fact (R, Fact) -> +retract_fact(R, Fact) -> [Kb, Alfa, Join, Agenda, State] = R, - case lists:member (Fact, Kb) of + case lists:member(Fact, Kb) of true -> Kb1 = Kb -- [Fact], - check_cond ([Kb1, Alfa, Join, Agenda, State], Alfa, {Fact, minus}); - false -> - R + check_cond([Kb1, Alfa, Join, Agenda, State], Alfa, + {Fact, minus}); + false -> R end. retract_facts(R, FactMatch) -> [Kb, Alfa, Join, Agenda, State] = R, MSC = ets:match_spec_compile(FactMatch), Facts = ets:match_spec_run(Kb, MSC), - lists:foldl(fun(X, S) -> - retract_fact(S, X) - end, R, Facts). - + lists:foldl(fun (X, S) -> retract_fact(S, X) end, R, + Facts). -check_cond (R, [], {Fact, Sign}) -> R; -check_cond (R, [{C1, Tab, Alfa_fun} | T], {Fact, Sign} ) -> +check_cond(R, [], {Fact, Sign}) -> R; +check_cond(R, [{C1, Tab, Alfa_fun} | T], + {Fact, Sign}) -> case catch Alfa_fun(Fact) of true -> case Sign of - plus -> - ets:insert (Tab, Fact); - minus -> - ets:delete_object(Tab, Fact) + plus -> ets:insert(Tab, Fact); + minus -> ets:delete_object(Tab, Fact) end, - R1 = pass_fact (R, Tab, {Fact, Sign}), - check_cond (R1, T, {Fact, Sign}); - {'EXIT',{function_clause,_}} -> + R1 = pass_fact(R, Tab, {Fact, Sign}), + check_cond(R1, T, {Fact, Sign}); + {'EXIT', {function_clause, _}} -> check_cond(R, T, {Fact, Sign}); - Other -> - check_cond(R, T, {Fact, Sign}) + Other -> check_cond(R, T, {Fact, Sign}) end. %% propaga il 'fatto' a tutti i nodi che seguono l'alfa-memory %% con indice Tab -pass_fact (R, Tab, {Fact, Sign}) -> +pass_fact(R, Tab, {Fact, Sign}) -> [Kb, Alfa, Join, Agenda, State] = R, - Succ_node_list = eresye_tree_list:lookup_all (Tab, Join), - {Join1, Agenda1} = propagate (Succ_node_list, {Fact, Sign}, Join, Agenda), + Succ_node_list = eresye_tree_list:lookup_all(Tab, Join), + {Join1, Agenda1} = propagate(Succ_node_list, + {Fact, Sign}, Join, Agenda), [Kb, Alfa, Join1, Agenda1, State]. -propagate ([], {Fact, Sign}, Join, Agenda) -> +propagate([], {Fact, Sign}, Join, Agenda) -> {Join, Agenda}; -propagate ([Join_node | T], {Fact, Sign}, Join, Agenda) -> +propagate([Join_node | T], {Fact, Sign}, Join, + Agenda) -> Join_node1 = eresye_tree_list:refresh(Join_node, Join), Tok_list = right_act({Fact, Sign}, Join_node1), case eresye_tree_list:get_key(Join_node1) of {{n_node, _}, _} -> - {Join1, Agenda1} = propagate_nnode (Join_node1, Tok_list, - Sign, Join, Agenda); + {Join1, Agenda1} = propagate_nnode(Join_node1, Tok_list, + Sign, Join, Agenda); {Tab, Fun} -> - Children_list = eresye_tree_list:children(Join_node1, Join), - {Join1, Agenda1} = pass_tok(Tok_list, Children_list, Join, Agenda) + Children_list = eresye_tree_list:children(Join_node1, + Join), + {Join1, Agenda1} = pass_tok(Tok_list, Children_list, + Join, Agenda) end, propagate(T, {Fact, Sign}, Join1, Agenda1). -propagate_nnode (Join_node, [], _, Join, Agenda) -> +propagate_nnode(Join_node, [], _, Join, Agenda) -> {Join, Agenda}; -propagate_nnode (Join_node, Tok_list, Sign, Join, Agenda)-> +propagate_nnode(Join_node, Tok_list, Sign, Join, + Agenda) -> % io:format("Tok_list=~w~n",[Tok_list]), - Children_list = eresye_tree_list:children(Join_node, Join), - Toks = lists:map(fun(Tk)-> - L = element(1, Tk), - T1 = lists:sublist(L, length(L)-1 ), - case Sign of - plus -> - {T1, minus }; - minus -> - {T1, plus} - end - end, Tok_list), + Children_list = eresye_tree_list:children(Join_node, + Join), + Toks = [propagate_nnode_1(V1, Sign) || V1 <- Tok_list], % io:format("Toks=~w~n",[Toks]), case Sign of - plus -> - pass_tok(Toks, Children_list, Join, Agenda); + plus -> pass_tok(Toks, Children_list, Join, Agenda); minus -> - {{n_node, IdNp_node}, Join_fun} = eresye_tree_list:get_key(Join_node), - test_nnode (Toks, IdNp_node, Join_fun, Join_node, Join, Agenda) + {{n_node, IdNp_node}, Join_fun} = + eresye_tree_list:get_key(Join_node), + test_nnode(Toks, IdNp_node, Join_fun, Join_node, Join, + Agenda) end. +propagate_nnode_1(Tk, Sign) -> + L = element(1, Tk), + T1 = lists:sublist(L, length(L) - 1), + case Sign of + plus -> {T1, minus}; + minus -> {T1, plus} + end. %% propaga ogni token ai nodi presenti in Children_list -pass_tok ([], Children_list, Join, Agenda) -> +pass_tok([], Children_list, Join, Agenda) -> {Join, Agenda}; -pass_tok ([Tok | T], Children_list, Join, Agenda) -> - {Join1, Agenda1} = left_act (Tok, Children_list, Join, Agenda), - Children_list1 = refresh (Children_list, Join1), - pass_tok (T, Children_list1, Join1, Agenda1). - - +pass_tok([Tok | T], Children_list, Join, Agenda) -> + {Join1, Agenda1} = left_act(Tok, Children_list, Join, + Agenda), + Children_list1 = refresh(Children_list, Join1), + pass_tok(T, Children_list1, Join1, Agenda1). %% inserisce il token Tok nella Beta_memory del Join_node, %% confronta il token Tok con tutti i fatti presenti nell'alfa memory %% associata al Join_node e se si ha un esito positivo propaga il %% token ai nodi figli -left_act ({Token, Sign}, [], Join, Agenda) -> +left_act({Token, Sign}, [], Join, Agenda) -> {Join, Agenda}; - -left_act ({Token, Sign}, [Join_node | T], Join, Agenda) -> - Beta = eresye_tree_list:get_beta (Join_node), +left_act({Token, Sign}, [Join_node | T], Join, + Agenda) -> + Beta = eresye_tree_list:get_beta(Join_node), case Sign of - plus -> - Beta1 = Beta ++ [Token]; - minus -> - Beta1 = Beta -- [Token] + plus -> Beta1 = Beta ++ [Token]; + minus -> Beta1 = Beta -- [Token] end, - Join1 = eresye_tree_list:update_beta (Beta1, Join_node, Join), + Join1 = eresye_tree_list:update_beta(Beta1, Join_node, + Join), case eresye_tree_list:get_key(Join_node) of {p_node, Rule} -> %%io:format ("LEFT ACT ~p~n", [Rule]), @@ -1293,135 +1229,126 @@ left_act ({Token, Sign}, [Join_node | T], Join, Agenda) -> left_act_nnode({Token, Sign}, IdNp_node, Join_fun, [Join_node | T], Join1, Agenda); {np_node, nil} -> - Children_list = eresye_tree_list:children(Join_node, Join1), - {Join2, Agenda1} = propagate (Children_list, - {Token, Sign}, Join1, Agenda), + Children_list = eresye_tree_list:children(Join_node, + Join1), + {Join2, Agenda1} = propagate(Children_list, + {Token, Sign}, Join1, Agenda), left_act({Token, Sign}, T, Join2, Agenda1); {Tab, Join_fun} -> Alfa_mem = ets:tab2list(Tab), - Tok_list = join_left ({Token, Sign}, Alfa_mem, Join_fun), - Children_list = eresye_tree_list:children(Join_node, Join1), - {Join2, Agenda1} = pass_tok (Tok_list, Children_list, Join1, Agenda), - left_act ({Token,Sign}, T, Join2, Agenda1) + Tok_list = join_left({Token, Sign}, Alfa_mem, Join_fun), + Children_list = eresye_tree_list:children(Join_node, + Join1), + {Join2, Agenda1} = pass_tok(Tok_list, Children_list, + Join1, Agenda), + left_act({Token, Sign}, T, Join2, Agenda1) end. - -join_left ({Tok, Sign}, Mem, Join_fun) -> - lists:foldl(fun(WmeOrTok, Tok_list) -> +join_left({Tok, Sign}, Mem, Join_fun) -> + lists:foldl(fun (WmeOrTok, Tok_list) -> Tok1 = match(WmeOrTok, Tok, Join_fun), case Tok1 of [] -> Tok_list; - Other -> - lists:append(Tok_list, [{Tok1, Sign}]) + Other -> Tok_list ++ [{Tok1, Sign}] end - end, [], Mem). + end, + [], Mem). - -left_act_nnode ({Token, Sign}, IdNp_node, Join_fun, [Join_node | T], Join, Agenda )-> +left_act_nnode({Token, Sign}, IdNp_node, Join_fun, + [Join_node | T], Join, Agenda) -> Np_node = eresye_tree_list:get_node(IdNp_node, Join), BetaN = eresye_tree_list:get_beta(Np_node), - Tok_list = join_left ({Token, Sign}, BetaN, Join_fun), + Tok_list = join_left({Token, Sign}, BetaN, Join_fun), case Tok_list of [] -> - Children_list = eresye_tree_list:children(Join_node, Join), - {Join1, Agenda1} = pass_tok ([{Token, Sign}], Children_list, - Join, Agenda), - left_act ({Token, Sign}, T, Join1, Agenda1); - Tok_list -> - left_act ({Token, Sign}, T, Join, Agenda) + Children_list = eresye_tree_list:children(Join_node, + Join), + {Join1, Agenda1} = pass_tok([{Token, Sign}], + Children_list, Join, Agenda), + left_act({Token, Sign}, T, Join1, Agenda1); + Tok_list -> left_act({Token, Sign}, T, Join, Agenda) end. -test_nnode ([], _, _, _, Join, Agenda)-> - {Join, Agenda}; -test_nnode ( [Tok| OtherTok], IdNpNode, Join_fun, Join_node, Join, Agenda) -> - {Join1, Agenda1} = left_act_nnode (Tok, IdNpNode, Join_fun, [Join_node], Join, Agenda), - test_nnode(OtherTok, IdNpNode, Join_fun, Join_node, Join1, Agenda1). - +test_nnode([], _, _, _, Join, Agenda) -> {Join, Agenda}; +test_nnode([Tok | OtherTok], IdNpNode, Join_fun, + Join_node, Join, Agenda) -> + {Join1, Agenda1} = left_act_nnode(Tok, IdNpNode, + Join_fun, [Join_node], Join, Agenda), + test_nnode(OtherTok, IdNpNode, Join_fun, Join_node, + Join1, Agenda1). %% confronta il nuovo Wme con tutti i token presenti nella Beta-memory %% genitore e ritorna una lista di nuovi token ([Tok1+Wme, Tok2+Wme,...]) %% o una lista vuota se il Wme non 'matcha' con i token della Beta-memory -right_act ({Fact, Sign}, Join_node) -> +right_act({Fact, Sign}, Join_node) -> Beta = element(2, Join_node), Join_fun = element(2, element(1, Join_node)), - Tok_list = join_right ({Fact, Sign}, Beta, Join_fun). + Tok_list = join_right({Fact, Sign}, Beta, Join_fun). - -join_right ({Fact, Sign}, Beta, nil) -> +join_right({Fact, Sign}, Beta, nil) -> append(Beta, {Fact, Sign}); -join_right ({Fact, Sign}, [], Join_fun) -> - []; -join_right ({Fact, Sign}, Beta, Join_fun) -> - join_right ({Fact, Sign}, Beta, Join_fun, []). - +join_right({Fact, Sign}, [], Join_fun) -> []; +join_right({Fact, Sign}, Beta, Join_fun) -> + join_right({Fact, Sign}, Beta, Join_fun, []). -join_right ({Fact, Sign}, [], Join_fun, PassedTok) -> +join_right({Fact, Sign}, [], Join_fun, PassedTok) -> PassedTok; -join_right ({Fact, Sign}, [Tok| T], Join_fun, PassedTok) -> - Pass = match (Fact, Tok, Join_fun), +join_right({Fact, Sign}, [Tok | T], Join_fun, + PassedTok) -> + Pass = match(Fact, Tok, Join_fun), case Pass of - [] -> - join_right ({Fact, Sign}, T, Join_fun, PassedTok); + [] -> join_right({Fact, Sign}, T, Join_fun, PassedTok); New_tok -> - L = lists:append(PassedTok, [{Pass, Sign}]), - join_right ({Fact, Sign}, T, Join_fun, L) + L = PassedTok ++ [{Pass, Sign}], + join_right({Fact, Sign}, T, Join_fun, L) end. - -refresh ([], Join, L) -> - lists:reverse (L); -refresh ([Node | OtherNode], Join, L) -> - Node1 = eresye_tree_list:refresh (Node, Join), +refresh([], Join, L) -> lists:reverse(L); +refresh([Node | OtherNode], Join, L) -> + Node1 = eresye_tree_list:refresh(Node, Join), L1 = [Node1 | L], - refresh (OtherNode, Join, L1). -refresh (N, Join) -> - refresh (N, Join, []). + refresh(OtherNode, Join, L1). +refresh(N, Join) -> refresh(N, Join, []). %% fa il match tra Wme e il token Tok e restituisce una lista vuota in caso %% negativo o un nuovo token (Tok+Wme) in caso positivo -match (Wme, Tok, Join_fun) -> +match(Wme, Tok, Join_fun) -> case catch Join_fun(Wme, Tok) of - true -> - lists:append(Tok, [Wme]); - {'EXIT',{function_clause,_}} -> - []; - Other -> - [] + true -> Tok ++ [Wme]; + {'EXIT', {function_clause, _}} -> []; + Other -> [] end. - -append ([], {Fact, Sign}) -> - [{[Fact], Sign}]; -append (Beta, {Fact, Sign}) -> - lists:foldl(fun(Tok, New_Beta)-> - Tok1 = lists:append(Tok, [Fact]), - lists:append(New_Beta, {Tok1, Sign}) - end, [], Beta). - - +append([], {Fact, Sign}) -> [{[Fact], Sign}]; +append(Beta, {Fact, Sign}) -> + lists:foldl(fun (Tok, New_Beta) -> + Tok1 = Tok ++ [Fact], New_Beta ++ {Tok1, Sign} + end, + [], Beta). %% condivide o crea un join-node -make_join_node (J, {new, Tab}, Cond, P, Parent_node, Agenda) -> +make_join_node(J, {new, Tab}, Cond, P, Parent_node, + Agenda) -> Join_fun = evaluate(prepare_fun(Cond, P)), - new_join (J, Tab, Join_fun, Parent_node, Agenda); -make_join_node (J, {old, Tab}, Cond, P, Parent_node, Agenda) -> + new_join(J, Tab, Join_fun, Parent_node, Agenda); +make_join_node(J, {old, Tab}, Cond, P, Parent_node, + Agenda) -> Result = eresye_tree_list:child(Tab, Parent_node, J), case Result of false -> Join_fun = evaluate(prepare_fun(Cond, P)), new_join(J, Tab, Join_fun, Parent_node, Agenda); - Node -> - {Node, J, Agenda} + Node -> {Node, J, Agenda} end. - - -new_join (J, Tab, Join_fun, Parent_node, Agenda) -> +new_join(J, Tab, Join_fun, Parent_node, Agenda) -> Key = {Tab, Join_fun}, Value = [], %Beta_parent - {Node, J1} = eresye_tree_list:insert(Key, Value, Parent_node, J), - {J2, Agenda1} = update_new_node(Node, Parent_node, J1, Agenda), + {Node, J1} = eresye_tree_list:insert(Key, Value, + Parent_node, J), + {J2, Agenda1} = update_new_node(Node, Parent_node, J1, + Agenda), Node1 = eresye_tree_list:refresh(Node, J2), {Node1, J2, Agenda1}. diff --git a/src/eresye_agenda.erl b/src/eresye_agenda.erl index 8705d60..4775185 100644 --- a/src/eresye_agenda.erl +++ b/src/eresye_agenda.erl @@ -1,62 +1,46 @@ -% -% eres_agenda.erl -% -% ---------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (eresye_agenda). --export ([addActivation/3, - addActivation/4, - start/1, - start_link/1, - deleteRule/2, - popRule/1, - deleteActivation/2, - clearAgenda/1, - getStrategy/1, - setStrategy/2, - getActivation/2, - getActivationFromName/2, - getFirstActivation/1, - getActivationSalience/2, - getNumberOfActivations/1, - getRulesFired/1, - setActivationSalience/3, - setRuleSalience/3, - schedule/1, - breadthOrder/2, - depthOrder/2, - fifoOrder/2, - executor/1]). +%% +%%eres_agenda.erl +%% +%%---------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(eresye_agenda). + +-export([addActivation/3, addActivation/4, + breadthOrder/2, clearAgenda/1, deleteActivation/2, + deleteRule/2, depthOrder/2, executor/1, fifoOrder/2, + getActivation/2, getActivationFromName/2, + getActivationSalience/2, getFirstActivation/1, + getNumberOfActivations/1, getRulesFired/1, + getStrategy/1, popRule/1, schedule/1, + setActivationSalience/3, setRuleSalience/3, + setStrategy/2, start/1, start_link/1]). %%==================================================================== %% Internal exports %%==================================================================== --export ([init/1, - handle_call/3, - handle_cast/2, - terminate/2, - code_change/3]). +-export([code_change/3, handle_call/3, handle_cast/2, + init/1, terminate/2]). --behaviour (gen_server). +-behaviour(gen_server). %%==================================================================== %% External functions @@ -65,92 +49,88 @@ %% Func: start/1 %% Arguments: creates a new agenda %%==================================================================== -start (EngineName) -> - {ok, Pid} = gen_server:start (?MODULE, EngineName, []), - Pid. - -start_link (EngineName) -> - {ok, Pid} = gen_server:start_link (?MODULE, EngineName, []), - Pid. - -addActivation (Agenda, Rule, Args) -> - addActivation(Agenda, Rule, Args, 0). - -addActivation (Agenda, Rule, Args, Salience) -> - %%io:format("addActivation>Agenda=~w~nRule=~w~nArgs=~w~n", - %% [Agenda,Rule,Args]), - gen_server:call (Agenda, {add_activation, Rule, Args, Salience}), - Agenda. - -% Remove all activation from Agenda, -% returns an empty agenda with same past strategy -clearAgenda (Agenda) -> - gen_server:call (Agenda, {clear}), - Agenda. - -getStrategy (Agenda) -> - gen_server:call (Agenda, {get_strategy}). - -setStrategy (Agenda, NewStrategy) -> - gen_server:call (Agenda, {set_strategy, NewStrategy}), - Agenda. - -getRulesFired (Agenda) -> - gen_server:call (Agenda, {get_rules_fired}). - - -% Remove activation with id='Id' or -% all activation whose id is in the list passed as argument -deleteActivation (Agenda, Ids) -> - %%io:format("deleteActivation>Agenda=~w~nRule=~w~n", - %% [Agenda, Ids]), - gen_server:call (Agenda, {delete_activation, Ids}), - Agenda. - - -% Remove all activation associated with rule 'Rule' from the agenda, -% returns the modified agenda -deleteRule (Agenda, Rule) -> - gen_server:call (Agenda, {delete_rule, Rule}), - Agenda. - - -% Returns the Id of activation associated to rule 'Rule' and -% arguments 'Args', false if it not present -getActivation (Agenda, {Rule, Args}) -> - gen_server:call (Agenda, {get_activation, {Rule, Args}}). - -% Returns the Id of first activation associated to rule 'Rule', -% false if 'Rule' is not present in the agenda -getActivationFromName (Agenda, Rule) -> - gen_server:call (Agenda, {get_activation, Rule}). - -% Return the Id associated to first activation in the agenda -% false if agenda is empty -getFirstActivation (Agenda) -> - gen_server:call (Agenda, {get_first_activation}). - -% Return the salience value of activation with id='Id' -% false if Id is not present in the agenda -getActivationSalience (Agenda, Id) -> - gen_server:call (Agenda, {get_activation_salience, Id}). - -% Sets the salience value of activation with id='Id', -% returns the modified agenda -setActivationSalience (Agenda, Id, NewSalience) -> - gen_server:call (Agenda, {set_activation_salience, Id, NewSalience}), - Agenda. - -% Sets the salience value of all activations associated to rule 'Rule', -% returns the modified agenda -setRuleSalience (Agenda, Rule, NewSalience) -> - gen_server:call (Agenda, {set_rule_salience, Rule, NewSalience}), - Agenda. - - -schedule (Agenda) -> - gen_server:cast (Agenda, {schedule}). - +start(EngineName) -> + {ok, Pid} = gen_server:start(?MODULE, EngineName, []), + Pid. + +start_link(EngineName) -> + {ok, Pid} = gen_server:start_link(?MODULE, EngineName, + []), + Pid. + +addActivation(Agenda, Rule, Args) -> + addActivation(Agenda, Rule, Args, 0). + +addActivation(Agenda, Rule, Args, Salience) -> + %%io:format("addActivation>Agenda=~w~nRule=~w~nArgs=~w~n", + %% [Agenda,Rule,Args]), + gen_server:call(Agenda, + {add_activation, Rule, Args, Salience}), + Agenda. + +%%Remove all activation from Agenda, +%%returns an empty agenda with same past strategy +clearAgenda(Agenda) -> + gen_server:call(Agenda, {clear}), Agenda. + +getStrategy(Agenda) -> + gen_server:call(Agenda, {get_strategy}). + +setStrategy(Agenda, NewStrategy) -> + gen_server:call(Agenda, {set_strategy, NewStrategy}), + Agenda. + +getRulesFired(Agenda) -> + gen_server:call(Agenda, {get_rules_fired}). + +%%Remove activation with id='Id' or +%%all activation whose id is in the list passed as argument +deleteActivation(Agenda, Ids) -> + %%io:format("deleteActivation>Agenda=~w~nRule=~w~n", + %% [Agenda, Ids]), + gen_server:call(Agenda, {delete_activation, Ids}), + Agenda. + +%%Remove all activation associated with rule 'Rule' from the agenda, +%%returns the modified agenda +deleteRule(Agenda, Rule) -> + gen_server:call(Agenda, {delete_rule, Rule}), Agenda. + +%%Returns the Id of activation associated to rule 'Rule' and +%%arguments 'Args', false if it not present +getActivation(Agenda, {Rule, Args}) -> + gen_server:call(Agenda, {get_activation, {Rule, Args}}). + +%%Returns the Id of first activation associated to rule 'Rule', +%%false if 'Rule' is not present in the agenda +getActivationFromName(Agenda, Rule) -> + gen_server:call(Agenda, {get_activation, Rule}). + +%%Return the Id associated to first activation in the agenda +%%false if agenda is empty +getFirstActivation(Agenda) -> + gen_server:call(Agenda, {get_first_activation}). + +%%Return the salience value of activation with id='Id' +%%false if Id is not present in the agenda +getActivationSalience(Agenda, Id) -> + gen_server:call(Agenda, {get_activation_salience, Id}). + +%%Sets the salience value of activation with id='Id', +%%returns the modified agenda +setActivationSalience(Agenda, Id, NewSalience) -> + gen_server:call(Agenda, + {set_activation_salience, Id, NewSalience}), + Agenda. + +%%Sets the salience value of all activations associated to rule 'Rule', +%%returns the modified agenda +setRuleSalience(Agenda, Rule, NewSalience) -> + gen_server:call(Agenda, + {set_rule_salience, Rule, NewSalience}), + Agenda. + +schedule(Agenda) -> gen_server:cast(Agenda, {schedule}). %%==================================================================== %% Callback functions @@ -158,343 +138,327 @@ schedule (Agenda) -> %%==================================================================== %% Func: init/1 %%==================================================================== -init (EngineName) -> - Pid = spawn (?MODULE, executor, [EngineName]), - put (rules_fired, 0), - {ok, {depth,[], Pid, nil, 0}}. - +init(EngineName) -> + Pid = spawn(?MODULE, executor, [EngineName]), + put(rules_fired, 0), + {ok, {depth, [], Pid, nil, 0}}. %%==================================================================== %% Func: code_change/3 %%==================================================================== code_change(OldVsn, State, Extra) -> {ok, State}. - %%==================================================================== %% Func: terminate/2 %%==================================================================== terminate(Reason, State) -> - {_, _, ExecutorPid, _, _} = State, - ExecutorPid ! {stop}, - %%io:format ("Terminating...~p~n", [self ()]), - ok. - + {_, _, ExecutorPid, _, _} = State, + ExecutorPid ! {stop}, + %%io:format ("Terminating...~p~n", [self ()]), + ok. %%==================================================================== %% Func: handle_call/3 %%==================================================================== -handle_call ({stop}, _, State) -> - {stop, normal, ok, State}; - -handle_call ({get_rules_fired}, _, State) -> - {reply, {ok, get(rules_fired)}, State}; - -handle_call ({add_activation, Rule, Args, Salience}, From, State) -> - {Strategy, RuleList, ExecutorPid, ExecState, Id} = State, - %%io:format("addActivation>Rule=~w~nArgs=~w~n",[Rule,Args]), - NewRuleList = - case Strategy of - depth -> depthAdd(RuleList, Rule, Args, Salience, Id); - breadth -> breadthAdd(RuleList, Rule, Args, Salience, Id); - fifo -> fifoAdd(RuleList, Rule, Args, Salience, Id) - end, - NewAgenda = {Strategy, NewRuleList, ExecutorPid, ExecState, Id + 1}, - {reply, ok, after_activation_schedule__ (NewAgenda)}; - -% Remove all activation from Agenda, -% returns an empty agenda with same past strategy -handle_call ({clear}, From, Agenda) -> - {_, _, ExecutorPid, ExecState, _} = Agenda, - NewAgenda = {element(1, Agenda), [], ExecutorPid, ExecState, 0}, - {reply, ok, NewAgenda}; - -handle_call ({get_strategy}, From, Agenda) -> - {reply, element(1, Agenda), Agenda}; - -handle_call ({set_strategy, NewStrategy}, From, Agenda) -> - {OldStrategy, RuleList, ExecutorPid, ExecState, NextId} = Agenda, - NewAgenda = - case NewStrategy of - depth -> - RuleList1 = lists:sort({agenda,depthOrder}, RuleList), - {depth, RuleList1, ExecutorPid, ExecState, NextId}; - breadth -> - RuleList1 = lists:sort({agenda,breadthOrder}, RuleList), - {breadth, RuleList1, ExecutorPid, ExecState, NextId}; - fifo -> - RuleList1 = lists:sort({agenda,fifoOrder}, RuleList), - {fifo, RuleList1, ExecutorPid, ExecState, NextId}; - _ -> - %% Strategy not changed - Agenda - end, - {reply, ok, NewAgenda}; - - -handle_call ({delete_activation, Id}, From, Agenda) -> - NewAgenda = deleteActivation__ (Agenda, Id), - {reply, ok, NewAgenda}; - -handle_call ({delete_rule, Rule}, From, Agenda) -> - {Strategy, RuleList, ExecutorPid, ExecState, NextId} = Agenda, - ActList = proplists:lookup_all(Rule, RuleList), - RuleList1 = lists:foldl (fun (X, R1)-> - lists:delete(X, R1) - end, RuleList, ActList), - NewAgenda = {Strategy, RuleList1, ExecutorPid, ExecState, NextId}, - {reply, ok, NewAgenda}; - -% Returns the Id of activation associated to rule 'Rule' and -% arguments 'Args', false if it not present -handle_call ({get_activation, {Rule, Args}}, From, Agenda) -> - %Rule = {Module, Fun}, or - %Rulle = fun(...) - {_, RuleList, _, _, _} = Agenda, - ActList = proplists:lookup_all(Rule, RuleList), - %%io:format ("get =~p, ~p. Res = ~p~n", [Rule, RuleList, ActList]), - Reply = - case lists:keysearch(Args, 2, ActList) of - {value, {_, _, _, Id}}-> - Id; - false -> - false - end, - {reply, Reply, Agenda}; - -% Returns the Id of first activation associated to rule 'Rule', -% false if 'Rule' is not present in the agenda -handle_call ({get_activation_from_name, Rule}, From, Agenda) -> - {_, RuleList, _, _, _} = Agenda, - Reply = - case lists:keysearch(Rule, 1, RuleList) of - {value, {_, _, _, Id}}-> - Id; - false -> - false - end, - %%io:format ("Rule = ~p~nRuleList = ~p~nRes = ~p~n", [Rule, RuleList, Reply]), - {reply, Reply, Agenda}; - - -% Return the Id associated to first activation in the agenda -% false if agenda is empty -handle_call ({get_first_activation}, From, - {_, [], _, _, _} = Agenda) -> - {reply, false, Agenda}; -handle_call ({get_first_activation}, From, - {_, [First | _], _, _, _} = Agenda) -> - {reply, element (4, First), Agenda}; - -% Return the salience value of activation with id='Id' -% false if Id is not present in the agenda -handle_call ({get_activation_salience, Id}, From, Agenda) -> - {_, RuleList, _, _, NextId} = Agenda, - Reply = - case NextId < Id of - true -> - false; - false -> - case lists:keysearch(Id, 4, RuleList) of - {value, {_, _, Salience, _}} -> - Salience; - false -> - false - end - end, - {reply, Reply, Agenda}; - -% Sets the salience value of activation with id='Id', -% returns the modified agenda -handle_call ({set_activation_salience, Id, NewSalience}, From, Agenda) -> - NewAgenda = setActivationSalience__ (Agenda, Id, NewSalience), - {reply, ok, NewAgenda}; - -% Sets the salience value of all activations associated to rule 'Rule', -% returns the modified agenda -handle_call ({set_rule_salience, Rule, NewSalience}, From, Agenda) -> - {_, RuleList, _, _, _} = Agenda, - ActList = proplists:lookup_all(Rule, RuleList), - IdList = lists:map( - fun({_,_,_,Id})-> - Id - end, ActList), - NewAgenda = setActivationSalience__ (Agenda, IdList, NewSalience), - {reply, ok, NewAgenda}. - - +handle_call({stop}, _, State) -> + {stop, normal, ok, State}; +handle_call({get_rules_fired}, _, State) -> + {reply, {ok, get(rules_fired)}, State}; +handle_call({add_activation, Rule, Args, Salience}, + From, State) -> + {Strategy, RuleList, ExecutorPid, ExecState, Id} = + State, + %%io:format("addActivation>Rule=~w~nArgs=~w~n",[Rule,Args]), + NewRuleList = case Strategy of + depth -> depthAdd(RuleList, Rule, Args, Salience, Id); + breadth -> + breadthAdd(RuleList, Rule, Args, Salience, Id); + fifo -> fifoAdd(RuleList, Rule, Args, Salience, Id) + end, + NewAgenda = {Strategy, NewRuleList, ExecutorPid, + ExecState, Id + 1}, + {reply, ok, after_activation_schedule__(NewAgenda)}; +%%Remove all activation from Agenda, +%%returns an empty agenda with same past strategy +handle_call({clear}, From, Agenda) -> + {_, _, ExecutorPid, ExecState, _} = Agenda, + NewAgenda = {element(1, Agenda), [], ExecutorPid, + ExecState, 0}, + {reply, ok, NewAgenda}; +handle_call({get_strategy}, From, Agenda) -> + {reply, element(1, Agenda), Agenda}; +handle_call({set_strategy, NewStrategy}, From, + Agenda) -> + {OldStrategy, RuleList, ExecutorPid, ExecState, + NextId} = + Agenda, + NewAgenda = case NewStrategy of + depth -> + RuleList1 = lists:sort({agenda, depthOrder}, RuleList), + {depth, RuleList1, ExecutorPid, ExecState, NextId}; + breadth -> + RuleList1 = lists:sort({agenda, breadthOrder}, + RuleList), + {breadth, RuleList1, ExecutorPid, ExecState, NextId}; + fifo -> + RuleList1 = lists:sort({agenda, fifoOrder}, RuleList), + {fifo, RuleList1, ExecutorPid, ExecState, NextId}; + _ -> + %% Strategy not changed + Agenda + end, + {reply, ok, NewAgenda}; +handle_call({delete_activation, Id}, From, Agenda) -> + NewAgenda = deleteActivation__(Agenda, Id), + {reply, ok, NewAgenda}; +handle_call({delete_rule, Rule}, From, Agenda) -> + {Strategy, RuleList, ExecutorPid, ExecState, NextId} = + Agenda, + ActList = proplists:lookup_all(Rule, RuleList), + RuleList1 = lists:foldl(fun (X, R1) -> + lists:delete(X, R1) + end, + RuleList, ActList), + NewAgenda = {Strategy, RuleList1, ExecutorPid, + ExecState, NextId}, + {reply, ok, NewAgenda}; +%%Returns the Id of activation associated to rule 'Rule' and +%%arguments 'Args', false if it not present +handle_call({get_activation, {Rule, Args}}, From, + Agenda) -> + %%Rule = {Module, Fun}, or + %%Rulle = fun(...) + {_, RuleList, _, _, _} = Agenda, + ActList = proplists:lookup_all(Rule, RuleList), + %%io:format ("get =~p, ~p. Res = ~p~n", [Rule, RuleList, ActList]), + Reply = case lists:keysearch(Args, 2, ActList) of + {value, {_, _, _, Id}} -> Id; + false -> false + end, + {reply, Reply, Agenda}; +%%Returns the Id of first activation associated to rule 'Rule', +%%false if 'Rule' is not present in the agenda +handle_call({get_activation_from_name, Rule}, From, + Agenda) -> + {_, RuleList, _, _, _} = Agenda, + Reply = case lists:keysearch(Rule, 1, RuleList) of + {value, {_, _, _, Id}} -> Id; + false -> false + end, + %%io:format ("Rule = ~p~nRuleList = ~p~nRes = ~p~n", [Rule, RuleList, Reply]), + {reply, Reply, Agenda}; +%%Return the Id associated to first activation in the agenda +%%false if agenda is empty +handle_call({get_first_activation}, From, + {_, [], _, _, _} = Agenda) -> + {reply, false, Agenda}; +handle_call({get_first_activation}, From, + {_, [First | _], _, _, _} = Agenda) -> + {reply, element(4, First), Agenda}; +%%Return the salience value of activation with id='Id' +%%false if Id is not present in the agenda +handle_call({get_activation_salience, Id}, From, + Agenda) -> + {_, RuleList, _, _, NextId} = Agenda, + Reply = case NextId < Id of + true -> false; + false -> + case lists:keysearch(Id, 4, RuleList) of + {value, {_, _, Salience, _}} -> Salience; + false -> false + end + end, + {reply, Reply, Agenda}; +%%Sets the salience value of activation with id='Id', +%%returns the modified agenda +handle_call({set_activation_salience, Id, NewSalience}, + From, Agenda) -> + NewAgenda = setActivationSalience__(Agenda, Id, + NewSalience), + {reply, ok, NewAgenda}; +%%Sets the salience value of all activations associated to rule 'Rule', +%%returns the modified agenda +handle_call({set_rule_salience, Rule, NewSalience}, + From, Agenda) -> + {_, RuleList, _, _, _} = Agenda, + ActList = proplists:lookup_all(Rule, RuleList), + IdList = [handle_call_1(V1) || V1 <- ActList], + NewAgenda = setActivationSalience__(Agenda, IdList, + NewSalience), + {reply, ok, NewAgenda}. + +handle_call_1({_, _, _, Id}) -> Id. %%==================================================================== %% Func: handle_cast/3 %%==================================================================== -handle_cast ({schedule}, Agenda) -> - {noreply, after_execution_schedule__ (Agenda)}. - - -after_activation_schedule__ (Agenda) -> - {Strategy, RuleList, ExecutorPid, ExecState, NextId} = Agenda, - {NewExecState, NewRuleList} = - if - ExecState == active -> {ExecState, RuleList}; - true -> - {RuleToExecute, RL} = popRule (RuleList), - if - RuleToExecute == false -> {nil, RL}; - true -> - ExecutorPid ! {exec, self (), RuleToExecute}, - put (rules_fired, get (rules_fired) + 1), - {active, RL} - end - end, - {Strategy, NewRuleList, ExecutorPid, NewExecState, NextId}. - - -after_execution_schedule__ (Agenda) -> - {Strategy, RuleList, ExecutorPid, ExecState, NextId} = Agenda, - {RuleToExecute, RL} = popRule (RuleList), - {NewExecState, NewRuleList} = - if - RuleToExecute == false -> {nil, RL}; - true -> - ExecutorPid ! {exec, self (), RuleToExecute}, - put (rules_fired, get (rules_fired) + 1), - {active, RL} +handle_cast({schedule}, Agenda) -> + {noreply, after_execution_schedule__(Agenda)}. + +after_activation_schedule__(Agenda) -> + {Strategy, RuleList, ExecutorPid, ExecState, NextId} = + Agenda, + {NewExecState, NewRuleList} = if ExecState == active -> + {ExecState, RuleList}; + true -> + {RuleToExecute, RL} = + popRule(RuleList), + if RuleToExecute == false -> {nil, RL}; + true -> + ExecutorPid ! + {exec, self(), RuleToExecute}, + put(rules_fired, + get(rules_fired) + 1), + {active, RL} + end + end, + {Strategy, NewRuleList, ExecutorPid, NewExecState, + NextId}. + +after_execution_schedule__(Agenda) -> + {Strategy, RuleList, ExecutorPid, ExecState, NextId} = + Agenda, + {RuleToExecute, RL} = popRule(RuleList), + {NewExecState, NewRuleList} = if RuleToExecute == + false -> + {nil, RL}; + true -> + ExecutorPid ! + {exec, self(), RuleToExecute}, + put(rules_fired, get(rules_fired) + 1), + {active, RL} + end, + {Strategy, NewRuleList, ExecutorPid, NewExecState, + NextId}. + +%%Remove activation with id='Id' or +%%all activation whose id is in the list passed as argument +deleteActivation__(Agenda, []) -> Agenda; +deleteActivation__({Strategy, RuleList, ExecutorPid, + ExecState, NextId}, + Id) + when not is_list(Id) -> + {Strategy, lists:keydelete(Id, 4, RuleList), + ExecutorPid, ExecState, NextId}; +deleteActivation__(Agenda, [Id | OtherId]) -> + A1 = deleteActivation__(Agenda, Id), + deleteActivation__(A1, OtherId). + +setActivationSalience__(Agenda, [], NewSalience) -> + Agenda; +setActivationSalience__(Agenda, Id, NewSalience) + when is_number(NewSalience) and not is_list(Id) -> + {Strategy, RuleList, ExecutorPid, ExecState, NextId} = + Agenda, + case lists:keysearch(Id, 4, RuleList) of + {value, {Rule, Args, Salience, Id}} -> + RuleList1 = lists:keyreplace(Id, 4, RuleList, + {Rule, Args, NewSalience, Id}), + RuleList2 = order(RuleList1, Strategy); + false -> RuleList2 = RuleList end, - {Strategy, NewRuleList, ExecutorPid, NewExecState, NextId}. - - -% Remove activation with id='Id' or -% all activation whose id is in the list passed as argument -deleteActivation__ (Agenda, []) -> - Agenda; -deleteActivation__ ({Strategy, RuleList, ExecutorPid, ExecState, NextId}, - Id) when not is_list(Id) -> - {Strategy, lists:keydelete(Id, 4, RuleList), ExecutorPid, ExecState, NextId}; -deleteActivation__ (Agenda, [Id|OtherId]) -> - A1 = deleteActivation__ (Agenda, Id), - deleteActivation__ (A1, OtherId). - - - -setActivationSalience__ (Agenda, [], NewSalience) -> - Agenda; -setActivationSalience__ (Agenda, Id, NewSalience) - when is_number(NewSalience) and not is_list(Id)-> - {Strategy, RuleList, ExecutorPid, ExecState, NextId} = Agenda, - case lists:keysearch(Id, 4, RuleList) of - {value, {Rule, Args, Salience, Id}}-> - RuleList1 = lists:keyreplace(Id, 4, RuleList, - {Rule, Args, NewSalience, Id}), - RuleList2 = order(RuleList1, Strategy); - false -> - RuleList2 = RuleList - end, - {Strategy, RuleList2, ExecutorPid, ExecState, NextId}; -setActivationSalience__ (Agenda, Id, NewSalience) when not is_list(Id) -> - io:format("setActivatinSalience>Id must be a number~n"), - Agenda; -setActivationSalience__ (Agenda, [Id | OtherId], NewSalience) -> - A1 = setActivationSalience__ (Agenda, Id, NewSalience), - setActivationSalience__ (A1, OtherId, NewSalience). - - -% Remove the first activation, returns the rule, -% function arguments and the modified agenda -popRule ([]) -> {false, []}; -popRule ([Activation | NewRuleList] = RuleList) -> {Activation, NewRuleList}. - - - - -depthAdd (RuleList, Rule, Args, Salience, Id) -> - {L1, L2} = lists:splitwith(fun({_, _, S, _}) -> - S > Salience - end, RuleList), - lists:append(L1, [{Rule, Args, Salience, Id}| L2]). - - - -breadthAdd (RuleList, Rule, Args, Salience, Id) -> - {L1, L2} = lists:splitwith(fun({_, _, S, _}) -> - S >= Salience - end, RuleList), - lists:append(L1, [{Rule, Args, Salience, Id}| L2]). - -fifoAdd (RuleList, Rule, Args, Salience, Id) -> - lists:append(RuleList, [{Rule, Args, Salience, Id}]). - -getNumberOfActivations ({Strategy, RuleList, NextId}) -> - length(RuleList). - - -order (ActionList, Strategy) -> - case Strategy of - breadth -> - lists:sort({agenda, breadthOrder}, ActionList); - depth -> - lists:sort({agenda, depthOrder}, ActionList); - fifo -> - lists:sort({agenda, fifoOrder}, ActionList); - Other -> - ActionList - end. - -% define when an Act1 comes before Act2 in breadth strategy -breadthOrder (Act1, Act2) when element(3, Act1) > element(3, Act2) -> - true; -breadthOrder (Act1, Act2) when element(3, Act1) < element(3, Act2) -> - false; -breadthOrder (Act1, Act2) when element(4, Act1) > element(4, Act2) -> - false; -breadthOrder (Act1, Act2) -> - true. - -% define when an Act1 comes before Act2 in depth strategy -depthOrder (Act1, Act2) when element(3, Act1) > element(3, Act2) -> - true; -depthOrder (Act1, Act2) when element(3, Act1) < element(3, Act2) -> - false; -depthOrder (Act1, Act2) when element(4, Act1) < element(4, Act2) -> - false; -depthOrder (Act1, Act2) -> - true. - -% define when an Act1 comes before Act2 in fifo strategy -fifoOrder (Act1, Act2) when element(4, Act1) > element(4, Act2) -> - false; -fifoOrder (Act1, Act2) -> - true. - + {Strategy, RuleList2, ExecutorPid, ExecState, NextId}; +setActivationSalience__(Agenda, Id, NewSalience) + when not is_list(Id) -> + io:format("setActivatinSalience>Id must be a number~n"), + Agenda; +setActivationSalience__(Agenda, [Id | OtherId], + NewSalience) -> + A1 = setActivationSalience__(Agenda, Id, NewSalience), + setActivationSalience__(A1, OtherId, NewSalience). + +%%Remove the first activation, returns the rule, +%%function arguments and the modified agenda +popRule([]) -> {false, []}; +popRule([Activation | NewRuleList] = RuleList) -> + {Activation, NewRuleList}. + +depthAdd(RuleList, Rule, Args, Salience, Id) -> + {L1, L2} = lists:splitwith(fun ({_, _, S, _}) -> + S > Salience + end, + RuleList), + L1 ++ [{Rule, Args, Salience, Id} | L2]. + +breadthAdd(RuleList, Rule, Args, Salience, Id) -> + {L1, L2} = lists:splitwith(fun ({_, _, S, _}) -> + S >= Salience + end, + RuleList), + L1 ++ [{Rule, Args, Salience, Id} | L2]. + +fifoAdd(RuleList, Rule, Args, Salience, Id) -> + RuleList ++ [{Rule, Args, Salience, Id}]. + +getNumberOfActivations({Strategy, RuleList, NextId}) -> + length(RuleList). + +order(ActionList, Strategy) -> + case Strategy of + breadth -> + lists:sort({agenda, breadthOrder}, ActionList); + depth -> lists:sort({agenda, depthOrder}, ActionList); + fifo -> lists:sort({agenda, fifoOrder}, ActionList); + Other -> ActionList + end. + +%%define when an Act1 comes before Act2 in breadth strategy +breadthOrder(Act1, Act2) + when element(3, Act1) > element(3, Act2) -> + true; +breadthOrder(Act1, Act2) + when element(3, Act1) < element(3, Act2) -> + false; +breadthOrder(Act1, Act2) + when element(4, Act1) > element(4, Act2) -> + false; +breadthOrder(Act1, Act2) -> true. + +%%define when an Act1 comes before Act2 in depth strategy +depthOrder(Act1, Act2) + when element(3, Act1) > element(3, Act2) -> + true; +depthOrder(Act1, Act2) + when element(3, Act1) < element(3, Act2) -> + false; +depthOrder(Act1, Act2) + when element(4, Act1) < element(4, Act2) -> + false; +depthOrder(Act1, Act2) -> true. + +%%define when an Act1 comes before Act2 in fifo strategy +fifoOrder(Act1, Act2) + when element(4, Act1) > element(4, Act2) -> + false; +fifoOrder(Act1, Act2) -> true. %%==================================================================== %% Executor functions %%==================================================================== -executor (EngineName) -> - receive - {exec, From, R} -> - %%io:format ("Executing rule ~p~n", [R]), - {Mod, Fun} = - case R of - {{M, F}, _, _, _} -> {M, F}; - _ -> {'_', '_'} - end, - case catch (execute_rule (EngineName, R)) of - {'EXIT', {function_clause, [{Mod, Fun, _} | _]}} -> - ok; - {'EXIT', Reason} -> - io:format("** Warning! ERES engine ~p rule execution error\n" - "** Rule is ~p~n" - "** Reason for Error == ~n** ~p~n", - [EngineName, R, Reason]); - _ -> ok - end, - schedule (From), - executor (EngineName); - {stop} -> ok; - _ -> executor (EngineName) - end. - +executor(EngineName) -> + receive + {exec, From, R} -> + %%io:format ("Executing rule ~p~n", [R]), + {Mod, Fun} = case R of + {{M, F}, _, _, _} -> {M, F}; + _ -> {'_', '_'} + end, + case catch execute_rule(EngineName, R) of + {'EXIT', {function_clause, [{Mod, Fun, _} | _]}} -> ok; + {'EXIT', Reason} -> + io:format("** Warning! ERES engine ~p rule execution " + "error\n** Rule is ~p~n** Reason for " + "Error == ~n** ~p~n", + [EngineName, R, Reason]); + _ -> ok + end, + schedule(From), + executor(EngineName); + {stop} -> ok; + _ -> executor(EngineName) + end. %% Fun = {Module, Function} or %% Fun = fun (...) -execute_rule (EngineName ,{Fun, [_, Args], _, _}) -> - apply (Fun, [EngineName | Args]). +execute_rule(EngineName, {Fun, [_, Args], _, _}) -> + apply(Fun, [EngineName | Args]). diff --git a/src/eresye_ontology.erl b/src/eresye_ontology.erl index 6c844f1..7e488d0 100644 --- a/src/eresye_ontology.erl +++ b/src/eresye_ontology.erl @@ -1,36 +1,36 @@ -% -% eres_ontology.erl -% -% ---------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (eresye_ontology). +%% +%%eres_ontology.erl +%% +%%---------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(eresye_ontology). %%==================================================================== %% Include files %%==================================================================== --include ("eres_ontology.hrl"). +-include("eres_ontology.hrl"). %%==================================================================== %% External exports %%==================================================================== --export ([compile/1, compile/2]). +-export([compile/1, compile/2]). %%==================================================================== %% External functions @@ -39,55 +39,59 @@ %% Function: compile/2 %% Description: Compiles an ontology file %%==================================================================== -compile (FileName, Options) -> - {ok, AbstractErlangForm} = epp:parse_file (FileName ++ ".onto", "", []), - %%io:format ("~w~n", [AbstractErlangForm]), - {ok, Classes} = compile_lines ([], list_to_atom (FileName), - AbstractErlangForm), - - %%io:format ("~p~n", [Classes]), - NewClasses = resolve_inheritance (Classes), - %%io:format ("~p~n", [NewClasses]), - IsAHierarchy = generate_hierarchy_tree ([], Classes, Classes), - %%io:format ("~p~n", [IsAHierarchy]), - FatherOfHierarchy = reverse_hierarchy_tree ([], IsAHierarchy, IsAHierarchy), - %%io:format ("~p~n", [FatherOfHierarchy]), - - IncludeLines = generate_include_file (NewClasses), - {ok, IncludeFile} = file:open (FileName ++ ".hrl", [write]), - io:format (IncludeFile, "~s", [IncludeLines]), - file:close (IncludeFile), - %% - - IsClassLines = generate_is_class ([], IsAHierarchy), - IsALines = generate_is_a ([], IsAHierarchy), - {CastClasses, CastLines} = - generate_cast ({[],[]}, FatherOfHierarchy, NewClasses), - ChildOfLines = generate_childof ([], FatherOfHierarchy), - - %% - OntologyFileName = FileName, - {ok, ConversionFile} = file:open (OntologyFileName ++ ".erl", [write]), - io:format (ConversionFile, "-module (~s).~n", [OntologyFileName]), - io:format (ConversionFile, "-include (\"~s.hrl\").~n", - [FileName]), - io:format (ConversionFile, - "-export ([is_class/1, is_a/2, ~s childof/1]).~n~n", - [lists:flatten ( - [io_lib:format ("'~s'/1,", [X]) || X <- CastClasses] - )]), - io:format (ConversionFile, "~s", [IsClassLines]), - io:format (ConversionFile, "~s", [IsALines]), - io:format (ConversionFile, "~s", [ChildOfLines]), - io:format (ConversionFile, "~s", [CastLines]), - file:close (ConversionFile), - ok. +compile(FileName, Options) -> + {ok, AbstractErlangForm} = epp:parse_file(FileName ++ + ".onto", + "", []), + %%io:format ("~w~n", [AbstractErlangForm]), + {ok, Classes} = compile_lines([], + list_to_atom(FileName), AbstractErlangForm), + %%io:format ("~p~n", [Classes]), + NewClasses = resolve_inheritance(Classes), + %%io:format ("~p~n", [NewClasses]), + IsAHierarchy = generate_hierarchy_tree([], Classes, + Classes), + %%io:format ("~p~n", [IsAHierarchy]), + FatherOfHierarchy = reverse_hierarchy_tree([], + IsAHierarchy, IsAHierarchy), + %%io:format ("~p~n", [FatherOfHierarchy]), + IncludeLines = generate_include_file(NewClasses), + {ok, IncludeFile} = file:open(FileName ++ ".hrl", + [write]), + io:format(IncludeFile, "~s", [IncludeLines]), + file:close(IncludeFile), + %% + IsClassLines = generate_is_class([], IsAHierarchy), + IsALines = generate_is_a([], IsAHierarchy), + {CastClasses, CastLines} = generate_cast({[], []}, + FatherOfHierarchy, NewClasses), + ChildOfLines = generate_childof([], FatherOfHierarchy), + %% + OntologyFileName = FileName, + {ok, ConversionFile} = file:open(OntologyFileName ++ + ".erl", + [write]), + io:format(ConversionFile, "-module (~s).~n", + [OntologyFileName]), + io:format(ConversionFile, "-include (\"~s.hrl\").~n", + [FileName]), + io:format(ConversionFile, + "-export ([is_class/1, is_a/2, ~s childof/1])." + "~n~n", + [lists:flatten([io_lib:format("'~s'/1,", [X]) + || X <- CastClasses])]), + io:format(ConversionFile, "~s", [IsClassLines]), + io:format(ConversionFile, "~s", [IsALines]), + io:format(ConversionFile, "~s", [ChildOfLines]), + io:format(ConversionFile, "~s", [CastLines]), + file:close(ConversionFile), + ok. %%==================================================================== %% Function: compile/1 %% Description: Compiles an ontology file %%==================================================================== -compile (FileName) -> compile (FileName, []). +compile(FileName) -> compile(FileName, []). %%==================================================================== %% Internal functions @@ -99,26 +103,31 @@ compile (FileName) -> compile (FileName, []). %% Returns: {ok, [#ontology_class]} | %% {error, Reason} %%==================================================================== -compile_lines (Accumulator, _, []) -> {ok, - lists:flatten ( - lists:reverse (Accumulator))}; -compile_lines (Accumulator, OntoName, - [{function, _, class, _, Clauses} | Tail]) -> - compile_lines ([compile_clauses ([], Clauses) | Accumulator], - OntoName, Tail); -compile_lines (Accumulator, OntoName, - [{attribute, _, ontology, OntoName} | Tail]) -> - compile_lines (Accumulator, OntoName, Tail); -compile_lines (Accumulator, OntoName, - [{attribute, Line, ontology, _} | Tail]) -> - {error,{"ontology name does not match with filename in line", Line}}; -compile_lines (Accumulator, OntoName, [{attribute, _, file, _} | Tail]) -> - compile_lines (Accumulator, OntoName, Tail); -compile_lines (Accumulator, OntoName, [{eof, _} | Tail]) -> - compile_lines (Accumulator, OntoName, Tail); -compile_lines (Accumulator, _, [{_, Line, _, _} | Tail]) -> - {error,{"syntax error in line", Line}}. - +compile_lines(Accumulator, _, []) -> + {ok, lists:flatten(lists:reverse(Accumulator))}; +compile_lines(Accumulator, OntoName, + [{function, _, class, _, Clauses} | Tail]) -> + compile_lines([compile_clauses([], Clauses) + | Accumulator], + OntoName, Tail); +compile_lines(Accumulator, OntoName, + [{attribute, _, ontology, OntoName} | Tail]) -> + compile_lines(Accumulator, OntoName, Tail); +compile_lines(Accumulator, OntoName, + [{attribute, Line, ontology, _} | Tail]) -> + {error, + {"ontology name does not match with filename " + "in line", + Line}}; +compile_lines(Accumulator, OntoName, + [{attribute, _, file, _} | Tail]) -> + compile_lines(Accumulator, OntoName, Tail); +compile_lines(Accumulator, OntoName, + [{eof, _} | Tail]) -> + compile_lines(Accumulator, OntoName, Tail); +compile_lines(Accumulator, _, + [{_, Line, _, _} | Tail]) -> + {error, {"syntax error in line", Line}}. %%==================================================================== %% Func: compile_clauses/2 @@ -126,11 +135,9 @@ compile_lines (Accumulator, _, [{_, Line, _, _} | Tail]) -> %% given its erlang abstract form %% Returns: [#ontology_class] %%==================================================================== -compile_clauses (Acc, []) -> lists:reverse (Acc); -compile_clauses (Acc, [H|T]) -> - compile_clauses ([compile_clause (H) | Acc], T). - - +compile_clauses(Acc, []) -> lists:reverse(Acc); +compile_clauses(Acc, [H | T]) -> + compile_clauses([compile_clause(H) | Acc], T). %%==================================================================== %% Func: compile_clause/1 @@ -138,25 +145,25 @@ compile_clauses (Acc, [H|T]) -> %% given its erlang abstract form %% Returns: #ontology_class %%==================================================================== -compile_clause ({clause, LineNum, - [{atom, _, ClassName}], [], [{tuple, _, ClassDef}]}) -> - #ontology_class { name = ClassName, - superclass = nil, - properties = compile_properties ([], ClassName, ClassDef)}; -compile_clause ({clause, LineNum, - [{atom, _, ClassName}], [], - [{call,_, {atom, _, is_a}, [{atom, _, SuperClass}]}]}) -> - #ontology_class { name = ClassName, - superclass = SuperClass, - properties = []}; -compile_clause ({clause, LineNum, - [{atom, _, ClassName}], [], - [{call,_, {atom, _, is_a}, [{atom, _, SuperClass}]}, - {tuple, _, ClassDef}]}) -> - #ontology_class { name = ClassName, +compile_clause({clause, LineNum, [{atom, _, ClassName}], + [], [{tuple, _, ClassDef}]}) -> + #ontology_class{name = ClassName, superclass = nil, + properties = + compile_properties([], ClassName, ClassDef)}; +compile_clause({clause, LineNum, [{atom, _, ClassName}], + [], + [{call, _, {atom, _, is_a}, + [{atom, _, SuperClass}]}]}) -> + #ontology_class{name = ClassName, + superclass = SuperClass, properties = []}; +compile_clause({clause, LineNum, [{atom, _, ClassName}], + [], + [{call, _, {atom, _, is_a}, [{atom, _, SuperClass}]}, + {tuple, _, ClassDef}]}) -> + #ontology_class{name = ClassName, superclass = SuperClass, - properties = compile_properties ([], ClassName, ClassDef)}. - + properties = + compile_properties([], ClassName, ClassDef)}. %%==================================================================== %% Func: compile_properties/3 @@ -164,10 +171,11 @@ compile_clause ({clause, LineNum, %% given the erlang abstract form %% Returns: [#ontology_property] %%==================================================================== -compile_properties (Acc, _, []) -> lists:reverse (Acc); -compile_properties (Acc, ClassName, [H|T]) -> - compile_properties ([compile_property (ClassName, H) | Acc], - ClassName, T). +compile_properties(Acc, _, []) -> lists:reverse(Acc); +compile_properties(Acc, ClassName, [H | T]) -> + compile_properties([compile_property(ClassName, H) + | Acc], + ClassName, T). %%==================================================================== %% Func: compile_properties/2 @@ -175,311 +183,304 @@ compile_properties (Acc, ClassName, [H|T]) -> %% given the erlang abstract form %% Returns: #ontology_property %%==================================================================== -compile_property (ClassName, - {match, _, {atom, _, FieldName}, FieldDef}) -> - L = cons_to_erl_list (FieldDef), - %%io:format ("~p~n", [L]), - [FieldType, FieldRequirement, Default |_] = L, - #ontology_property {name = FieldName, - type = FieldType, - requirement = FieldRequirement, - is_primitive = is_primitive (FieldType), - is_digit = is_digit (FieldName), - default = Default}. - - +compile_property(ClassName, + {match, _, {atom, _, FieldName}, FieldDef}) -> + L = cons_to_erl_list(FieldDef), + %%io:format ("~p~n", [L]), + [FieldType, FieldRequirement, Default | _] = L, + #ontology_property{name = FieldName, type = FieldType, + requirement = FieldRequirement, + is_primitive = is_primitive(FieldType), + is_digit = is_digit(FieldName), default = Default}. %%==================================================================== %% Func: cons_to_erl_list/1 %% Description: transforms a "cons" abstract erlang construct to a list %% Returns: [term()] %%==================================================================== -cons_to_erl_list ({cons, Line, OP1, OP2}) -> [cons_decode (OP1) | - cons_to_erl_list (OP2)]; -cons_to_erl_list (X) -> [cons_decode(X)]. - - +cons_to_erl_list({cons, Line, OP1, OP2}) -> + [cons_decode(OP1) | cons_to_erl_list(OP2)]; +cons_to_erl_list(X) -> [cons_decode(X)]. %%==================================================================== %% Func: cons_decode/1 %% Description: decodes a single abstract erlang term %% Returns: term() %%==================================================================== -cons_decode ({atom, _, nodefault}) -> ?NO_DEFAULT; -cons_decode ({atom, _, Option}) -> Option; -cons_decode ({nil, _}) -> nil; -cons_decode ({call, _, {atom, _, set_of}, [{atom,_,Type}]}) -> - {set_of, Type}; -cons_decode ({call, _, {atom, _, sequence_of}, [{atom,_,Type}]}) -> - {sequence_of, Type}; -cons_decode ({call,_, {atom, _, default}, [{atom, _, Value}]}) -> - Value. -%cons_decode ({match,_, {atom, _, cardinality}, -% {tuple,_,[{_, _, Low},{_, _, High}]}}) -> -% {cardinality, Low, High}. - +cons_decode({atom, _, nodefault}) -> ?NO_DEFAULT; +cons_decode({atom, _, Option}) -> Option; +cons_decode({nil, _}) -> nil; +cons_decode({call, _, {atom, _, set_of}, + [{atom, _, Type}]}) -> + {set_of, Type}; +cons_decode({call, _, {atom, _, sequence_of}, + [{atom, _, Type}]}) -> + {sequence_of, Type}; +cons_decode({call, _, {atom, _, default}, + [{atom, _, Value}]}) -> + Value.%cons_decode ({match,_, {atom, _, cardinality}, +%% {tuple,_,[{_, _, Low},{_, _, High}]}}) -> +%% {cardinality, Low, High}. %%==================================================================== %% Func: is_primitive/1 %% Description: checks if a type is primitive %% Returns: true | false %%==================================================================== -is_primitive (string) -> true; -is_primitive (number) -> true; -is_primitive (integer) -> true; -is_primitive (boolean) -> true; -is_primitive (any) -> true; -is_primitive ({sequence_of, X}) -> is_primitive (X); -is_primitive ({set_of, X}) -> is_primitive (X); -is_primitive (_) -> false. - - +is_primitive(string) -> true; +is_primitive(number) -> true; +is_primitive(integer) -> true; +is_primitive(boolean) -> true; +is_primitive(any) -> true; +is_primitive({sequence_of, X}) -> is_primitive(X); +is_primitive({set_of, X}) -> is_primitive(X); +is_primitive(_) -> false. %%==================================================================== %% Func: is_digit/1 %% Description: checks if a slot name is a digit %% Returns: true | false %%==================================================================== -is_digit ('0') -> true; -is_digit ('1') -> true; -is_digit ('2') -> true; -is_digit ('3') -> true; -is_digit ('4') -> true; -is_digit ('5') -> true; -is_digit ('6') -> true; -is_digit ('7') -> true; -is_digit ('8') -> true; -is_digit ('9') -> true; -is_digit (_) -> false. - +is_digit('0') -> true; +is_digit('1') -> true; +is_digit('2') -> true; +is_digit('3') -> true; +is_digit('4') -> true; +is_digit('5') -> true; +is_digit('6') -> true; +is_digit('7') -> true; +is_digit('8') -> true; +is_digit('9') -> true; +is_digit(_) -> false. %%==================================================================== %% Func: resolve_inheritance/1 %% Description: resolves the inheritances in the list of #ontology_class %% Returns: [#ontology_class] %%==================================================================== -resolve_inheritance (Classes) -> - case resolve_inheritance ([], Classes, Classes) of - {false, NewClassList} -> resolve_inheritance (NewClassList); - {true, NewClassList} -> NewClassList - end. - +resolve_inheritance(Classes) -> + case resolve_inheritance([], Classes, Classes) of + {false, NewClassList} -> + resolve_inheritance(NewClassList); + {true, NewClassList} -> NewClassList + end. %%==================================================================== %% Func: resolve_inheritance/3 %% Description: resolves the inheritances in the list of #ontology_class %% Returns: {Solved, [#ontology_class]} %%==================================================================== -resolve_inheritance (Acc, _, []) -> {true, lists:reverse (Acc)}; -resolve_inheritance (Acc, Classes, - [Class = #ontology_class { superclass = nil} | T]) -> - resolve_inheritance ([Class | Acc], Classes, T); -resolve_inheritance (Acc, Classes, [Class | T]) -> - SuperClass = get_class (Class#ontology_class.superclass, Classes), - NewClass = Class#ontology_class { - properties = - lists:foldl (fun (X, Acc) -> - override_property ([], Acc, X) - end, - SuperClass#ontology_class.properties, - Class#ontology_class.properties), - superclass = nil}, - {false, lists:reverse ([NewClass | Acc]) ++ T}. - - -override_property (Acc, [], _) -> lists:reverse (Acc); -override_property (Acc, - [P = #ontology_property { name = N} | T], - Property = #ontology_property {name = N}) -> - override_property ([Property | Acc], T, Property); -override_property (Acc, [P | T], Property) -> - override_property ([P | Acc], T, Property). - +resolve_inheritance(Acc, _, []) -> + {true, lists:reverse(Acc)}; +resolve_inheritance(Acc, Classes, + [Class = #ontology_class{superclass = nil} | T]) -> + resolve_inheritance([Class | Acc], Classes, T); +resolve_inheritance(Acc, Classes, [Class | T]) -> + SuperClass = get_class(Class#ontology_class.superclass, + Classes), + NewClass = Class#ontology_class{properties = + lists:foldl(fun (X, Acc) -> + override_property([], + Acc, + X) + end, + SuperClass#ontology_class.properties, + Class#ontology_class.properties), + superclass = nil}, + {false, lists:reverse([NewClass | Acc]) ++ T}. + +override_property(Acc, [], _) -> lists:reverse(Acc); +override_property(Acc, + [P = #ontology_property{name = N} | T], + Property = #ontology_property{name = N}) -> + override_property([Property | Acc], T, Property); +override_property(Acc, [P | T], Property) -> + override_property([P | Acc], T, Property). %%==================================================================== %% Func: get_class/2 %% Description: Searches for a class in the list %% Returns: #ontology_class %%==================================================================== -get_class (ClassName, []) -> nil; -get_class (ClassName, [Class = #ontology_class { name = ClassName } | T]) -> - Class; -get_class (ClassName, [_ | T]) -> - get_class (ClassName, T). - - +get_class(ClassName, []) -> nil; +get_class(ClassName, + [Class = #ontology_class{name = ClassName} | T]) -> + Class; +get_class(ClassName, [_ | T]) -> + get_class(ClassName, T). %%==================================================================== %% Func: generate_hierarchy_tree/3 %% Description: generates the tree of hierarchies %% Returns: [{classname, [classname]}] %%==================================================================== -generate_hierarchy_tree (Acc, [], _) -> lists:reverse (Acc); -generate_hierarchy_tree (Acc, [Class | T], Classes) -> - Item = {Class#ontology_class.name, - ancestors_list ([], Class#ontology_class.superclass, Classes)}, - generate_hierarchy_tree ([Item | Acc], T, Classes). - - -ancestors_list (Acc, nil, Classes) -> lists:reverse (Acc); -ancestors_list (Acc, X, Classes) -> - C = get_class (X, Classes), - ancestors_list ([X | Acc], C#ontology_class.superclass, Classes). - - - - -reverse_hierarchy_tree (Acc, [], _) -> lists:reverse (Acc); -reverse_hierarchy_tree (Acc, [{Father, _} | T], Classes) -> - Item = {Father, child_list (Father, Classes)}, - reverse_hierarchy_tree ([Item | Acc], T, Classes). - -child_list (Father, Classes) -> - [ C || {C, Ancestors} <- Classes, lists:member (Father, Ancestors)]. - +generate_hierarchy_tree(Acc, [], _) -> + lists:reverse(Acc); +generate_hierarchy_tree(Acc, [Class | T], Classes) -> + Item = {Class#ontology_class.name, + ancestors_list([], Class#ontology_class.superclass, + Classes)}, + generate_hierarchy_tree([Item | Acc], T, Classes). + +ancestors_list(Acc, nil, Classes) -> lists:reverse(Acc); +ancestors_list(Acc, X, Classes) -> + C = get_class(X, Classes), + ancestors_list([X | Acc], C#ontology_class.superclass, + Classes). + +reverse_hierarchy_tree(Acc, [], _) -> + lists:reverse(Acc); +reverse_hierarchy_tree(Acc, [{Father, _} | T], + Classes) -> + Item = {Father, child_list(Father, Classes)}, + reverse_hierarchy_tree([Item | Acc], T, Classes). + +child_list(Father, Classes) -> + [C + || {C, Ancestors} <- Classes, + lists:member(Father, Ancestors)]. %%==================================================================== %% Func: generate_include_file/1 %% Description: generates the include file from a list of #ontology_class %% Returns: [string()] %%==================================================================== -generate_include_file (Classes) -> generate_include_file ([], Classes). - -generate_include_file (Acc, []) -> lists:flatten (lists:reverse (Acc)); -generate_include_file (Acc, [Class | T]) -> - Head = io_lib:format ("-record('~s',{~n", [Class#ontology_class.name]), - Properties = generate_include_lines ([], Class#ontology_class.properties), - Line = lists:flatten ([Head, Properties, "\n"]), - generate_include_file ([Line | Acc], T). +generate_include_file(Classes) -> + generate_include_file([], Classes). +generate_include_file(Acc, []) -> + lists:flatten(lists:reverse(Acc)); +generate_include_file(Acc, [Class | T]) -> + Head = io_lib:format("-record('~s',{~n", + [Class#ontology_class.name]), + Properties = generate_include_lines([], + Class#ontology_class.properties), + Line = lists:flatten([Head, Properties, "\n"]), + generate_include_file([Line | Acc], T). %%==================================================================== %% Func: generate_include_lines/1 %% Description: generates the lines of properties for an include file %% Returns: [string()] %%==================================================================== -generate_include_lines (Acc, []) -> - Line = io_lib:format ("}).~n", []), - lists:reverse ([Line | Acc]); -generate_include_lines (Acc, [Property = #ontology_property - { default = ?NO_DEFAULT }]) -> - Line = io_lib:format (" '~s'", [Property#ontology_property.name]), - generate_include_lines ([Line | Acc], []); -generate_include_lines (Acc, [Property = #ontology_property - { default = ?NO_DEFAULT } | T]) -> - Line = io_lib:format (" '~s',~n", [Property#ontology_property.name]), - generate_include_lines ([Line | Acc], T); -generate_include_lines (Acc, [Property]) -> - Line = io_lib:format (" '~s' = '~s'", - [Property#ontology_property.name, - Property#ontology_property.default]), - generate_include_lines ([Line | Acc], []); -generate_include_lines (Acc, [Property | T]) -> - Line = io_lib:format (" '~s' = '~s',~n", - [Property#ontology_property.name, - Property#ontology_property.default]), - generate_include_lines ([Line | Acc], T). - - - +generate_include_lines(Acc, []) -> + Line = io_lib:format("}).~n", []), + lists:reverse([Line | Acc]); +generate_include_lines(Acc, + [Property = #ontology_property{default = + ?NO_DEFAULT}]) -> + Line = io_lib:format(" '~s'", + [Property#ontology_property.name]), + generate_include_lines([Line | Acc], []); +generate_include_lines(Acc, + [Property = #ontology_property{default = ?NO_DEFAULT} + | T]) -> + Line = io_lib:format(" '~s',~n", + [Property#ontology_property.name]), + generate_include_lines([Line | Acc], T); +generate_include_lines(Acc, [Property]) -> + Line = io_lib:format(" '~s' = '~s'", + [Property#ontology_property.name, + Property#ontology_property.default]), + generate_include_lines([Line | Acc], []); +generate_include_lines(Acc, [Property | T]) -> + Line = io_lib:format(" '~s' = '~s',~n", + [Property#ontology_property.name, + Property#ontology_property.default]), + generate_include_lines([Line | Acc], T). %%==================================================================== %% Func: generate_childof/2 %% Description: generates the lines for 'childof' functions %% Returns: [string()] %%==================================================================== -generate_childof (Acc, []) -> - lists:flatten ( - lists:reverse (["childof (_) -> exit (undef_class).\n\n" | Acc])); -generate_childof (Acc, [{FatherClassName, Children} | T]) -> - Line = lists:flatten ( - io_lib:format ("childof ('~s') -> ~p;\n", - [FatherClassName, Children])), - generate_childof ([Line | Acc], T). - - +generate_childof(Acc, []) -> + lists:flatten(lists:reverse(["childof (_) -> exit (undef_class).\n\n" + | Acc])); +generate_childof(Acc, + [{FatherClassName, Children} | T]) -> + Line = + lists:flatten(io_lib:format("childof ('~s') -> ~p;\n", + [FatherClassName, Children])), + generate_childof([Line | Acc], T). %%==================================================================== %% Func: generate_is_a/2 %% Description: generates the lines for 'is_a' functions %% Returns: [string()] %%==================================================================== -generate_is_a (Acc, []) -> - lists:flatten (lists:reverse (["is_a (_,_) -> false.\n\n" | Acc])); -generate_is_a (Acc, [{ClassName, []} | T]) -> - generate_is_a (Acc, T); -generate_is_a (Acc, [{ClassName, Ancestors} | T]) -> - Line = [lists:flatten ( - io_lib:format ("is_a ('~s','~s') -> true;\n", - [ClassName, Ancestor])) - || Ancestor <- Ancestors], - generate_is_a ([Line | Acc], T). - +generate_is_a(Acc, []) -> + lists:flatten(lists:reverse(["is_a (_,_) -> false.\n\n" + | Acc])); +generate_is_a(Acc, [{ClassName, []} | T]) -> + generate_is_a(Acc, T); +generate_is_a(Acc, [{ClassName, Ancestors} | T]) -> + Line = + [lists:flatten(io_lib:format("is_a ('~s','~s') -> true;\n", + [ClassName, Ancestor])) + || Ancestor <- Ancestors], + generate_is_a([Line | Acc], T). %%==================================================================== %% Func: generate_is_class/1 %% Description: generates the lines for 'is_class' functions %% Returns: boolean %%==================================================================== -generate_is_class (Acc, []) -> - lists:flatten (lists:reverse (["is_class (_) -> false.\n\n" | Acc])); -generate_is_class (Acc, [{ClassName, _} | T]) -> - Line = lists:flatten ( - io_lib:format ("is_class ('~s') -> true;\n", - [ClassName])), - generate_is_class ([Line | Acc], T). - +generate_is_class(Acc, []) -> + lists:flatten(lists:reverse(["is_class (_) -> false.\n\n" + | Acc])); +generate_is_class(Acc, [{ClassName, _} | T]) -> + Line = + lists:flatten(io_lib:format("is_class ('~s') -> true;\n", + [ClassName])), + generate_is_class([Line | Acc], T). %%==================================================================== %% Func: generate_cast/2 %% Description: generates the lines for cast functions %% Returns: [string()] %%==================================================================== -generate_cast ({Acc1, Acc2}, [], _) -> - {lists:reverse (Acc1), lists:reverse (Acc2)}; -generate_cast ({Acc1, Acc2}, [{ClassName, []} | T], ResolvedClasses) -> - generate_cast ({Acc1, Acc2}, T, ResolvedClasses); -generate_cast ({Acc1, Acc2}, [{ClassName, Children} | T], - ResolvedClasses) -> - - Lines = lists:flatten ( - lists:map ( - fun (X) -> - DestinationClass = get_class (ClassName, ResolvedClasses), - SourceClass = get_class (X, ResolvedClasses), - generate_translation_lines (SourceClass, - DestinationClass) - end, Children)), - [CR, CR, _ | ReversedList] = lists:reverse (Lines), - %%replace last semicolon with a dot to end the clause - NewLines = lists:reverse ([CR, CR, $. | ReversedList]), - generate_cast ({[ClassName | Acc1] , [NewLines | Acc2]}, T, ResolvedClasses). - - - -generate_translation_lines (SourceClass, DestinationClass) -> - Lines = - [ lists:flatten (io_lib:format (" '~s' = X#'~s'.'~s'", - [X#ontology_property.name, +generate_cast({Acc1, Acc2}, [], _) -> + {lists:reverse(Acc1), lists:reverse(Acc2)}; +generate_cast({Acc1, Acc2}, [{ClassName, []} | T], + ResolvedClasses) -> + generate_cast({Acc1, Acc2}, T, ResolvedClasses); +generate_cast({Acc1, Acc2}, [{ClassName, Children} | T], + ResolvedClasses) -> + Lines = lists:flatten([generate_cast_1(V1, ClassName, + ResolvedClasses) + || V1 <- Children]), + [CR, CR, _ | ReversedList] = lists:reverse(Lines), + %%replace last semicolon with a dot to end the clause + NewLines = lists:reverse([CR, CR, $. | ReversedList]), + generate_cast({[ClassName | Acc1], [NewLines | Acc2]}, + T, ResolvedClasses). + +generate_cast_1(X, ClassName, ResolvedClasses) -> + DestinationClass = get_class(ClassName, + ResolvedClasses), + SourceClass = get_class(X, ResolvedClasses), + generate_translation_lines(SourceClass, + DestinationClass). + +generate_translation_lines(SourceClass, + DestinationClass) -> + Lines = + [lists:flatten(io_lib:format(" '~s' = X#'~s'.'~s'", + [X#ontology_property.name, + SourceClass#ontology_class.name, + X#ontology_property.name])) + || X <- DestinationClass#ontology_class.properties], + %%io:format ("~p~n", [Lines]), + XLines = lists:foldl(fun (X, Sum) -> + lists:concat([Sum, ",\n", X]) + end, + "", Lines), + %%io:format ("~p~n", [XLines]), + [_, _ | YLines] = XLines, + Head = + lists:flatten(io_lib:format("'~s' (X = #'~s'{}) ->\n #'~s'{\n", + [DestinationClass#ontology_class.name, SourceClass#ontology_class.name, - X#ontology_property.name])) - || X <- DestinationClass#ontology_class.properties], - %%io:format ("~p~n", [Lines]), - XLines = lists:foldl (fun (X, Sum) -> - lists:concat ([Sum, ",\n", X]) - end, - "", - Lines), - %%io:format ("~p~n", [XLines]), - [_,_ | YLines] = XLines, - Head = lists:flatten ( - io_lib:format ("'~s' (X = #'~s'{}) ->\n #'~s'{\n", - [DestinationClass#ontology_class.name, - SourceClass#ontology_class.name, - DestinationClass#ontology_class.name])), - lists:concat ([Head , - lists:flatten (YLines), - "};\n\n"]). - - - + DestinationClass#ontology_class.name])), + lists:concat([Head, lists:flatten(YLines), "};\n\n"]). diff --git a/src/eresye_ontology_resolver.erl b/src/eresye_ontology_resolver.erl index 68a83b4..5f674a5 100644 --- a/src/eresye_ontology_resolver.erl +++ b/src/eresye_ontology_resolver.erl @@ -1,90 +1,88 @@ -% -% eresye_ontology_resolver.erl -% -% ---------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% +%% +%%eresye_ontology_resolver.erl +%% +%%---------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% --module (eresye_ontology_resolver). --export ([resolve_ontology/2]). +-module(eresye_ontology_resolver). +-export([resolve_ontology/2]). -resolve_ontology (AbstractErlangForm, Ontology) -> - generate_clauses ([], AbstractErlangForm, Ontology). -%% iterate ([], AbstractErlangForm, Ontology). - -iterate (Acc, [], _) -> lists:reverse (Acc); -iterate (Acc, [{function, Line, Name, Arity, Def} | T], Ontology) -> - Clauses = generate_clauses ([], Def, Ontology), - iterate ([{function, Line, Name, Arity, Clauses} | Acc], T, Ontology); -iterate (Acc, [H | T], Ontology) -> - iterate ([H | Acc], T, Ontology). - - -generate_clauses (Acc, [], _) -> Acc; -generate_clauses (Acc, [{clause, Line, [], Guard, Body} | T], Ontology) -> - generate_clauses ([{clause, Line, [], Guard, Body} | Acc], T, Ontology); -generate_clauses (Acc, [{clause, Line, Head, Guard, Body} | T], Ontology) -> - %%io:format ("~p~n", [Head]), - Solved = substitute (Head, - fun ({match, _, {record, _, C, _}, _}) -> - Ontology:is_class (C); - (_) -> false end, - fun ({X1, X2, {record, X3, C, X4}, X5}) -> - [ {X1, X2, {record, X3, X, X4}, X5} - || X <- [C | Ontology:childof (C)]] - end), - NewClauses = [ {clause, Line, X, Guard, Body} || X <- Solved], - generate_clauses (NewClauses ++ Acc, T, Ontology). - +resolve_ontology(AbstractErlangForm, Ontology) -> + generate_clauses([], AbstractErlangForm, Ontology). +%% iterate ([], AbstractErlangForm, Ontology). -indexOf (Acc, [], _, _) -> lists:reverse (Acc); -indexOf (Acc, [H | T], Pred, New) -> - case Pred (H) of - true -> indexOf ([New (H) | Acc], T, Pred, New); - _ -> indexOf ([[H] | Acc], T, Pred, New) - end. - -indexOf (Data, Pred, New) -> indexOf ([], Data, Pred, New). +generate_clauses(Acc, [], _) -> Acc; +generate_clauses(Acc, + [{clause, Line, [], Guard, Body} | T], Ontology) -> + generate_clauses([{clause, Line, [], Guard, Body} + | Acc], + T, Ontology); +generate_clauses(Acc, + [{clause, Line, Head, Guard, Body} | T], Ontology) -> + %%io:format ("~p~n", [Head]), + Solved = substitute(Head, + fun ({match, _, {record, _, C, _}, _}) -> + Ontology:is_class(C); + (_) -> false + end, + fun ({X1, X2, {record, X3, C, X4}, X5}) -> + [{X1, X2, {record, X3, X, X4}, X5} + || X <- [C | Ontology:childof(C)]] + end), + NewClauses = [{clause, Line, X, Guard, Body} + || X <- Solved], + generate_clauses(NewClauses ++ Acc, T, Ontology). +indexOf(Acc, [], _, _) -> lists:reverse(Acc); +indexOf(Acc, [H | T], Pred, New) -> + case Pred(H) of + true -> indexOf([New(H) | Acc], T, Pred, New); + _ -> indexOf([[H] | Acc], T, Pred, New) + end. -substitute (L, Pred, New) -> - Lists = indexOf(L, Pred, New), - Arg = tl(lists:foldr (fun (X,Sum) -> - lists:flatten(io_lib:format (",A~w", [X])) ++ Sum - end, - "", - lists:seq (1,length (L)))), - StringLists = tl(lists:foldr ( - fun (X,Sum) -> - lists:flatten( - io_lib:format (",A~w<-~p", - [X, lists:nth (X, Lists)])) ++ Sum - end, "", - lists:seq (1,length (L)))), - String = "[ [" ++ Arg ++ "] || " ++ StringLists ++ "].", - {ok, Tokens, _} = erl_scan:string (String), - {ok, Expr} = erl_parse:parse_exprs (Tokens), - case catch (erl_eval:exprs (Expr, erl_eval:new_bindings ())) of - {'EXIT', _} -> false; - {value, Value, Bindings} -> Value; - _ -> false - end. +indexOf(Data, Pred, New) -> + indexOf([], Data, Pred, New). +substitute(L, Pred, New) -> + Lists = indexOf(L, Pred, New), + Arg = tl(lists:foldr(fun (X, Sum) -> + lists:flatten(io_lib:format(",A~w", [X])) ++ + Sum + end, + "", lists:seq(1, length(L)))), + StringLists = tl(lists:foldr(fun (X, Sum) -> + lists:flatten(io_lib:format(",A~w<-~p", + [X, + lists:nth(X, + Lists)])) + ++ Sum + end, + "", lists:seq(1, length(L)))), + String = "[ [" ++ Arg ++ "] || " ++ StringLists ++ "].", + {ok, Tokens, _} = erl_scan:string(String), + {ok, Expr} = erl_parse:parse_exprs(Tokens), + case catch erl_eval:exprs(Expr, erl_eval:new_bindings()) + of + {'EXIT', _} -> false; + {value, Value, Bindings} -> Value; + _ -> false + end. diff --git a/src/eresye_tree_list.erl b/src/eresye_tree_list.erl index 1264a52..0b31140 100644 --- a/src/eresye_tree_list.erl +++ b/src/eresye_tree_list.erl @@ -1,277 +1,227 @@ -% -% eres_tree_list.erl -% -% ---------------------------------------------------------------------- -% -% ERESYE, an ERlang Expert SYstem Engine -% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% --module (eresye_tree_list). --export ([new/0, - insert/4, - child/3, - get_last_insert/1, - get_root/1, - lookup_all/2, - children/2, - update_node/2, - refresh/2, - is_root/1, - get_beta/1, - update_beta/3, - get_key/1, - update_key/3, - have_child/1, - get_parent/2, - remove_node/2, - is_present/2, - keysearch/2, - set_child/3, - get_node/2, - get_id/1, - remove_child/3]). - -new () -> - [{root, nil, [], 0, 1}]. - - -insert (Key, Value, Parent_node, List) -> - {Parent_key, Parent_value, Children, Parent, Pos} = Parent_node, +%% +%%eres_tree_list.erl +%% +%%---------------------------------------------------------------------- +%% +%% ERESYE, an ERlang Expert SYstem Engine +%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com) +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +-module(eresye_tree_list). + +-export([child/3, children/2, get_beta/1, get_id/1, + get_key/1, get_last_insert/1, get_node/2, get_parent/2, + get_root/1, have_child/1, insert/4, is_present/2, + is_root/1, keysearch/2, lookup_all/2, new/0, refresh/2, + remove_child/3, remove_node/2, set_child/3, + update_beta/3, update_key/3, update_node/2]). + +new() -> [{root, nil, [], 0, 1}]. + +insert(Key, Value, Parent_node, List) -> + {Parent_key, Parent_value, Children, Parent, Pos} = + Parent_node, Next = length(List) + 1, Node = {Key, Value, [], Pos, Next}, - List1 = lists:append(List, [Node]), - Children1 = lists:append(Children, [Next]), - Parent_node1 = {Parent_key, Parent_value, Children1, Parent, Pos}, + List1 = List ++ [Node], + Children1 = Children ++ [Next], + Parent_node1 = {Parent_key, Parent_value, Children1, + Parent, Pos}, L1 = lists:keyreplace(Pos, 5, List1, Parent_node1), {Node, L1}. - +%%cerca tra i figli del Parent_node un nodo la cui chiave (tupla) sia uguale a Key +%%se Key non e' una tupla cerca il nodo il cui primo elemento e' {Key,_} +%%Restituisce il nodo stesso o false se non trova alcuna tupla -% cerca tra i figli del Parent_node un nodo la cui chiave (tupla) sia uguale a Key -% se Key non e' una tupla cerca il nodo il cui primo elemento e' {Key,_} -% Restituisce il nodo stesso o false se non trova alcuna tupla - -child (Key, Parent_node, List) -> +child(Key, Parent_node, List) -> Children = element(3, Parent_node), - search (Key, List, Children). + search(Key, List, Children). -search (Key, List, []) -> - false; -search (Key, List, [Nth_element | T]) -> +search(Key, List, []) -> false; +search(Key, List, [Nth_element | T]) -> Elem = lists:nth(Nth_element, List), Res = search(Key, Elem), case Res of - true -> - Elem; - false -> - search (Key, List, T) + true -> Elem; + false -> search(Key, List, T) end. -search ({p_node, Fun},{{p_node,{Fun,_}},_,_,_,_}) -> - true; -search ({p_node, Fun,_},{{p_node,{Fun,_}},_,_,_,_})-> - true; -search ({Tab, Fun},{{Tab, Fun},_,_,_,_})-> +search({p_node, Fun}, + {{p_node, {Fun, _}}, _, _, _, _}) -> true; -search (Tab,{{Tab,_},_,_,_,_})-> +search({p_node, Fun, _}, + {{p_node, {Fun, _}}, _, _, _, _}) -> true; -search (K, E) -> - false. +search({Tab, Fun}, {{Tab, Fun}, _, _, _, _}) -> true; +search(Tab, {{Tab, _}, _, _, _, _}) -> true; +search(K, E) -> false. +test(X, X) -> true; +test(X, Y) -> false. -test (X, X) -> - true; -test (X, Y) -> - false. - - - -get_root ([]) -> - nil; -get_root ([Root | T]) -> +get_root([]) -> nil; +get_root([Root | T]) -> case is_root(Root) of - true -> - Root; - false -> - nil + true -> Root; + false -> nil end. +is_root({root, _, _, _, _}) -> true; +is_root(Node) -> false. -is_root ({root, _, _, _, _}) -> - true; -is_root (Node) -> - false. - -% controlla se esiste un join_node legato all'alfa-memory Tab -% restituisce true se ne esiste almeno uno, altrimenti false -is_present (Tab, []) -> - false; +%%controlla se esiste un join_node legato all'alfa-memory Tab +%%restituisce true se ne esiste almeno uno, altrimenti false +is_present(Tab, []) -> false; is_present(Tab, [Node | T]) -> - case catch element(1, element(1, Node)) of % il primo elemento della lista - {'EXIT', {badarg,_}} -> % genera un'eccezione - is_present(Tab, T); - Tab_elem -> - case test(Tab_elem, Tab) of - true -> - true; - false -> - is_present(Tab, T) - end + case catch element(1, + element(1, Node)) % il primo elemento della lista + of + {'EXIT', + {badarg, _}} -> % genera un'eccezione + is_present(Tab, T); + Tab_elem -> + case test(Tab_elem, Tab) of + true -> true; + false -> is_present(Tab, T) + end end. -% restituisce la lista di tutti gli elementi in List associati alla -% chiave Key. Se non esiste nessun elemento con la chiave richiesta -% il risultato e' una lista vuota -% Key = Tab -% Key = {Tab, Join_fun} -% Key = {p_node, Fun} -% Key = {p_node, {Fun, _}} -lookup_all (Key, List) -> +%%restituisce la lista di tutti gli elementi in List associati alla +%%chiave Key. Se non esiste nessun elemento con la chiave richiesta +%%il risultato e' una lista vuota +%%Key = Tab +%%Key = {Tab, Join_fun} +%%Key = {p_node, Fun} +%%Key = {p_node, {Fun, _}} +lookup_all(Key, List) -> [Root | L] = List, - lists:foldl(fun(Elem, Result_list) -> - %Tab_elem = element(1, element(1, Elem)), - case search(Key, Elem) of - true -> - %lists:append(Result_list, [Elem]); - [Elem | Result_list]; - false -> - Result_list - end - end, [], L). - -% Cerca un elemento con chiave Key e restituisce il primo trovato o false -keysearch (Key, []) -> - false; -keysearch (Key, [Node | OtherNode]) -> + lists:foldl(fun (Elem, Result_list) -> + %%Tab_elem = element(1, element(1, Elem)), + case search(Key, Elem) of + true -> + %%lists:append(Result_list, [Elem]); + [Elem | Result_list]; + false -> Result_list + end + end, + [], L). + +%%Cerca un elemento con chiave Key e restituisce il primo trovato o false +keysearch(Key, []) -> false; +keysearch(Key, [Node | OtherNode]) -> case search(Key, Node) of - false -> - keysearch(Key, OtherNode); - true -> - Node + false -> keysearch(Key, OtherNode); + true -> Node end. -% restituisce tutti i nodi figli di Join_node -% o una lista vuota se Join_node non ha successori -children (Join_node, List) -> +%%restituisce tutti i nodi figli di Join_node +%%o una lista vuota se Join_node non ha successori +children(Join_node, List) -> Pos_list = element(3, Join_node), - lists:foldl(fun(Pos, Children)-> - Elem = lists:nth(Pos, List), - lists:append(Children, [Elem]) - end, [], Pos_list). - + lists:foldl(fun (Pos, Children) -> + Elem = lists:nth(Pos, List), Children ++ [Elem] + end, + [], Pos_list). -update_node (Join_node, List) -> - Pos = element (5, Join_node), +update_node(Join_node, List) -> + Pos = element(5, Join_node), lists:keyreplace(Pos, 5, List, Join_node). -get_node (Id, List) -> - lists:nth(Id, List). - -get_last_insert (List) -> - N = length (List), - lists:nth (N, List). +get_node(Id, List) -> lists:nth(Id, List). -get_id (Node) -> - element(5, Node). +get_last_insert(List) -> + N = length(List), lists:nth(N, List). -refresh (Node, List) -> - Pos = element(5, Node), - lists:nth(Pos, List). +get_id(Node) -> element(5, Node). +refresh(Node, List) -> + Pos = element(5, Node), lists:nth(Pos, List). -get_beta (Node) -> - element(2, Node). +get_beta(Node) -> element(2, Node). -update_beta (Beta_new, Node, List) -> +update_beta(Beta_new, Node, List) -> {Key, Beta_old, Children, Parent, Pos} = Node, New_node = {Key, Beta_new, Children, Parent, Pos}, lists:keyreplace(Pos, 5, List, New_node). +get_key(Node) -> element(1, Node). -get_key (Node) -> - element(1, Node). - -update_key (NewKey, Node, List) -> +update_key(NewKey, Node, List) -> {Key, Beta, Children, Parent, Pos} = Node, New_node = {NewKey, Beta, Children, Parent, Pos}, lists:keyreplace(Pos, 5, List, New_node). +get_parent(Node, List) -> + Parent = element(4, Node), lists:nth(Parent, List). -get_parent (Node, List) -> - Parent = element (4, Node), - lists:nth(Parent, List). - -have_child (Node) -> +have_child(Node) -> Children = element(3, Node), case Children of - [] -> - false; - Other -> - true + [] -> false; + Other -> true end. -remove_child (Child, Parent_Node, List) -> +remove_child(Child, Parent_Node, List) -> ChildId = element(5, Child), {Key, Value, Children, Parent, Pos} = Parent_Node, - New_node = {Key, Value, Children -- [ChildId], Parent, Pos}, + New_node = {Key, Value, Children -- [ChildId], Parent, + Pos}, lists:keyreplace(Pos, 5, List, New_node). - -set_child (Child, Parent_node, List) -> +set_child(Child, Parent_node, List) -> {Key, Value, Children, Parent, Pos} = Parent_node, ChildId = element(5, Child), - New_node = {Key, Value, Children ++ [ChildId], Parent, Pos}, + New_node = {Key, Value, Children ++ [ChildId], Parent, + Pos}, lists:keyreplace(Pos, 5, List, New_node). - - -remove_node (Node, List) -> - Pos = element (5, Node), +remove_node(Node, List) -> + Pos = element(5, Node), Parent_node = get_parent(Node, List), - List1 = remove_child (Node, Parent_node, List), - Head = lists:sublist(List1, Pos-1), + List1 = remove_child(Node, Parent_node, List), + Head = lists:sublist(List1, Pos - 1), Tail = lists:nthtail(Pos, List1), - update_list (Head, Tail, Pos). + update_list(Head, Tail, Pos). -update_list (List, [], N) -> - List; -update_list (List, [Node | T], N) -> -% io:format("Node=~w~n",[Node]), - New_pos = length(List)+1, +update_list(List, [], N) -> List; +update_list(List, [Node | T], N) -> + %% io:format("Node=~w~n",[Node]), + New_pos = length(List) + 1, {Key, Value, Children, Parent, Pos} = Node, case Parent > N of - true -> - New_parent = Parent -1, - List1 = List; - false -> - New_parent = Parent, - {Key1, Value1, Children1, Parent1, Pos1} = lists:nth(New_parent, List), - Parent_node = {Key1, Value1, (Children1 -- [Pos])++ [New_pos], Parent1, Pos1}, - % io:format(">ParentNode=~w~n",[Parent_node]), - List1 = lists:keyreplace(Parent, 5, List, Parent_node) + true -> New_parent = Parent - 1, List1 = List; + false -> + New_parent = Parent, + {Key1, Value1, Children1, Parent1, Pos1} = + lists:nth(New_parent, List), + Parent_node = {Key1, Value1, + (Children1 -- [Pos]) ++ [New_pos], Parent1, Pos1}, + %% io:format(">ParentNode=~w~n",[Parent_node]), + List1 = lists:keyreplace(Parent, 5, List, Parent_node) end, - New_children = lists:map(fun(X)-> - case X > N of - true -> X-1; - false ->X - end - end, Children), - New_node = {Key, Value, New_children, New_parent, New_pos}, -% io:format("NewNode=~w~n",[New_node]), + New_children = [update_list_1(V1, N) || V1 <- Children], + New_node = {Key, Value, New_children, New_parent, + New_pos}, + %% io:format("NewNode=~w~n",[New_node]), List2 = List1 ++ [New_node], update_list(List2, T, N). +update_list_1(X, N) -> + case X > N of + true -> X - 1; + false -> X + end. diff --git a/src/eventmanager.erl b/src/eventmanager.erl index f4a759c..f11290b 100644 --- a/src/eventmanager.erl +++ b/src/eventmanager.erl @@ -21,11 +21,9 @@ %% %% -module(eventmanager). --export([silent_event/4, - timeout_event/4, - acl_event/4, - eres_event/4, - eventof/1]). + +-export([acl_event/4, eres_event/4, eventof/1, + silent_event/4, timeout_event/4]). eventof(timeout) -> timeout_event; eventof(acl) -> acl_event; @@ -54,10 +52,10 @@ acl_event(Sync, Agent, Pattern, Proc) -> Message = agent:match_message(Agent, Pattern), object:call(Sync, signal, [{acl, Message, Proc}]). -eres_event(Sync, Agent, {Engine, read, Pattern}, Proc) -> +eres_event(Sync, Agent, {Engine, read, Pattern}, + Proc) -> Data = eresye:wait(Engine, Pattern), object:call(Sync, signal, [{eres, Data, Proc}]); - eres_event(Sync, Agent, {Engine, get, Pattern}, Proc) -> Data = eresye:wait_and_retract(Engine, Pattern), %%io:format("eres got ~w\n", [Data]), diff --git a/src/exat.erl b/src/exat.erl index 677f4bc..cacde12 100644 --- a/src/exat.erl +++ b/src/exat.erl @@ -20,8 +20,9 @@ %% along with this program. If not, see %% %% --module (exat). --behaviour (application). +-module(exat). + +-behaviour(application). %%==================================================================== %% Include files @@ -31,17 +32,14 @@ %% External exports %%==================================================================== --export ([start/2, - stop/1, - current_platform/0, - split_agent_identifier/1, - get_argument/1]). +-export([current_platform/0, get_argument/1, + split_agent_identifier/1, start/2, stop/1]). %%==================================================================== %% Internal exports %%==================================================================== --export ([]). +-export([]). %%==================================================================== %% Macros @@ -60,44 +58,36 @@ %% {ok, Pid, State} | %% {error, Reason} %%==================================================================== -start (Type, StartArgs) -> - exat_sup:start_link(). - +start(Type, StartArgs) -> exat_sup:start_link(). %%==================================================================== %% Func: stop/1 %% Returns: any %%==================================================================== -stop (State) -> - ok. - - +stop(State) -> ok. %%==================================================================== %% Func: current_platform/0 %% Returns: string() %%==================================================================== -current_platform () -> - {CurrentPlatform, [$@ | Hostname]} = lists:splitwith(fun(X) -> X =/= $@ end , - atom_to_list (node ())), +current_platform() -> + {CurrentPlatform, [$@ | Hostname]} = lists:splitwith(fun + (X) -> X =/= $@ + end, + atom_to_list(node())), CurrentPlatform ++ "." ++ Hostname. - - %%==================================================================== %% Func: split_agent_identifier/1 %% Returns: {string(), string()} %%==================================================================== -split_agent_identifier (AgentID) -> - case lists:splitwith(fun(X) -> X =/= $@ end , AgentID) of - {LocalID, []} -> - {LocalID, current_platform()}; - {LocalID, [$@ | RealHAP]} -> - {LocalID, RealHAP} +split_agent_identifier(AgentID) -> + case lists:splitwith(fun (X) -> X =/= $@ end, AgentID) + of + {LocalID, []} -> {LocalID, current_platform()}; + {LocalID, [$@ | RealHAP]} -> {LocalID, RealHAP} end. - - %%==================================================================== %% Func: get_argument/1 %% Returns: {ok, [string()]} | error @@ -108,8 +98,6 @@ get_argument(Name) -> _ -> error end. - %%==================================================================== %% Internal functions %%==================================================================== - diff --git a/src/exat_app.erl b/src/exat_app.erl index ac61313..fb84f35 100644 --- a/src/exat_app.erl +++ b/src/exat_app.erl @@ -1,26 +1,26 @@ -% -% exat_app.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (exat_app). +%% +%%exat_app.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(exat_app). %%==================================================================== %% Include files @@ -30,7 +30,7 @@ %% External exports %%==================================================================== --export ([start/0, stop/0]). +-export([start/0, stop/0]). %%==================================================================== %% Internal exports @@ -52,9 +52,10 @@ %%==================================================================== start() -> - application:start(inets, permanent), % FIXME! Use ".rel" + application:start(inets, + permanent), % FIXME! Use ".rel" application:start(exat, permanent), - case init:get_argument ('start') of + case init:get_argument(start) of {ok, [[List]]} -> ApplicationList = string:tokens(List, ","), case ApplicationList of @@ -62,13 +63,14 @@ start() -> _ -> logger:log('AMS', {"Staring Applications: ~s", - [lists:flatten (["{" ++ X ++ "}" || - X <- ApplicationList])]}), + [lists:flatten(["{" ++ X ++ "}" + || X <- ApplicationList])]}), lists:foreach(fun (X) -> - M = list_to_atom (X), + M = list_to_atom(X), io:format("~p~n", [M]), - M:start () - end, ApplicationList) + M:start() + end, + ApplicationList) end; _ -> ok end. @@ -78,9 +80,8 @@ start() -> %% Returns: any %%==================================================================== -stop () -> application:stop (exat). +stop() -> application:stop(exat). %%==================================================================== %% Internal functions %%==================================================================== - diff --git a/src/exat_server.erl b/src/exat_server.erl index ff8c8c3..f70e18c 100644 --- a/src/exat_server.erl +++ b/src/exat_server.erl @@ -1,26 +1,26 @@ -% -% exat_server.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (exat_server). +%% +%%exat_server.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(exat_server). %%==================================================================== %% Include files @@ -30,7 +30,7 @@ %% External exports %%==================================================================== --export ([start_link/1]). +-export([start_link/1]). %%==================================================================== %% Internal exports @@ -52,21 +52,31 @@ %% Description: Starts the MTP worker %%==================================================================== -start_link (Port) -> - io:format ("~n"), - io:format (" __ __ __ _______~n"), - io:format (" \\ \\ / / / \\ |__ __|~n"), - io:format (" ____ \\ \\ / / / /\\ \\ | |~n"), - io:format (" / __ \\ \\ \\/ / | |__| | | |~n"), - io:format (" | ____/ / /\\ \\ | __ | | |~n"), - io:format (" | \\____ / / \\ \\ | | | | | |~n"), - io:format (" \\____/ /_/ \\_\\ |_| |_| |_|~n"), - io:format ("***** *****************~n"), - io:format ("* The erlang eXperimental Agent Tool -- Release 1.3.0-EYE *~n"), - io:format ("***********************************************************~n"), - io:format ("eXAT, an erlang eXperimental Agent Tool~n"), - io:format ("ERESYE, an ERlang Expert SYstem Engine~n"), - io:format ("Copyright (C) 2003-07 Corrado Santoro (csanto@diit.unict.it)~n"), - io:format ("Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)~n"), - mtp:http (Port). - +start_link(Port) -> + io:format("~n"), + io:format(" __ __ __ _______~n"), + io:format(" \\ \\ / / / \\ " + "|__ __|~n"), + io:format(" ____ \\ \\ / / / /\\ \\ " + " | |~n"), + io:format(" / __ \\ \\ \\/ / | |__| | " + " | |~n"), + io:format(" | ____/ / /\\ \\ | __ | " + " | |~n"), + io:format(" | \\____ / / \\ \\ | | | | " + " | |~n"), + io:format(" \\____/ /_/ \\_\\ |_| |_| " + " |_|~n"), + io:format("***** " + " *****************~n"), + io:format("* The erlang eXperimental Agent Tool " + "-- Release 1.3.0-EYE *~n"), + io:format("*********************************************" + "**************~n"), + io:format("eXAT, an erlang eXperimental Agent Tool~n"), + io:format("ERESYE, an ERlang Expert SYstem Engine~n"), + io:format("Copyright (C) 2003-07 Corrado Santoro " + "(csanto@diit.unict.it)~n"), + io:format("Copyright (C) 2005-07 Francesca Gangemi " + "(francesca@erlang-consulting.com)~n"), + mtp:http(Port). diff --git a/src/exat_sup.erl b/src/exat_sup.erl index d396edc..462b391 100644 --- a/src/exat_sup.erl +++ b/src/exat_sup.erl @@ -1,27 +1,28 @@ -% -% exat_sup.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (exat_sup). --behaviour (supervisor). +%% +%%exat_sup.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(exat_sup). + +-behaviour(supervisor). %%==================================================================== %% Include files @@ -31,19 +32,19 @@ %% External exports %%==================================================================== --export ([start_link/0]). +-export([start_link/0]). %%==================================================================== %% Internal exports %%==================================================================== --export ([init/1]). +-export([init/1]). %%==================================================================== %% Macros %%==================================================================== --define (DEFAULT_PORT, 7779). +-define(DEFAULT_PORT, 7779). %%==================================================================== %% Records @@ -57,10 +58,8 @@ %% Description: Starts the supervisor %%==================================================================== -start_link () -> - supervisor:start_link ({ local, ?MODULE }, ?MODULE, []). - - +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). %%==================================================================== %% Internal functions @@ -72,31 +71,23 @@ start_link () -> %% {error, Reason} %%==================================================================== -init ([]) -> - case init:get_argument ('http_port') of - {ok, [[ThePort]]} -> Port = list_to_integer (ThePort); - _ -> Port = ?DEFAULT_PORT +init([]) -> + case init:get_argument(http_port) of + {ok, [[ThePort]]} -> Port = list_to_integer(ThePort); + _ -> Port = (?DEFAULT_PORT) end, - eresye:start (agent_registry), - - MTP = {exat_platform, - {exat_server, start_link, [Port]}, + eresye:start(agent_registry), + MTP = {exat_platform, {exat_server, start_link, [Port]}, permanent, brutal_kill, supervisor, [exat_server]}, - MTP_SENDER = {mtp_sender_service, {gen_server, start_link, [{local, mtp_sender}, mtp, [], []]}, permanent, brutal_kill, worker, [ontology_service]}, - - AMS = {exat_ams, - {ams, start_link, []}, - permanent, brutal_kill, worker, [ams]}, - + AMS = {exat_ams, {ams, start_link, []}, permanent, + brutal_kill, worker, [ams]}, ONTO = {ontology_service, {gen_server, start_link, [{local, ontology_service}, ontology_service, [], []]}, permanent, brutal_kill, worker, [ontology_service]}, - ExatChildSpec = [MTP, MTP_SENDER, ONTO, AMS], - {ok, { {one_for_all, 5, 20}, ExatChildSpec} }. - + {ok, {{one_for_all, 5, 20}, ExatChildSpec}}. diff --git a/src/fipa_ontology_sl_codec.erl b/src/fipa_ontology_sl_codec.erl index 4b47633..a92863c 100644 --- a/src/fipa_ontology_sl_codec.erl +++ b/src/fipa_ontology_sl_codec.erl @@ -1,228 +1,1563 @@ --module (fipa_ontology_sl_codec). --include ("acl.hrl"). --include ("fipa_ontology.hrl"). --export ([encode/1, decode/1]). - -encode(X) when is_record (X,'agent-identifier') -> - ["agent-identifier",{'name', ontology:sl_encode_term (X#'agent-identifier'.'name', string)},{'addresses', ["sequence" | X#'agent-identifier'.'addresses']}]; - -encode(X) when is_record (X,'acl-message') -> - ["acl-message",{'sender', encode (X#'acl-message'.'sender')},{'receiver', ["set" | encode (X#'acl-message'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'acl-message'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'acl-message'.'content', string)},{'language', ontology:sl_encode_term (X#'acl-message'.'language', string)},{'encoding', ontology:sl_encode_term (X#'acl-message'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'acl-message'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'acl-message'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'acl-message'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'acl-message'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'acl-message'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'acl-message'.'reply-by', string)}]; - -encode(X) when is_record (X,'ACCEPT-PROPOSAL') -> - ["ACCEPT-PROPOSAL",{'sender', encode (X#'ACCEPT-PROPOSAL'.'sender')},{'receiver', ["set" | encode (X#'ACCEPT-PROPOSAL'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'content', string)},{'language', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'language', string)},{'encoding', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'ACCEPT-PROPOSAL'.'reply-by', string)}]; - -encode(X) when is_record (X,'AGREE') -> - ["AGREE",{'sender', encode (X#'AGREE'.'sender')},{'receiver', ["set" | encode (X#'AGREE'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'AGREE'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'AGREE'.'content', string)},{'language', ontology:sl_encode_term (X#'AGREE'.'language', string)},{'encoding', ontology:sl_encode_term (X#'AGREE'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'AGREE'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'AGREE'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'AGREE'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'AGREE'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'AGREE'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'AGREE'.'reply-by', string)}]; - -encode(X) when is_record (X,'CANCEL') -> - ["CANCEL",{'sender', encode (X#'CANCEL'.'sender')},{'receiver', ["set" | encode (X#'CANCEL'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'CANCEL'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'CANCEL'.'content', string)},{'language', ontology:sl_encode_term (X#'CANCEL'.'language', string)},{'encoding', ontology:sl_encode_term (X#'CANCEL'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'CANCEL'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'CANCEL'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'CANCEL'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'CANCEL'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'CANCEL'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'CANCEL'.'reply-by', string)}]; - -encode(X) when is_record (X,'CFP') -> - ["CFP",{'sender', encode (X#'CFP'.'sender')},{'receiver', ["set" | encode (X#'CFP'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'CFP'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'CFP'.'content', string)},{'language', ontology:sl_encode_term (X#'CFP'.'language', string)},{'encoding', ontology:sl_encode_term (X#'CFP'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'CFP'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'CFP'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'CFP'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'CFP'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'CFP'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'CFP'.'reply-by', string)}]; - -encode(X) when is_record (X,'CONFIRM') -> - ["CONFIRM",{'sender', encode (X#'CONFIRM'.'sender')},{'receiver', ["set" | encode (X#'CONFIRM'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'CONFIRM'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'CONFIRM'.'content', string)},{'language', ontology:sl_encode_term (X#'CONFIRM'.'language', string)},{'encoding', ontology:sl_encode_term (X#'CONFIRM'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'CONFIRM'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'CONFIRM'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'CONFIRM'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'CONFIRM'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'CONFIRM'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'CONFIRM'.'reply-by', string)}]; - -encode(X) when is_record (X,'DISCONFIRM') -> - ["DISCONFIRM",{'sender', encode (X#'DISCONFIRM'.'sender')},{'receiver', ["set" | encode (X#'DISCONFIRM'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'DISCONFIRM'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'DISCONFIRM'.'content', string)},{'language', ontology:sl_encode_term (X#'DISCONFIRM'.'language', string)},{'encoding', ontology:sl_encode_term (X#'DISCONFIRM'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'DISCONFIRM'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'DISCONFIRM'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'DISCONFIRM'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'DISCONFIRM'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'DISCONFIRM'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'DISCONFIRM'.'reply-by', string)}]; - -encode(X) when is_record (X,'INFORM') -> - ["INFORM",{'sender', encode (X#'INFORM'.'sender')},{'receiver', ["set" | encode (X#'INFORM'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'INFORM'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'INFORM'.'content', string)},{'language', ontology:sl_encode_term (X#'INFORM'.'language', string)},{'encoding', ontology:sl_encode_term (X#'INFORM'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'INFORM'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'INFORM'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'INFORM'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'INFORM'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'INFORM'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'INFORM'.'reply-by', string)}]; - -encode(X) when is_record (X,'INFORM-IF') -> - ["INFORM-IF",{'sender', encode (X#'INFORM-IF'.'sender')},{'receiver', ["set" | encode (X#'INFORM-IF'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'INFORM-IF'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'INFORM-IF'.'content', string)},{'language', ontology:sl_encode_term (X#'INFORM-IF'.'language', string)},{'encoding', ontology:sl_encode_term (X#'INFORM-IF'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'INFORM-IF'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'INFORM-IF'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'INFORM-IF'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'INFORM-IF'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'INFORM-IF'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'INFORM-IF'.'reply-by', string)}]; - -encode(X) when is_record (X,'INFORM-REF') -> - ["INFORM-REF",{'sender', encode (X#'INFORM-REF'.'sender')},{'receiver', ["set" | encode (X#'INFORM-REF'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'INFORM-REF'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'INFORM-REF'.'content', string)},{'language', ontology:sl_encode_term (X#'INFORM-REF'.'language', string)},{'encoding', ontology:sl_encode_term (X#'INFORM-REF'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'INFORM-REF'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'INFORM-REF'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'INFORM-REF'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'INFORM-REF'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'INFORM-REF'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'INFORM-REF'.'reply-by', string)}]; - -encode(X) when is_record (X,'NOT-UNDERSTOOD') -> - ["NOT-UNDERSTOOD",{'sender', encode (X#'NOT-UNDERSTOOD'.'sender')},{'receiver', ["set" | encode (X#'NOT-UNDERSTOOD'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'content', string)},{'language', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'language', string)},{'encoding', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'NOT-UNDERSTOOD'.'reply-by', string)}]; - -encode(X) when is_record (X,'PROPAGATE') -> - ["PROPAGATE",{'sender', encode (X#'PROPAGATE'.'sender')},{'receiver', ["set" | encode (X#'PROPAGATE'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'PROPAGATE'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'PROPAGATE'.'content', string)},{'language', ontology:sl_encode_term (X#'PROPAGATE'.'language', string)},{'encoding', ontology:sl_encode_term (X#'PROPAGATE'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'PROPAGATE'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'PROPAGATE'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'PROPAGATE'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'PROPAGATE'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'PROPAGATE'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'PROPAGATE'.'reply-by', string)}]; - -encode(X) when is_record (X,'PROPOSE') -> - ["PROPOSE",{'sender', encode (X#'PROPOSE'.'sender')},{'receiver', ["set" | encode (X#'PROPOSE'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'PROPOSE'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'PROPOSE'.'content', string)},{'language', ontology:sl_encode_term (X#'PROPOSE'.'language', string)},{'encoding', ontology:sl_encode_term (X#'PROPOSE'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'PROPOSE'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'PROPOSE'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'PROPOSE'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'PROPOSE'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'PROPOSE'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'PROPOSE'.'reply-by', string)}]; - -encode(X) when is_record (X,'PROXY') -> - ["PROXY",{'sender', encode (X#'PROXY'.'sender')},{'receiver', ["set" | encode (X#'PROXY'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'PROXY'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'PROXY'.'content', string)},{'language', ontology:sl_encode_term (X#'PROXY'.'language', string)},{'encoding', ontology:sl_encode_term (X#'PROXY'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'PROXY'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'PROXY'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'PROXY'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'PROXY'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'PROXY'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'PROXY'.'reply-by', string)}]; - -encode(X) when is_record (X,'QUERY-IF') -> - ["QUERY-IF",{'sender', encode (X#'QUERY-IF'.'sender')},{'receiver', ["set" | encode (X#'QUERY-IF'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'QUERY-IF'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'QUERY-IF'.'content', string)},{'language', ontology:sl_encode_term (X#'QUERY-IF'.'language', string)},{'encoding', ontology:sl_encode_term (X#'QUERY-IF'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'QUERY-IF'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'QUERY-IF'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'QUERY-IF'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'QUERY-IF'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'QUERY-IF'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'QUERY-IF'.'reply-by', string)}]; - -encode(X) when is_record (X,'QUERY-REF') -> - ["QUERY-REF",{'sender', encode (X#'QUERY-REF'.'sender')},{'receiver', ["set" | encode (X#'QUERY-REF'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'QUERY-REF'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'QUERY-REF'.'content', string)},{'language', ontology:sl_encode_term (X#'QUERY-REF'.'language', string)},{'encoding', ontology:sl_encode_term (X#'QUERY-REF'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'QUERY-REF'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'QUERY-REF'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'QUERY-REF'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'QUERY-REF'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'QUERY-REF'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'QUERY-REF'.'reply-by', string)}]; - -encode(X) when is_record (X,'REFUSE') -> - ["REFUSE",{'sender', encode (X#'REFUSE'.'sender')},{'receiver', ["set" | encode (X#'REFUSE'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'REFUSE'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'REFUSE'.'content', string)},{'language', ontology:sl_encode_term (X#'REFUSE'.'language', string)},{'encoding', ontology:sl_encode_term (X#'REFUSE'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'REFUSE'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'REFUSE'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'REFUSE'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'REFUSE'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'REFUSE'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'REFUSE'.'reply-by', string)}]; - -encode(X) when is_record (X,'REJECT-PROPOSAL') -> - ["REJECT-PROPOSAL",{'sender', encode (X#'REJECT-PROPOSAL'.'sender')},{'receiver', ["set" | encode (X#'REJECT-PROPOSAL'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'content', string)},{'language', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'language', string)},{'encoding', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'REJECT-PROPOSAL'.'reply-by', string)}]; - -encode(X) when is_record (X,'REQUEST') -> - ["REQUEST",{'sender', encode (X#'REQUEST'.'sender')},{'receiver', ["set" | encode (X#'REQUEST'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'REQUEST'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'REQUEST'.'content', string)},{'language', ontology:sl_encode_term (X#'REQUEST'.'language', string)},{'encoding', ontology:sl_encode_term (X#'REQUEST'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'REQUEST'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'REQUEST'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'REQUEST'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'REQUEST'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'REQUEST'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'REQUEST'.'reply-by', string)}]; - -encode(X) when is_record (X,'REQUEST-WHEN') -> - ["REQUEST-WHEN",{'sender', encode (X#'REQUEST-WHEN'.'sender')},{'receiver', ["set" | encode (X#'REQUEST-WHEN'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'REQUEST-WHEN'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'REQUEST-WHEN'.'content', string)},{'language', ontology:sl_encode_term (X#'REQUEST-WHEN'.'language', string)},{'encoding', ontology:sl_encode_term (X#'REQUEST-WHEN'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'REQUEST-WHEN'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'REQUEST-WHEN'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'REQUEST-WHEN'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'REQUEST-WHEN'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'REQUEST-WHEN'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'REQUEST-WHEN'.'reply-by', string)}]; - -encode(X) when is_record (X,'REQUEST-WHENEVER') -> - ["REQUEST-WHENEVER",{'sender', encode (X#'REQUEST-WHENEVER'.'sender')},{'receiver', ["set" | encode (X#'REQUEST-WHENEVER'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'content', string)},{'language', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'language', string)},{'encoding', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'REQUEST-WHENEVER'.'reply-by', string)}]; - -encode(X) when is_record (X,'SUBSCRIBE') -> - ["SUBSCRIBE",{'sender', encode (X#'SUBSCRIBE'.'sender')},{'receiver', ["set" | encode (X#'SUBSCRIBE'.'receiver') ]},{'reply-to', ontology:sl_encode_term (X#'SUBSCRIBE'.'reply-to', string)},{'content', ontology:sl_encode_term (X#'SUBSCRIBE'.'content', string)},{'language', ontology:sl_encode_term (X#'SUBSCRIBE'.'language', string)},{'encoding', ontology:sl_encode_term (X#'SUBSCRIBE'.'encoding', string)},{'ontology', ontology:sl_encode_term (X#'SUBSCRIBE'.'ontology', string)},{'protocol', ontology:sl_encode_term (X#'SUBSCRIBE'.'protocol', string)},{'conversation-id', ontology:sl_encode_term (X#'SUBSCRIBE'.'conversation-id', string)},{'reply-with', ontology:sl_encode_term (X#'SUBSCRIBE'.'reply-with', string)},{'in-reply-to', ontology:sl_encode_term (X#'SUBSCRIBE'.'in-reply-to', string)},{'reply-by', ontology:sl_encode_term (X#'SUBSCRIBE'.'reply-by', string)}]; - -encode(X) when is_record (X,'action') -> - ["action",encode (X#'action'.'0'),encode (X#'action'.'1')]; - -encode(X) when is_record (X,'action-specification') -> - ["action-specification"]; - -encode(X) when is_record (X,'get-description') -> - ["get-description"]; - -encode(X) when is_record (X,'search') -> - ["search",encode (X#'search'.'0'),encode (X#'search'.'1')]; - -encode(X) when is_record (X,'AMS-OR-DF-agent-description') -> - ["AMS-OR-DF-agent-description"]; - -encode(X) when is_record (X,'ams-agent-description') -> - ["ams-agent-description",{'name', encode (X#'ams-agent-description'.'name')},{'ownership', ontology:sl_encode_term (X#'ams-agent-description'.'ownership', string)},{'state', ontology:sl_encode_term (X#'ams-agent-description'.'state', string)}]; - -encode(X) when is_record (X,'search-constraints') -> - ["search-constraints",{'max-depth', ontology:sl_encode_term (X#'search-constraints'.'max-depth', integer)},{'max-results', ontology:sl_encode_term (X#'search-constraints'.'max-results', integer)},{'search-id', ontology:sl_encode_term (X#'search-constraints'.'search-id', string)}]; - -encode(X) when is_record (X,'result') -> - ["result",encode (X#'result'.'0'),["sequence" | encode (X#'result'.'1')]]; - -encode(X) when is_record (X,'result-specification') -> - ["result-specification"]; - -encode(X) when is_record (X,'ap-service') -> - ["ap-service",{'name', ontology:sl_encode_term (X#'ap-service'.'name', string)},{'type', ontology:sl_encode_term (X#'ap-service'.'type', string)},{'addresses', ["sequence" | X#'ap-service'.'addresses']}]; - -encode(X) when is_record (X,'ap-description') -> - ["ap-description",{'name', ontology:sl_encode_term (X#'ap-description'.'name', string)},{'ap-services', ["sequence" | encode (X#'ap-description'.'ap-services')]}]; - -encode(X) when is_list (X) -> [encode (Y) || Y <- X]; - +-module(fipa_ontology_sl_codec). + +-include("acl.hrl"). + +-include("fipa_ontology.hrl"). + +-export([decode/1, encode/1]). + +encode(X) when is_record(X, 'agent-identifier') -> + ["agent-identifier", + {name, + ontology:sl_encode_term(X#'agent-identifier'.name, + string)}, + {addresses, + ["sequence" | X#'agent-identifier'.addresses]}]; +encode(X) when is_record(X, 'acl-message') -> + ["acl-message", + {sender, encode(X#'acl-message'.sender)}, + {receiver, ["set" | encode(X#'acl-message'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'acl-message'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'acl-message'.content, + string)}, + {language, + ontology:sl_encode_term(X#'acl-message'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'acl-message'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'acl-message'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'acl-message'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'acl-message'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'acl-message'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'acl-message'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'acl-message'.'reply-by', + string)}]; +encode(X) when is_record(X, 'ACCEPT-PROPOSAL') -> + ["ACCEPT-PROPOSAL", + {sender, encode(X#'ACCEPT-PROPOSAL'.sender)}, + {receiver, + ["set" | encode(X#'ACCEPT-PROPOSAL'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.content, + string)}, + {language, + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'ACCEPT-PROPOSAL'.'reply-by', + string)}]; +encode(X) when is_record(X, 'AGREE') -> + ["AGREE", {sender, encode(X#'AGREE'.sender)}, + {receiver, ["set" | encode(X#'AGREE'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'AGREE'.'reply-to', string)}, + {content, + ontology:sl_encode_term(X#'AGREE'.content, string)}, + {language, + ontology:sl_encode_term(X#'AGREE'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'AGREE'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'AGREE'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'AGREE'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'AGREE'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'AGREE'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'AGREE'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'AGREE'.'reply-by', string)}]; +encode(X) when is_record(X, 'CANCEL') -> + ["CANCEL", {sender, encode(X#'CANCEL'.sender)}, + {receiver, ["set" | encode(X#'CANCEL'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'CANCEL'.'reply-to', string)}, + {content, + ontology:sl_encode_term(X#'CANCEL'.content, string)}, + {language, + ontology:sl_encode_term(X#'CANCEL'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'CANCEL'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'CANCEL'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'CANCEL'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'CANCEL'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'CANCEL'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'CANCEL'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'CANCEL'.'reply-by', + string)}]; +encode(X) when is_record(X, 'CFP') -> + ["CFP", {sender, encode(X#'CFP'.sender)}, + {receiver, ["set" | encode(X#'CFP'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'CFP'.'reply-to', string)}, + {content, + ontology:sl_encode_term(X#'CFP'.content, string)}, + {language, + ontology:sl_encode_term(X#'CFP'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'CFP'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'CFP'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'CFP'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'CFP'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'CFP'.'reply-with', string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'CFP'.'in-reply-to', string)}, + {'reply-by', + ontology:sl_encode_term(X#'CFP'.'reply-by', string)}]; +encode(X) when is_record(X, 'CONFIRM') -> + ["CONFIRM", {sender, encode(X#'CONFIRM'.sender)}, + {receiver, ["set" | encode(X#'CONFIRM'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'CONFIRM'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'CONFIRM'.content, string)}, + {language, + ontology:sl_encode_term(X#'CONFIRM'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'CONFIRM'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'CONFIRM'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'CONFIRM'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'CONFIRM'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'CONFIRM'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'CONFIRM'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'CONFIRM'.'reply-by', + string)}]; +encode(X) when is_record(X, 'DISCONFIRM') -> + ["DISCONFIRM", {sender, encode(X#'DISCONFIRM'.sender)}, + {receiver, ["set" | encode(X#'DISCONFIRM'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'DISCONFIRM'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'DISCONFIRM'.content, + string)}, + {language, + ontology:sl_encode_term(X#'DISCONFIRM'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'DISCONFIRM'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'DISCONFIRM'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'DISCONFIRM'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'DISCONFIRM'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'DISCONFIRM'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'DISCONFIRM'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'DISCONFIRM'.'reply-by', + string)}]; +encode(X) when is_record(X, 'INFORM') -> + ["INFORM", {sender, encode(X#'INFORM'.sender)}, + {receiver, ["set" | encode(X#'INFORM'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'INFORM'.'reply-to', string)}, + {content, + ontology:sl_encode_term(X#'INFORM'.content, string)}, + {language, + ontology:sl_encode_term(X#'INFORM'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'INFORM'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'INFORM'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'INFORM'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'INFORM'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'INFORM'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'INFORM'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'INFORM'.'reply-by', + string)}]; +encode(X) when is_record(X, 'INFORM-IF') -> + ["INFORM-IF", {sender, encode(X#'INFORM-IF'.sender)}, + {receiver, ["set" | encode(X#'INFORM-IF'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'INFORM-IF'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'INFORM-IF'.content, string)}, + {language, + ontology:sl_encode_term(X#'INFORM-IF'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'INFORM-IF'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'INFORM-IF'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'INFORM-IF'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'INFORM-IF'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'INFORM-IF'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'INFORM-IF'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'INFORM-IF'.'reply-by', + string)}]; +encode(X) when is_record(X, 'INFORM-REF') -> + ["INFORM-REF", {sender, encode(X#'INFORM-REF'.sender)}, + {receiver, ["set" | encode(X#'INFORM-REF'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'INFORM-REF'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'INFORM-REF'.content, + string)}, + {language, + ontology:sl_encode_term(X#'INFORM-REF'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'INFORM-REF'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'INFORM-REF'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'INFORM-REF'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'INFORM-REF'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'INFORM-REF'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'INFORM-REF'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'INFORM-REF'.'reply-by', + string)}]; +encode(X) when is_record(X, 'NOT-UNDERSTOOD') -> + ["NOT-UNDERSTOOD", + {sender, encode(X#'NOT-UNDERSTOOD'.sender)}, + {receiver, + ["set" | encode(X#'NOT-UNDERSTOOD'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.content, + string)}, + {language, + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'NOT-UNDERSTOOD'.'reply-by', + string)}]; +encode(X) when is_record(X, 'PROPAGATE') -> + ["PROPAGATE", {sender, encode(X#'PROPAGATE'.sender)}, + {receiver, ["set" | encode(X#'PROPAGATE'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'PROPAGATE'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'PROPAGATE'.content, string)}, + {language, + ontology:sl_encode_term(X#'PROPAGATE'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'PROPAGATE'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'PROPAGATE'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'PROPAGATE'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'PROPAGATE'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'PROPAGATE'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'PROPAGATE'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'PROPAGATE'.'reply-by', + string)}]; +encode(X) when is_record(X, 'PROPOSE') -> + ["PROPOSE", {sender, encode(X#'PROPOSE'.sender)}, + {receiver, ["set" | encode(X#'PROPOSE'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'PROPOSE'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'PROPOSE'.content, string)}, + {language, + ontology:sl_encode_term(X#'PROPOSE'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'PROPOSE'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'PROPOSE'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'PROPOSE'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'PROPOSE'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'PROPOSE'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'PROPOSE'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'PROPOSE'.'reply-by', + string)}]; +encode(X) when is_record(X, 'PROXY') -> + ["PROXY", {sender, encode(X#'PROXY'.sender)}, + {receiver, ["set" | encode(X#'PROXY'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'PROXY'.'reply-to', string)}, + {content, + ontology:sl_encode_term(X#'PROXY'.content, string)}, + {language, + ontology:sl_encode_term(X#'PROXY'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'PROXY'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'PROXY'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'PROXY'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'PROXY'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'PROXY'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'PROXY'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'PROXY'.'reply-by', string)}]; +encode(X) when is_record(X, 'QUERY-IF') -> + ["QUERY-IF", {sender, encode(X#'QUERY-IF'.sender)}, + {receiver, ["set" | encode(X#'QUERY-IF'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'QUERY-IF'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'QUERY-IF'.content, string)}, + {language, + ontology:sl_encode_term(X#'QUERY-IF'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'QUERY-IF'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'QUERY-IF'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'QUERY-IF'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'QUERY-IF'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'QUERY-IF'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'QUERY-IF'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'QUERY-IF'.'reply-by', + string)}]; +encode(X) when is_record(X, 'QUERY-REF') -> + ["QUERY-REF", {sender, encode(X#'QUERY-REF'.sender)}, + {receiver, ["set" | encode(X#'QUERY-REF'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'QUERY-REF'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'QUERY-REF'.content, string)}, + {language, + ontology:sl_encode_term(X#'QUERY-REF'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'QUERY-REF'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'QUERY-REF'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'QUERY-REF'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'QUERY-REF'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'QUERY-REF'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'QUERY-REF'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'QUERY-REF'.'reply-by', + string)}]; +encode(X) when is_record(X, 'REFUSE') -> + ["REFUSE", {sender, encode(X#'REFUSE'.sender)}, + {receiver, ["set" | encode(X#'REFUSE'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'REFUSE'.'reply-to', string)}, + {content, + ontology:sl_encode_term(X#'REFUSE'.content, string)}, + {language, + ontology:sl_encode_term(X#'REFUSE'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'REFUSE'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'REFUSE'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'REFUSE'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'REFUSE'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'REFUSE'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'REFUSE'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'REFUSE'.'reply-by', + string)}]; +encode(X) when is_record(X, 'REJECT-PROPOSAL') -> + ["REJECT-PROPOSAL", + {sender, encode(X#'REJECT-PROPOSAL'.sender)}, + {receiver, + ["set" | encode(X#'REJECT-PROPOSAL'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.content, + string)}, + {language, + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'REJECT-PROPOSAL'.'reply-by', + string)}]; +encode(X) when is_record(X, 'REQUEST') -> + ["REQUEST", {sender, encode(X#'REQUEST'.sender)}, + {receiver, ["set" | encode(X#'REQUEST'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'REQUEST'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'REQUEST'.content, string)}, + {language, + ontology:sl_encode_term(X#'REQUEST'.language, string)}, + {encoding, + ontology:sl_encode_term(X#'REQUEST'.encoding, string)}, + {ontology, + ontology:sl_encode_term(X#'REQUEST'.ontology, string)}, + {protocol, + ontology:sl_encode_term(X#'REQUEST'.protocol, string)}, + {'conversation-id', + ontology:sl_encode_term(X#'REQUEST'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'REQUEST'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'REQUEST'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'REQUEST'.'reply-by', + string)}]; +encode(X) when is_record(X, 'REQUEST-WHEN') -> + ["REQUEST-WHEN", + {sender, encode(X#'REQUEST-WHEN'.sender)}, + {receiver, ["set" | encode(X#'REQUEST-WHEN'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'REQUEST-WHEN'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'REQUEST-WHEN'.content, + string)}, + {language, + ontology:sl_encode_term(X#'REQUEST-WHEN'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'REQUEST-WHEN'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'REQUEST-WHEN'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'REQUEST-WHEN'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'REQUEST-WHEN'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'REQUEST-WHEN'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'REQUEST-WHEN'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'REQUEST-WHEN'.'reply-by', + string)}]; +encode(X) when is_record(X, 'REQUEST-WHENEVER') -> + ["REQUEST-WHENEVER", + {sender, encode(X#'REQUEST-WHENEVER'.sender)}, + {receiver, + ["set" | encode(X#'REQUEST-WHENEVER'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.content, + string)}, + {language, + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'REQUEST-WHENEVER'.'reply-by', + string)}]; +encode(X) when is_record(X, 'SUBSCRIBE') -> + ["SUBSCRIBE", {sender, encode(X#'SUBSCRIBE'.sender)}, + {receiver, ["set" | encode(X#'SUBSCRIBE'.receiver)]}, + {'reply-to', + ontology:sl_encode_term(X#'SUBSCRIBE'.'reply-to', + string)}, + {content, + ontology:sl_encode_term(X#'SUBSCRIBE'.content, string)}, + {language, + ontology:sl_encode_term(X#'SUBSCRIBE'.language, + string)}, + {encoding, + ontology:sl_encode_term(X#'SUBSCRIBE'.encoding, + string)}, + {ontology, + ontology:sl_encode_term(X#'SUBSCRIBE'.ontology, + string)}, + {protocol, + ontology:sl_encode_term(X#'SUBSCRIBE'.protocol, + string)}, + {'conversation-id', + ontology:sl_encode_term(X#'SUBSCRIBE'.'conversation-id', + string)}, + {'reply-with', + ontology:sl_encode_term(X#'SUBSCRIBE'.'reply-with', + string)}, + {'in-reply-to', + ontology:sl_encode_term(X#'SUBSCRIBE'.'in-reply-to', + string)}, + {'reply-by', + ontology:sl_encode_term(X#'SUBSCRIBE'.'reply-by', + string)}]; +encode(X) when is_record(X, action) -> + ["action", encode(X#action.'0'), encode(X#action.'1')]; +encode(X) when is_record(X, 'action-specification') -> + ["action-specification"]; +encode(X) when is_record(X, 'get-description') -> + ["get-description"]; +encode(X) when is_record(X, search) -> + ["search", encode(X#search.'0'), encode(X#search.'1')]; +encode(X) + when is_record(X, 'AMS-OR-DF-agent-description') -> + ["AMS-OR-DF-agent-description"]; +encode(X) when is_record(X, 'ams-agent-description') -> + ["ams-agent-description", + {name, encode(X#'ams-agent-description'.name)}, + {ownership, + ontology:sl_encode_term(X#'ams-agent-description'.ownership, + string)}, + {state, + ontology:sl_encode_term(X#'ams-agent-description'.state, + string)}]; +encode(X) when is_record(X, 'search-constraints') -> + ["search-constraints", + {'max-depth', + ontology:sl_encode_term(X#'search-constraints'.'max-depth', + integer)}, + {'max-results', + ontology:sl_encode_term(X#'search-constraints'.'max-results', + integer)}, + {'search-id', + ontology:sl_encode_term(X#'search-constraints'.'search-id', + string)}]; +encode(X) when is_record(X, result) -> + ["result", encode(X#result.'0'), + ["sequence" | encode(X#result.'1')]]; +encode(X) when is_record(X, 'result-specification') -> + ["result-specification"]; +encode(X) when is_record(X, 'ap-service') -> + ["ap-service", + {name, + ontology:sl_encode_term(X#'ap-service'.name, string)}, + {type, + ontology:sl_encode_term(X#'ap-service'.type, string)}, + {addresses, ["sequence" | X#'ap-service'.addresses]}]; +encode(X) when is_record(X, 'ap-description') -> + ["ap-description", + {name, + ontology:sl_encode_term(X#'ap-description'.name, + string)}, + {'ap-services', + ["sequence" + | encode(X#'ap-description'.'ap-services')]}]; +encode(X) when is_list(X) -> [encode(Y) || Y <- X]; encode(nil) -> nil; - -encode(X) -> exit ({ontology_error,X}). +encode(X) -> exit({ontology_error, X}). decode(["agent-identifier" | T]) -> - #'agent-identifier'{'name' = ontology:sl_decode_term (sl:get_slot ('name', T), string),'addresses' = sequence_of (sl:get_slot ('addresses', T))}; - + #'agent-identifier'{name = + ontology:sl_decode_term(sl:get_slot(name, T), + string), + addresses = sequence_of(sl:get_slot(addresses, T))}; decode(["acl-message" | T]) -> - #'acl-message'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'acl-message'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["ACCEPT-PROPOSAL" | T]) -> - #'ACCEPT-PROPOSAL'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'ACCEPT-PROPOSAL'{sender = + decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', + T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["AGREE" | T]) -> - #'AGREE'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'AGREE'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["CANCEL" | T]) -> - #'CANCEL'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'CANCEL'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["CFP" | T]) -> - #'CFP'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'CFP'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["CONFIRM" | T]) -> - #'CONFIRM'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'CONFIRM'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["DISCONFIRM" | T]) -> - #'DISCONFIRM'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'DISCONFIRM'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["INFORM" | T]) -> - #'INFORM'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'INFORM'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["INFORM-IF" | T]) -> - #'INFORM-IF'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'INFORM-IF'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["INFORM-REF" | T]) -> - #'INFORM-REF'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'INFORM-REF'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["NOT-UNDERSTOOD" | T]) -> - #'NOT-UNDERSTOOD'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'NOT-UNDERSTOOD'{sender = + decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["PROPAGATE" | T]) -> - #'PROPAGATE'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'PROPAGATE'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["PROPOSE" | T]) -> - #'PROPOSE'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'PROPOSE'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["PROXY" | T]) -> - #'PROXY'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'PROXY'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["QUERY-IF" | T]) -> - #'QUERY-IF'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'QUERY-IF'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["QUERY-REF" | T]) -> - #'QUERY-REF'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'QUERY-REF'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["REFUSE" | T]) -> - #'REFUSE'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'REFUSE'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["REJECT-PROPOSAL" | T]) -> - #'REJECT-PROPOSAL'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'REJECT-PROPOSAL'{sender = + decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', + T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["REQUEST" | T]) -> - #'REQUEST'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'REQUEST'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["REQUEST-WHEN" | T]) -> - #'REQUEST-WHEN'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'REQUEST-WHEN'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["REQUEST-WHENEVER" | T]) -> - #'REQUEST-WHENEVER'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'REQUEST-WHENEVER'{sender = + decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', + T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', + T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["SUBSCRIBE" | T]) -> - #'SUBSCRIBE'{'sender' = decode (sl:get_slot ('sender', T)),'receiver' = decode (set_of (sl:get_slot ('receiver', T))),'reply-to' = ontology:sl_decode_term (sl:get_slot ('reply-to', T), string),'content' = ontology:sl_decode_term (sl:get_slot ('content', T), string),'language' = ontology:sl_decode_term (sl:get_slot ('language', T), string),'encoding' = ontology:sl_decode_term (sl:get_slot ('encoding', T), string),'ontology' = ontology:sl_decode_term (sl:get_slot ('ontology', T), string),'protocol' = ontology:sl_decode_term (sl:get_slot ('protocol', T), string),'conversation-id' = ontology:sl_decode_term (sl:get_slot ('conversation-id', T), string),'reply-with' = ontology:sl_decode_term (sl:get_slot ('reply-with', T), string),'in-reply-to' = ontology:sl_decode_term (sl:get_slot ('in-reply-to', T), string),'reply-by' = ontology:sl_decode_term (sl:get_slot ('reply-by', T), string)}; - + #'SUBSCRIBE'{sender = decode(sl:get_slot(sender, T)), + receiver = decode(set_of(sl:get_slot(receiver, T))), + 'reply-to' = + ontology:sl_decode_term(sl:get_slot('reply-to', T), + string), + content = + ontology:sl_decode_term(sl:get_slot(content, T), + string), + language = + ontology:sl_decode_term(sl:get_slot(language, T), + string), + encoding = + ontology:sl_decode_term(sl:get_slot(encoding, T), + string), + ontology = + ontology:sl_decode_term(sl:get_slot(ontology, T), + string), + protocol = + ontology:sl_decode_term(sl:get_slot(protocol, T), + string), + 'conversation-id' = + ontology:sl_decode_term(sl:get_slot('conversation-id', + T), + string), + 'reply-with' = + ontology:sl_decode_term(sl:get_slot('reply-with', T), + string), + 'in-reply-to' = + ontology:sl_decode_term(sl:get_slot('in-reply-to', T), + string), + 'reply-by' = + ontology:sl_decode_term(sl:get_slot('reply-by', T), + string)}; decode(["action" | T]) -> - #'action'{'0' = decode (lists:nth (1, T)),'1' = decode (lists:nth (2, T))}; - + #action{'0' = decode(lists:nth(1, T)), + '1' = decode(lists:nth(2, T))}; decode(["action-specification" | T]) -> - #'action-specification'{}; - -decode(["get-description" | T]) -> - #'get-description'{}; - + #'action-specification'{}; +decode(["get-description" | T]) -> #'get-description'{}; decode(["search" | T]) -> - #'search'{'0' = decode (lists:nth (1, T)),'1' = decode (lists:nth (2, T))}; - + #search{'0' = decode(lists:nth(1, T)), + '1' = decode(lists:nth(2, T))}; decode(["AMS-OR-DF-agent-description" | T]) -> - #'AMS-OR-DF-agent-description'{}; - + #'AMS-OR-DF-agent-description'{}; decode(["ams-agent-description" | T]) -> - #'ams-agent-description'{'name' = decode (sl:get_slot ('name', T)),'ownership' = ontology:sl_decode_term (sl:get_slot ('ownership', T), string),'state' = ontology:sl_decode_term (sl:get_slot ('state', T), string)}; - + #'ams-agent-description'{name = + decode(sl:get_slot(name, T)), + ownership = + ontology:sl_decode_term(sl:get_slot(ownership, + T), + string), + state = + ontology:sl_decode_term(sl:get_slot(state, T), + string)}; decode(["search-constraints" | T]) -> - #'search-constraints'{'max-depth' = ontology:sl_decode_term (sl:get_slot ('max-depth', T), integer),'max-results' = ontology:sl_decode_term (sl:get_slot ('max-results', T), integer),'search-id' = ontology:sl_decode_term (sl:get_slot ('search-id', T), string)}; - + #'search-constraints'{'max-depth' = + ontology:sl_decode_term(sl:get_slot('max-depth', + T), + integer), + 'max-results' = + ontology:sl_decode_term(sl:get_slot('max-results', + T), + integer), + 'search-id' = + ontology:sl_decode_term(sl:get_slot('search-id', + T), + string)}; decode(["result" | T]) -> - #'result'{'0' = decode (lists:nth (1, T)),'1' = decode (lists:nth (2, T))}; - + #result{'0' = decode(lists:nth(1, T)), + '1' = decode(lists:nth(2, T))}; decode(["result-specification" | T]) -> - #'result-specification'{}; - + #'result-specification'{}; decode(["ap-service" | T]) -> - #'ap-service'{'name' = ontology:sl_decode_term (sl:get_slot ('name', T), string),'type' = ontology:sl_decode_term (sl:get_slot ('type', T), string),'addresses' = sequence_of (sl:get_slot ('addresses', T))}; - + #'ap-service'{name = + ontology:sl_decode_term(sl:get_slot(name, T), string), + type = + ontology:sl_decode_term(sl:get_slot(type, T), string), + addresses = sequence_of(sl:get_slot(addresses, T))}; decode(["ap-description" | T]) -> - #'ap-description'{'name' = ontology:sl_decode_term (sl:get_slot ('name', T), string),'ap-services' = decode (sequence_of (sl:get_slot ('ap-services', T)))}; - + #'ap-description'{name = + ontology:sl_decode_term(sl:get_slot(name, T), string), + 'ap-services' = + decode(sequence_of(sl:get_slot('ap-services', T)))}; decode(nil) -> nil; +decode(X) -> + case sl:isList(X) of + true -> [decode(Y) || Y <- X]; + _ -> X + end. -decode(X) -> - case sl:isList (X) of - true -> [decode (Y) || Y <- X]; - _ -> X - end. - -set_of ([ "set" | L]) -> decode (L); -set_of ([ "set", L]) -> decode (L). - -sequence_of ([ "sequence" | L]) -> decode (L). +set_of(["set" | L]) -> decode(L); +set_of(["set", L]) -> decode(L). +sequence_of(["sequence" | L]) -> decode(L). diff --git a/src/fipa_semantics_simple.erl b/src/fipa_semantics_simple.erl index 7fe8209..e6c7586 100644 --- a/src/fipa_semantics_simple.erl +++ b/src/fipa_semantics_simple.erl @@ -1,38 +1,40 @@ -% -% fipa_semantics_simple.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (fipa_semantics_simple). --export ([extends/0, is_feasible/4, rational_effect/4]). --include ("acl.hrl"). +%% +%%fipa_semantics_simple.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(fipa_semantics_simple). -extends () -> semantics. +-export([extends/0, is_feasible/4, rational_effect/4]). -is_feasible (Self, Agent, KB, - AclMessage = #aclmessage { speechact = 'INFORM' }) -> - %%io:format ("[Agent: ~w] Doing FP test on ~w\n", [Agent, AclMessage]), - true. +-include("acl.hrl"). -rational_effect (Self, Agent, KB, - AclMessage = #aclmessage { speechact = 'INFORM' }) -> - %%io:format ("[Agent: ~w] Performing RE on ~p\n", [Agent, AclMessage]), - eresye:assert (KB, AclMessage#aclmessage.content), - true. +extends() -> semantics. + +is_feasible(Self, Agent, KB, + AclMessage = #aclmessage{speechact = 'INFORM'}) -> + %%io:format ("[Agent: ~w] Doing FP test on ~w\n", [Agent, AclMessage]), + true. + +rational_effect(Self, Agent, KB, + AclMessage = #aclmessage{speechact = 'INFORM'}) -> + %%io:format ("[Agent: ~w] Performing RE on ~p\n", [Agent, AclMessage]), + eresye:assert(KB, AclMessage#aclmessage.content), + true. diff --git a/src/http_server.erl b/src/http_server.erl index 3e7aebe..2d37184 100644 --- a/src/http_server.erl +++ b/src/http_server.erl @@ -1,82 +1,59 @@ -% -% http_server.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (http_server). - --export ([decode/1, - media_type_decode/1, - terms_to_string/1, - terms_to_atom/1, - terms_to_tuple/1, - terms_to_integer/1, - trim/1, - tokenize/1]). - --author ('csanto@diit.unict.it'). - --define (CRLF, "\r\n"). - - - - -tokenize ([]) -> [{'$end',1}]; -tokenize ([H|T]) -> [ {list_to_atom ([H]),1} | tokenize (T) ]. - - -terms_to_string ([]) -> []; -terms_to_string ([H|T]) -> - [ L | _ ] = atom_to_list (element (1, H)), - [ L | terms_to_string (T) ]. - -terms_to_atom (X) -> - list_to_atom (terms_to_string (X)). - -terms_to_tuple (X) -> - list_to_tuple (terms_to_string (X)). - -terms_to_integer (X) -> - Z = terms_to_string (X), - list_to_integer (Z). - -ltrim ([]) -> - []; -ltrim ([$ | T]) -> - ltrim (T); -ltrim ([H | T]) -> - [H | T]. - -trim (S) -> - lists:reverse (ltrim (lists:reverse (ltrim (S)))). - -decode (M) -> - T = tokenize (M), - http_parser:parse (T). - - -media_type_decode (M) -> - T = tokenize (M), - media_type:parse (T). - - - - - +%% +%%http_server.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(http_server). + +-export([decode/1, media_type_decode/1, terms_to_atom/1, + terms_to_integer/1, terms_to_string/1, terms_to_tuple/1, + tokenize/1, trim/1]). + +-author('csanto@diit.unict.it'). + +-define(CRLF, "\r\n"). + +tokenize([]) -> [{'$end', 1}]; +tokenize([H | T]) -> + [{list_to_atom([H]), 1} | tokenize(T)]. + +terms_to_string([]) -> []; +terms_to_string([H | T]) -> + [L | _] = atom_to_list(element(1, H)), + [L | terms_to_string(T)]. + +terms_to_atom(X) -> list_to_atom(terms_to_string(X)). + +terms_to_tuple(X) -> list_to_tuple(terms_to_string(X)). + +terms_to_integer(X) -> + Z = terms_to_string(X), list_to_integer(Z). + +ltrim([]) -> []; +ltrim([$\s | T]) -> ltrim(T); +ltrim([H | T]) -> [H | T]. + +trim(S) -> + lists:reverse(ltrim(lists:reverse(ltrim(S)))). + +decode(M) -> T = tokenize(M), http_parser:parse(T). + +media_type_decode(M) -> + T = tokenize(M), media_type:parse(T). diff --git a/src/logger.erl b/src/logger.erl index 0a1d0e5..085fe81 100644 --- a/src/logger.erl +++ b/src/logger.erl @@ -1,28 +1,28 @@ -% -% logger.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (logger). --behaviour (gen_event). -%%==================================================================== +%% +%%logger.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(logger). + +-behaviour(gen_event).%%==================================================================== %% Include files %%==================================================================== @@ -30,18 +30,14 @@ %% External exports %%==================================================================== --export ([start/1, - log/2, - stop/1]). +-export([log/2, start/1, stop/1]). %%==================================================================== %% Internal exports %%==================================================================== --export ([init/1, - handle_event/2, - terminate/2, - code_change/3]). +-export([code_change/3, handle_event/2, init/1, + terminate/2]). %%==================================================================== %% External functions @@ -51,25 +47,23 @@ %% Description: Starts a new logger %%==================================================================== -start (LoggerName) -> - gen_event:start ({local, LoggerName}), - gen_event:add_handler (LoggerName, logger, LoggerName). +start(LoggerName) -> + gen_event:start({local, LoggerName}), + gen_event:add_handler(LoggerName, logger, LoggerName). %%==================================================================== %% Function: stop/1 %% Description: Stops a logger %%==================================================================== -stop (LoggerName) -> - gen_event:stop (LoggerName). +stop(LoggerName) -> gen_event:stop(LoggerName). %%==================================================================== %% Function: log/2 %% Description: Logs a message %%==================================================================== -log (LoggerName, Message) -> - gen_event:notify (LoggerName, Message). - +log(LoggerName, Message) -> + gen_event:notify(LoggerName, Message). %%==================================================================== %% Internal functions @@ -78,33 +72,29 @@ log (LoggerName, Message) -> %% Func: init/1 %% Returns: {ok, State} %%==================================================================== -init (Arg) -> - {ok, Arg}. - +init(Arg) -> {ok, Arg}. %%==================================================================== %% Func: handle_event/2 %% Returns: {ok, State} %%==================================================================== -handle_event (LogEvent, State) -> - case LogEvent of - {LogFormat, LogArgs} -> - io:format ("[~w] " ++ LogFormat ++ "~n", [State | LogArgs]); - LogString -> - io:format ("[~w] ~s~n", [State, LogString]) - end, - {ok, State}. - +handle_event(LogEvent, State) -> + case LogEvent of + {LogFormat, LogArgs} -> + io:format("[~w] " ++ LogFormat ++ "~n", + [State | LogArgs]); + LogString -> io:format("[~w] ~s~n", [State, LogString]) + end, + {ok, State}. %%==================================================================== %% Func: terminate/2 %% Returns: ok %%==================================================================== -terminate (Args, State) -> ok. +terminate(Args, State) -> ok. %%==================================================================== %% Func: code_change/3 %% Returns: {ok, NewState} %%==================================================================== -code_change(OldVsn, State, _) -> - {ok, State}. +code_change(OldVsn, State, _) -> {ok, State}. diff --git a/src/match_lib.erl b/src/match_lib.erl index d0ee543..2869489 100644 --- a/src/match_lib.erl +++ b/src/match_lib.erl @@ -1,102 +1,69 @@ -% -% match_lib.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (match_lib). --export ([match_all/2,match_acl/2]). +%% +%%match_lib.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(match_lib). --author ('csanto@diit.unict.it'). --include ("acl.hrl"). +-export([match_acl/2, match_all/2]). +-author('csanto@diit.unict.it'). -match_atoms (F, Atom) when function(F) -> F (Atom); +-include("acl.hrl"). -match_atoms (Atom1, Atom2) -> - (Atom1 == ?ACL_ANY) or (Atom2 == ?ACL_ANY) or (Atom1 == Atom2). +match_atoms(F, Atom) when is_function(F) -> F(Atom); +match_atoms(Atom1, Atom2) -> + (Atom1 == (?ACL_ANY)) or (Atom2 == (?ACL_ANY)) or + (Atom1 == Atom2). -% matches lists -match_lists ([], []) -> true; -match_lists ([L1], [L2]) -> match_atoms (L1, L2); -match_lists ([L], [H|T]) -> false; -match_lists ([H|T], [L]) ->false; -match_lists ([H1|T1], [H2|T2]) -> - X = match_atoms (H1, H2), - if - X -> match_lists (T1, T2); - true -> false - end. +%%matches lists +match_lists([], []) -> true; +match_lists([L1], [L2]) -> match_atoms(L1, L2); +match_lists([L], [H | T]) -> false; +match_lists([H | T], [L]) -> false; +match_lists([H1 | T1], [H2 | T2]) -> + X = match_atoms(H1, H2), + if X -> match_lists(T1, T2); + true -> false + end. -% matches lists or tuples -match_all (Fact1, Fact2) -> - Tuple1 = is_tuple (Fact1), - Tuple2 = is_tuple (Fact2), - if - Tuple1 and Tuple2 -> - match_lists (tuple_to_list (Fact1), tuple_to_list(Fact2)); - (not (Tuple1)) and Tuple2 -> - false; - Tuple1 and (not (Tuple2)) -> - false; - true -> - match_lists (Fact1, Fact2) - end. +%%matches lists or tuples +match_all(Fact1, Fact2) -> + Tuple1 = is_tuple(Fact1), + Tuple2 = is_tuple(Fact2), + if Tuple1 and Tuple2 -> + match_lists(tuple_to_list(Fact1), tuple_to_list(Fact2)); + not Tuple1 and Tuple2 -> false; + Tuple1 and not Tuple2 -> false; + true -> match_lists(Fact1, Fact2) + end. +%% +%%example: +%% match_lib:match_acl ({aclmessage,infom,nil,..,..,..,..}). +%% +match_acl([], Data) -> false; +match_acl([Clause | Clauses], Data) -> + Match = match_all(Clause, Data), + if Match -> true; + true -> match_acl(Clauses, Data) + end. -% -% example: -% match_lib:match_acl ({aclmessage,infom,nil,..,..,..,..}). -% -match_acl ([], Data) -> false; -match_acl ([Clause | Clauses], Data) -> - Match = match_all (Clause, Data), - if - Match -> true; - true -> match_acl (Clauses, Data) - end. - -% -% example: -% match_lib:match(["[_,a]","[b,b]","[c,c]"],[z,a]). -% -match (Clauses, Pattern) -> - F = build_fun (Clauses), - StrPattern = lists:flatten (io_lib:write (Pattern)), - F1 = "X=fun " ++ F ++ " end, X(" ++ - StrPattern ++ ").", - %io:format ("~s\n", [F1]), - {ok, Tokens, _} = erl_scan:string (F1), - {ok, Expr} = erl_parse:parse_exprs (Tokens), - case catch (erl_eval:exprs (Expr, erl_eval:new_bindings ())) of - {'EXIT', _} -> false; - {value, Value, Bindings} -> Value; - _ -> false - end. - -build_fun ([H]) -> - fun_from_term (H); - -build_fun ([H|T]) -> - fun_from_term (H) ++ "; " ++ build_fun (T). - -%build_fun ([]) -> "". - -fun_from_term (Term) -> - "(" ++ Term ++ ") -> true". +%%build_fun ([]) -> "". diff --git a/src/mtp.erl b/src/mtp.erl index 3664c59..4b4bf17 100644 --- a/src/mtp.erl +++ b/src/mtp.erl @@ -1,53 +1,51 @@ -% -% mtp.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (mtp). +%% +%%mtp.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(mtp). %%==================================================================== %% Include files %%==================================================================== -include_lib("kernel/include/inet.hrl"). --include ("acl.hrl"). --include ("fipa_ontology.hrl"). + +-include("acl.hrl"). + +-include("fipa_ontology.hrl"). %%==================================================================== %% External exports %%==================================================================== --export ([http/1, - addresses/0, - http_mtp_encode_and_send/3]). +-export([addresses/0, http/1, + http_mtp_encode_and_send/3]). --export ([init/1, - handle_call/3, - terminate/2, - code_change/3]). +-export([code_change/3, handle_call/3, init/1, + terminate/2]). %%==================================================================== %% Macros %%==================================================================== --define (BAD_RESPONSE, Req:respond(400)). - --define (OK_RESPONSE, Req:ok("")). +-define(BAD_RESPONSE, Req:respond(400)). +-define(OK_RESPONSE, Req:ok("")). %%==================================================================== %% External functions @@ -55,45 +53,53 @@ %%==================================================================== %% Func: http/1 %%==================================================================== -http (Port) -> - logger:start ('HTTP-MTP'), - logger:log ('HTTP-MTP', {"MTP Started at port ~w", [Port]}), - {ok, Hostname} = inet:gethostname (), - {ok, HostEnt} = inet:gethostbyname (Hostname), - MTPAddress = lists:flatten ( - ["http://", HostEnt#hostent.h_name, ":", - integer_to_list (Port), "/acc" ]), - eresye:assert (agent_registry, {mtp_address, MTPAddress}), +http(Port) -> + logger:start('HTTP-MTP'), + logger:log('HTTP-MTP', + {"MTP Started at port ~w", [Port]}), + {ok, Hostname} = inet:gethostname(), + {ok, HostEnt} = inet:gethostbyname(Hostname), + MTPAddress = lists:flatten(["http://", + HostEnt#hostent.h_name, ":", + integer_to_list(Port), "/acc"]), + eresye:assert(agent_registry, + {mtp_address, MTPAddress}), misultin:start_link([{port, Port}, {loop, fun handle_http/1}]). %%==================================================================== %% Func: addresses/0 %%==================================================================== -addresses () -> - MTPAddress = eresye:query_kb (agent_registry, {mtp_address, '_'}), - [ X || {_,X} <- MTPAddress]. +addresses() -> + MTPAddress = eresye:query_kb(agent_registry, + {mtp_address, '_'}), + [X || {_, X} <- MTPAddress]. %%==================================================================== %% Func: http_mtp_post/3 %%==================================================================== handle_http(Req) -> - http_mtp_post(Req:get(method), Req:resource([lowercase, urldecode]), Req:get(headers), Req). + http_mtp_post(Req:get(method), + Req:resource([lowercase, urldecode]), Req:get(headers), + Req). -http_mtp_post ('POST', Url, Headers, Req) -> +http_mtp_post('POST', Url, Headers, Req) -> %%io:format ("URL = ~s~n", [Url]), %%display_params (Headers), Content = Req:parse_post(), - [{part, _, XmlContent}] = - lists:filter(fun({part, H, D}) -> - "application/xml" == misultin_utility:header_get_value('Content-Type', H) - end, Content), - [{part, _, SLContent}] = - lists:filter(fun({part, H, D}) -> - "application/text" == misultin_utility:header_get_value('Content-Type', H) - end, Content), + [{part, _, XmlContent}] = [V1 + || V1 <- Content, http_mtp_post_1(V1)], + [{part, _, SLContent}] = [V2 + || V2 <- Content, http_mtp_post_2(V2)], http_mtp_decode(Req, XmlContent, SLContent). +http_mtp_post_1({part, H, D}) -> + "application/xml" == + misultin_utility:header_get_value('Content-Type', H). + +http_mtp_post_2({part, H, D}) -> + "application/text" == + misultin_utility:header_get_value('Content-Type', H). %% %% @@ -102,157 +108,142 @@ http_mtp_post ('POST', Url, Headers, Req) -> %% Func: http_mtp_decode/3 %%==================================================================== http_mtp_decode(Req, XmlContent, SLContent) -> - {To, From, ACLRepr} = envelope:parse_xml_envelope(binary_to_list(XmlContent)), - decode_and_forward_acl (Req, To, From, SLContent, ACLRepr). + {To, From, ACLRepr} = + envelope:parse_xml_envelope(binary_to_list(XmlContent)), + decode_and_forward_acl(Req, To, From, SLContent, + ACLRepr). %% %% -decode_and_forward_acl (Req, _, _, Message, "fipa.acl.rep.string.std") -> - DecodedMessage = sl:decode (binary_to_list(Message)), - %io:format ("MSG = ~p~n", [DecodedMessage]), - ACLMessage = list_to_tuple ([ aclmessage | - tuple_to_list (DecodedMessage)]), - %io:format ("Message = ~w~n", [ACLMessage]), - %io:format ("R = ~w~n", [ACLMessage#aclmessage.receiver]), - - % decode content - ParsedMessage = - case ontology_service:get_codec (ACLMessage#aclmessage.ontology) of - {ok, Codec} -> - {ok, SL} = sl:decode (ACLMessage#aclmessage.content, - ascii_sl, erlang_sl), - %io:format ("Content = ~p~n", [SL]), - ACLMessage#aclmessage { content = Codec:decode (SL) }; - _ -> ACLMessage - end, - - - % determine receiver list - Receivers = - case is_list (ParsedMessage#aclmessage.receiver) of - true -> - ParsedMessage#aclmessage.receiver; - false -> - [ParsedMessage#aclmessage.receiver] - end, +decode_and_forward_acl(Req, _, _, Message, + "fipa.acl.rep.string.std") -> + DecodedMessage = sl:decode(binary_to_list(Message)), + %%io:format ("MSG = ~p~n", [DecodedMessage]), + ACLMessage = list_to_tuple([aclmessage + | tuple_to_list(DecodedMessage)]), + %%io:format ("Message = ~w~n", [ACLMessage]), + %%io:format ("R = ~w~n", [ACLMessage#aclmessage.receiver]), + %%decode content + ParsedMessage = case + ontology_service:get_codec(ACLMessage#aclmessage.ontology) + of + {ok, Codec} -> + {ok, SL} = sl:decode(ACLMessage#aclmessage.content, + ascii_sl, erlang_sl), + %%io:format ("Content = ~p~n", [SL]), + ACLMessage#aclmessage{content = Codec:decode(SL)}; + _ -> ACLMessage + end, + %%determine receiver list + Receivers = case + is_list(ParsedMessage#aclmessage.receiver) + of + true -> ParsedMessage#aclmessage.receiver; + false -> [ParsedMessage#aclmessage.receiver] + end, CurrentPlatform = exat:current_platform(), - %io:format ("Receivers = ~w~n", [Receivers]), - LocalReceivers = lists:filter ( - fun (X) -> - {_ID, HAP} = - exat:split_agent_identifier ( - X#'agent-identifier'.name), - HAP == CurrentPlatform - end, Receivers), - MessagesToSend = [ParsedMessage#aclmessage { receiver = X } || X <- LocalReceivers], - %io:format ("Parsed Message = ~w~n", [MessagesToSend]), - lists:foreach ( - fun (X) -> - Receiver = (X#aclmessage.receiver)#'agent-identifier'.name, - {ID, _} = exat:split_agent_identifier (Receiver), - %io:format ("Recv = ~w~n", [Receiver]), - gen_server:call(list_to_atom (ID), [acl_erl_native, X]) - end, MessagesToSend), + %%io:format ("Receivers = ~w~n", [Receivers]), + LocalReceivers = [V1 + || V1 <- Receivers, + decode_and_forward_acl_1(V1, CurrentPlatform)], + MessagesToSend = [ParsedMessage#aclmessage{receiver = X} + || X <- LocalReceivers], + %%io:format ("Parsed Message = ~w~n", [MessagesToSend]), + lists:foreach(fun (X) -> + Receiver = + (X#aclmessage.receiver)#'agent-identifier'.name, + {ID, _} = exat:split_agent_identifier(Receiver), + %%io:format ("Recv = ~w~n", [Receiver]), + gen_server:call(list_to_atom(ID), [acl_erl_native, X]) + end, + MessagesToSend), ?OK_RESPONSE; +decode_and_forward_acl(Req, _, _, _, _) -> + ?BAD_RESPONSE. -decode_and_forward_acl (Req, _, _, _, _) -> ?BAD_RESPONSE. - - -display_params ([]) -> ok; -display_params ([{Param, Value} | T]) -> - io:format ("~s = ~s~n", [Param, Value]), - display_params (T). - +decode_and_forward_acl_1(X, CurrentPlatform) -> + {_ID, HAP} = + exat:split_agent_identifier(X#'agent-identifier'.name), + HAP == CurrentPlatform. %%==================================================================== %% Func: http_mtp_encode_and_send/1 %%==================================================================== -http_mtp_encode_and_send (To, From, Message) -> - %io:format ("Message ~w~n", [Message]), - XX = fipa_ontology_sl_codec:encode (Message), - %io:format ("XX ~w~n", [XX]), - ACL = sl:encode (XX), - %io:format ("ACL ~s~n", [ACL]), - - Envelope = envelope:make_xml_envelope (To, From, length (ACL)), - %io:format ("Envelope ~s~n", [Envelope]), - - HTTPBody = lists:flatten ( - [[$\r, $\n], - "This is not part of MIME multipart", [$\r, $\n, $\r, $\n], - "--251D738450A171593A1583EB", [$\r, $\n], - "Content-Type: application/xml", [$\r, $\n, $\r, $\n], - Envelope, [$\r, $\n, $\r, $\n], - "--251D738450A171593A1583EB", [$\r, $\n], - "Content-Type: application/text", [$\r, $\n, $\r, $\n], - ACL, [$\r, $\n], - "--251D738450A171593A1583EB--", [$\r, $\n, $\r, $\n]]), - +http_mtp_encode_and_send(To, From, Message) -> + %%io:format ("Message ~w~n", [Message]), + XX = fipa_ontology_sl_codec:encode(Message), + %%io:format ("XX ~w~n", [XX]), + ACL = sl:encode(XX), + %%io:format ("ACL ~s~n", [ACL]), + Envelope = envelope:make_xml_envelope(To, From, + length(ACL)), + %%io:format ("Envelope ~s~n", [Envelope]), + HTTPBody = lists:flatten([[$\r, $\n], + "This is not part of MIME multipart", + [$\r, $\n, $\r, $\n], + "--251D738450A171593A1583EB", [$\r, $\n], + "Content-Type: application/xml", + [$\r, $\n, $\r, $\n], Envelope, + [$\r, $\n, $\r, $\n], + "--251D738450A171593A1583EB", [$\r, $\n], + "Content-Type: application/text", + [$\r, $\n, $\r, $\n], ACL, [$\r, $\n], + "--251D738450A171593A1583EB--", + [$\r, $\n, $\r, $\n]]), [ReceiverAddr | _] = To#'agent-identifier'.addresses, - - {Host, Port} = case http_uri:parse (ReceiverAddr) of + {Host, Port} = case http_uri:parse(ReceiverAddr) of {http, _, H, P, _, _} -> {H, P}; - {ok,{http,_,H,P,_,_}} -> {H, P} + {ok, {http, _, H, P, _, _}} -> {H, P} end, - - Headers = [ {"Cache-Control", "no-cache"}, - {"Mime-Version", "1.0"}, - {"Host", Host ++ ":" ++ integer_to_list (Port)}, - {"Content-Length", integer_to_list (length (HTTPBody))}, - {"Connection", "close"}], - - %display_params (Headers), - %io:format ("Body ~w~n", [HTTPBody]), - - %io:format ("Receiver ~w,~w~n", - % [(Message#aclmessage.receiver)#'agent-identifier'.name, - % ReceiverAddr]), - - Request = { ReceiverAddr, - Headers, - "multipart/mixed ; boundary=\"251D738450A171593A1583EB\"", - HTTPBody}, - - % HTTPID = http:request ( - % post, - % { ReceiverAddr, - % Headers, - % "multipart/mixed ; boundary=\"251D738450A171593A1583EB\"", - % HTTPBody}, [], [{sync, true}]), - - HTTPID = gen_server:call (mtp_sender, {http_post, Request}), - + Headers = [{"Cache-Control", "no-cache"}, + {"Mime-Version", "1.0"}, + {"Host", Host ++ ":" ++ integer_to_list(Port)}, + {"Content-Length", integer_to_list(length(HTTPBody))}, + {"Connection", "close"}], + %%display_params (Headers), + %%io:format ("Body ~w~n", [HTTPBody]), + %%io:format ("Receiver ~w,~w~n", + %% [(Message#aclmessage.receiver)#'agent-identifier'.name, + %% ReceiverAddr]), + Request = {ReceiverAddr, Headers, + "multipart/mixed ; boundary=\"251D738450A17159" + "3A1583EB\"", + HTTPBody}, + %% HTTPID = http:request ( + %% post, + %% { ReceiverAddr, + %% Headers, + %% "multipart/mixed ; boundary=\"251D738450A171593A1583EB\"", + %% HTTPBody}, [], [{sync, true}]), + HTTPID = gen_server:call(mtp_sender, + {http_post, Request}), {ok, RequestID} = HTTPID, Result = RequestID, - %io:format ("Result ~p, ~p~n", [self (), Result]), + %%io:format ("Result ~p, ~p~n", [self (), Result]), {StatusLine, ReceivedHeaders, ReceivedBody} = Result, - %io:format ("Status ~w,~s~n", [StatusCode, ReasonPhrase]), - %io:format ("Body ~s~n", [ReceivedBody]). + %%io:format ("Status ~w,~s~n", [StatusCode, ReasonPhrase]), + %%io:format ("Body ~s~n", [ReceivedBody]). {HttpVersion, StatusCode, ReasonPhrase} = StatusLine. - - %%==================================================================== %% Func: init/1 %%==================================================================== -init (_) -> {ok, []}. +init(_) -> {ok, []}. %%==================================================================== %% Func: handle_call/3 %%==================================================================== handle_call({http_post, Request}, From, State) -> - HTTPID = httpc:request(post, Request, [], [{sync, true}]), - {reply, HTTPID, State}. - + HTTPID = httpc:request(post, Request, [], + [{sync, true}]), + {reply, HTTPID, State}. %%==================================================================== %% Func: terminate/2 %%==================================================================== terminate(_, _) -> ok. - %%==================================================================== %% Func: code_change/3 %%==================================================================== code_change(OldVsn, State, Extra) -> {ok, State}. - diff --git a/src/mtp_utils.erl b/src/mtp_utils.erl index 91bf647..bf3edcd 100644 --- a/src/mtp_utils.erl +++ b/src/mtp_utils.erl @@ -1,22 +1,24 @@ -module(mtp_utils). --export([skip_to_empty_line/1, - replace_newlines/2]). +-export([replace_newlines/2, skip_to_empty_line/1]). %% %% -skip_to_empty_line ([]) -> []; -skip_to_empty_line ([[] | T]) -> T; -skip_to_empty_line ([_ | T]) -> skip_to_empty_line (T). +skip_to_empty_line([]) -> []; +skip_to_empty_line([[] | T]) -> T; +skip_to_empty_line([_ | T]) -> skip_to_empty_line(T). %% %% -replace_newlines (Acc, []) -> lists:reverse (Acc); -replace_newlines (Acc, [$\r | T]) -> replace_newlines ([$ | Acc], T); -replace_newlines (Acc, [$\n | T]) -> replace_newlines ([$ | Acc], T); -replace_newlines (Acc, [H | T]) -> replace_newlines ([H | Acc], T). +replace_newlines(Acc, []) -> lists:reverse(Acc); +replace_newlines(Acc, [$\r | T]) -> + replace_newlines([$\s | Acc], T); +replace_newlines(Acc, [$\n | T]) -> + replace_newlines([$\s | Acc], T); +replace_newlines(Acc, [H | T]) -> + replace_newlines([H | Acc], T). %% %% diff --git a/src/multisync.erl b/src/multisync.erl index c9eac84..a9c4ffd 100644 --- a/src/multisync.erl +++ b/src/multisync.erl @@ -21,33 +21,32 @@ %% %% -module(multisync). --export([new/0, add_task/4, wait_one/1, abort/1]). + +-export([abort/1, add_task/4, new/0, wait_one/1]). new() -> - O = object:new(sync), - object:set(O, 'tasklist', []), - O. + O = object:new(sync), object:set(O, tasklist, []), O. add_task(Sync, Module, Proc, Params) -> %%io:format("Exec task ~w\n", [Proc]), - OldList = object:get(Sync, 'tasklist'), + OldList = object:get(Sync, tasklist), Pid = spawn(Module, Proc, [Sync | Params]), List = [Pid | OldList], - object:set(Sync, 'tasklist', List), + object:set(Sync, tasklist, List), ok. wait_one(Sync) -> Result = object:call(Sync, wait), %%io:format("Wait result ~w\n", [Result]), - kill_all(object:get(Sync, 'tasklist')), + kill_all(object:get(Sync, tasklist)), object:delete(Sync), Result. abort(Sync) -> - kill_all(object:get(Sync, 'tasklist')), + kill_all(object:get(Sync, tasklist)), object:delete(Sync), ok. kill_all([]) -> nil; -kill_all([H]) -> catch(exit(H, kill)); -kill_all([H|T]) -> kill_all([H]), kill_all(T). +kill_all([H]) -> catch exit(H, kill); +kill_all([H | T]) -> kill_all([H]), kill_all(T). diff --git a/src/object.erl b/src/object.erl index 1850c8e..e1136d4 100644 --- a/src/object.erl +++ b/src/object.erl @@ -21,50 +21,39 @@ %% %% -module(object). --export([new/1, - new/2, - delete/1, - start/1, - do/2, - join/1, - stop/1, - bind/2, - agentof/1, - aclqueueof/1, - executorof/1, - property_server/1, - executor/0, - call/2, - call/3, - super_class/2, - super_class/3, - super_class/4, - super/1, - super/2, - super/3, - super_/1, - set/3, - get/2, - getClass/1, - getParent/1, - getAttributes/1, - getAttributeNames/1]). + +-export([aclqueueof/1, agentof/1, bind/2, call/2, + call/3, delete/1, do/2, executor/0, executorof/1, get/2, + getAttributeNames/1, getAttributes/1, getClass/1, + getParent/1, join/1, new/1, new/2, property_server/1, + set/3, start/1, stop/1, super/1, super/2, super/3, + super_/1, super_class/2, super_class/3, super_class/4]). + -author('csanto@diit.unict.it'). + -include("object.hrl"). -define(PROPERTY_STATUS, '__status__'). + -define(TERMINATING, '__terminating__'). + -define(JOINING_SYNC, '__joining__'). + -define(INIT_STATUS, '__init__'). + -define(END_STATUS, '__end__'). + -define(BOUND_AGENT, '__agent__'). + -define(ACL_QUEUE, '__acl_queue__'). + -define(NO_AGENT, '__no_agent__'). --define(MULTISYNC, '__multisync__'). +-define(MULTISYNC, '__multisync__'). new(Class, P) -> - PropertyServerPid = spawn(object, property_server, [dict:new()]), + PropertyServerPid = spawn(object, property_server, + [dict:new()]), server_call(PropertyServerPid, {self(), set, ?PROPERTY_STATUS, ?INIT_STATUS}), server_call(PropertyServerPid, @@ -76,15 +65,13 @@ new(Class, P) -> server_call(PropertyServerPid, {self(), set, class, Class}), ExecutorPid = spawn(object, executor, []), - Object = #object {class=Class, - context=Class, - property_server = PropertyServerPid, - executor = ExecutorPid}, + Object = #object{class = Class, context = Class, + property_server = PropertyServerPid, + executor = ExecutorPid}, c_tor_call(Object, Class, P), Object. -new(Class) -> - new(Class, []). +new(Class) -> new(Class, []). delete(Object) -> Class = Object#object.class, @@ -92,21 +79,19 @@ delete(Object) -> d_tor_call(Object, Class, []), S = get(Object, ?JOINING_SYNC), %%io:format("Before d_tor ~w\n", [S]), - if - S =/= nil -> delete(S); - true -> nil + if S =/= nil -> delete(S); + true -> nil end, M = get(Object, ?MULTISYNC), - if - S =/= nil -> catch(multisync:abort(M)); - true -> nil + if S =/= nil -> catch multisync:abort(M); + true -> nil end, %% Destroy the property server %%io:format("After d_tor II ~w\n", [Object]), - catch(exit(Object#object.property_server, kill)), + catch exit(Object#object.property_server, kill), %% Destroy the executor %%io:format("After d_tor ~w\n", [Object]), - catch(exit(Object#object.executor, kill)), + catch exit(Object#object.executor, kill), ok. set(Object, AttributeName, AttributeValue) -> @@ -123,29 +108,28 @@ get(Object, AttributeName) -> _ -> exit({undef, [attribute, Object, AttributeName]}) end. -call(Object, Method) -> - call(Object, Method, []). +call(Object, Method) -> call(Object, Method, []). call(Object, Method, Params) -> %% only the virtual inheritance is implemented %%io:format("Calling1 ~w,~w\n", [Object,Method]), - Obj1 = Object#object {context = Object#object.class}, + Obj1 = Object#object{context = Object#object.class}, X = call(Obj1, Method, Object#object.class, Params), %%io:format("Result is ~w,~w\n", [Object,X]), X. call(Object, Method, nil, _) -> exit({undef, [method, Object, Method]}); - call(Object, Method, Class, Params) -> - case public_call(Object, Method, Class, Params, fun(M,C) -> M end) of + case public_call(Object, Method, Class, Params, + fun (M, C) -> M end) + of {error, Error} -> %%exit({undef, [method, Object, Method]}); exit(Error); {ok, Value} -> Value end. - super_class(Object, Class) -> super_class(Object, Class, Class, []). @@ -153,10 +137,9 @@ super_class(Object, Class, Method) -> super_class(Object, Class, Method, []). super_class(Object, Class, Method, Params) -> - Obj1 = Object#object {context = Class}, + Obj1 = Object#object{context = Class}, call(Obj1, Method, Obj1#object.context, Params). - %% calls the constructor of the ancestor class super(Object) -> super_class(Object, getParent(Object#object.context)). @@ -165,33 +148,29 @@ super(Object) -> super(Object, Arguments) when is_list(Arguments) -> Parent = getParent(Object#object.context), super_class(Object, Parent, Parent, Arguments); - %% calls the method of the ancestor class -super(Object, Method) -> +super(Object, Method) -> Parent = getParent(Object#object.context), super_class(Object, Parent, Method). %% calls the method of the ancestor class with the given arguments -super(Object, Method, Arguments) -> +super(Object, Method, Arguments) -> Parent = getParent(Object#object.context), super_class(Object, Parent, Method, Arguments). %% calls the destructor of the ancestor class -super_ (Object) -> +super_(Object) -> Parent = getParent(Object#object.context), Method = Parent ++ "_", super_class(Object, Parent, Method, []). - %% %% behavioural procedures %% start(Object) -> V = get(Object, ?PROPERTY_STATUS), - if - V == ?INIT_STATUS -> - do(Object, start); - true -> nil + if V == (?INIT_STATUS) -> do(Object, start); + true -> nil end, ok. @@ -199,64 +178,60 @@ do(Object, State) -> set(Object, ?TERMINATING, false), %% FIXME: ????? V = get(Object, ?PROPERTY_STATUS), set(Object, ?PROPERTY_STATUS, State), - if - V == ?INIT_STATUS -> - case catch(object:call(Object, on_starting)) of + if V == (?INIT_STATUS) -> + case catch object:call(Object, on_starting) of {'EXIT', {undef, _}} -> ok; {'EXIT', Error} -> - io:format("Error in 'on_starting' for object ~w: ~w\n", + io:format("Error in 'on_starting' for object ~w: " + "~w\n", [Object, Error]); _ -> ok end, set(Object, ?JOINING_SYNC, object:new(sync)), trigger_executor(Object); - true -> nil + true -> nil end, ok. -stop(Object) -> - set(Object, ?TERMINATING, true). +stop(Object) -> set(Object, ?TERMINATING, true). join(Object) -> - S = get(Object, ?JOINING_SYNC), - object:call(S, wait). + S = get(Object, ?JOINING_SYNC), object:call(S, wait). bind(Object, Agent) -> set(Object, ?BOUND_AGENT, Agent), - set(Object, ?ACL_QUEUE, list_to_atom(atom_to_list(Agent) ++ "__queue")). + set(Object, ?ACL_QUEUE, + list_to_atom(atom_to_list(Agent) ++ "__queue")). -agentof(Object) -> - get(Object, ?BOUND_AGENT). +agentof(Object) -> get(Object, ?BOUND_AGENT). -aclqueueof(Object) -> - get(Object, ?ACL_QUEUE). +aclqueueof(Object) -> get(Object, ?ACL_QUEUE). -executorof(Object) -> - Object#object.executor. +executorof(Object) -> Object#object.executor. %% %% reflection API %% -getClass(Obj) -> - Obj#object.class. +getClass(Obj) -> Obj#object.class. getParent(Class) -> %% calls "extends/0" function to obtain the parent class %%io:format("Calling getParent ~w\n", [Class]), - X = call_ (Class, extends), + X = call_(Class, extends), %%io:format("Called getParent ~w,~w\n", [Class, X]), X. - %% getMethods(Class) -> %% %% calls "public/0" function to obtain the method list %% call_ (Class, public). getAttributeNames(Object) -> - server_call(Object#object.property_server, {self(), list}). + server_call(Object#object.property_server, + {self(), list}). getAttributes(Object) -> - server_call(Object#object.property_server, {self(), list_values}). + server_call(Object#object.property_server, + {self(), list_values}). %% ---------------------------------------------- %% @@ -267,11 +242,9 @@ getAttributes(Object) -> %% %% Calling a function of a module %% -call_ (Module, Func) -> - call_ (Module, Func, []). +call_(Module, Func) -> call_(Module, Func, []). -call_ (Module, Func, P) -> - apply({Module, Func}, P). +call_(Module, Func, P) -> apply({Module, Func}, P). %% %% Performing a virtual call to a method of an object @@ -280,69 +253,80 @@ public_call(Object, Method, Class, Params, NameFun) -> public_call(Object, Method, Class, Params, NameFun, {undef, [method, Object, Method]}). -public_call(Object, Method, nil, Params, NameFun, LastException) -> +public_call(Object, Method, nil, Params, NameFun, + LastException) -> {error, LastException}; - -public_call(Object, Method, Class, Params, NameFun, LastException) -> +public_call(Object, Method, Class, Params, NameFun, + LastException) -> Parents = tolist(getParent(Class)), %%io:format("Parents = ~w,~w\n", [Object, Parents]), - list_call(Object, Method, Class, Parents, Params, NameFun, LastException). - -list_call(Object, Method, Class, [], Params, NameFun, LastException) -> - {error, LastException}; %%{undef, [method, Object, Method]}}; + list_call(Object, Method, Class, Parents, Params, + NameFun, LastException). +list_call(Object, Method, Class, [], Params, NameFun, + LastException) -> + {error, + LastException}; %%{undef, [method, Object, Method]}}; list_call(Object, Method, Class, [ParentH | ParentT], Params, NameFun, LastException) -> {Result, Value} = deep_call(Object, Method, Class, ParentH, Params, NameFun), - if - Result == ok -> {Result, Value}; - true -> list_call(Object, Method, Class, ParentT, - Params, NameFun, LastException) + if Result == ok -> {Result, Value}; + true -> + list_call(Object, Method, Class, ParentT, Params, + NameFun, LastException) end. -deep_call(Object, Method, Class, Parent, Params, NameFun) -> - case call_a_method(Object, Method, Class, Params, NameFun) of - {ok, Value} -> - {ok, Value}; +deep_call(Object, Method, Class, Parent, Params, + NameFun) -> + case call_a_method(Object, Method, Class, Params, + NameFun) + of + {ok, Value} -> {ok, Value}; {to_parent, Exception} -> - Obj1 = Object#object {context = Parent}, - public_call(Obj1, Method, Parent, Params, NameFun, Exception); - {error, Exception} -> - exit(Exception) + Obj1 = Object#object{context = Parent}, + public_call(Obj1, Method, Parent, Params, NameFun, + Exception); + {error, Exception} -> exit(Exception) end. call_a_method(Object, Method, Class, Params, NameFun) -> %%io:format("Calling a method ~w,~w\n", [Object, Method]), MethodName = NameFun(Method, Class), - case catch(call_ (Class, MethodName, [Object | Params])) of - {'EXIT', Error = {undef, [ {Module, Function, _} | _]}} -> - MethodNotPresend = (Module == Class) and(Function == MethodName), + case catch call_(Class, MethodName, [Object | Params]) + of + {'EXIT', + Error = {undef, [{Module, Function, _} | _]}} -> + MethodNotPresend = (Module == Class) and + (Function == MethodName), check_for_returning_error(Error, MethodNotPresend); - {'EXIT', Error = {function_clause, [ {Module, Function, _} | _]}} -> - ClauseNotPresend = (Module == Class) and(Function == MethodName), + {'EXIT', + Error = {function_clause, + [{Module, Function, _} | _]}} -> + ClauseNotPresend = (Module == Class) and + (Function == MethodName), check_for_returning_error(Error, ClauseNotPresend); {'EXIT', Other} -> %%io:format("Error in calling ~w:~w = ~w\n", [Object, MethodName, %% Other]), {error, Other}; - Val -> - {ok, Val} + Val -> {ok, Val} end. - -check_for_returning_error(Error, true) ->%% the method is not present +check_for_returning_error(Error, + true) ->%% the method is not present {to_parent, Error}; -check_for_returning_error(Error, _) ->%% an internal exception occurred +check_for_returning_error(Error, + _) ->%% an internal exception occurred exit(Error). - %% %% Performing a virtual call to the Ctor of an object %% c_tor_call(Object, Class, Params) -> - case catch(public_call(Object, Class, Class, Params, - fun(M,C) -> C end)) of + case catch public_call(Object, Class, Class, Params, + fun (M, C) -> C end) + of {'EXIT', {undef, _}} -> nil; {'EXIT', Other} -> exit(Other); _ -> nil @@ -374,35 +358,27 @@ c_tor_call(Object, Class, Params) -> %% Obj1 = Object#object {context = Parent}, %% c_tor_call(Obj1, Parent, Params). - %% %% Performing a virtual call to the Dtor of an object %% -d_tor_call(Object, nil, Params) -> - nil; +d_tor_call(Object, nil, Params) -> nil; d_tor_call(Object, Class, Params) -> Parents = tolist(getParent(Class)), dtor_list_call(Object, Class, Parents, Params). -dtor_list_call(Object, nil, _, Params) -> - nil; - -dtor_list_call(Object, Class, [], Params) -> - nil; - -dtor_list_call(Object, Class, [ParentH | ParentT], Params) -> +dtor_list_call(Object, nil, _, Params) -> nil; +dtor_list_call(Object, Class, [], Params) -> nil; +dtor_list_call(Object, Class, [ParentH | ParentT], + Params) -> dtor_deep_call(Object, Class, ParentH, Params), dtor_list_call(Object, Class, ParentT, Params). dtor_deep_call(Object, Class, Parent, Params) -> call_a_method(Object, method, Class, Params, - fun(M,C) -> - list_to_atom(atom_to_list(C) ++ "_") - end), - Obj1 = Object#object {context = Parent}, + fun (M, C) -> list_to_atom(atom_to_list(C) ++ "_") end), + Obj1 = Object#object{context = Parent}, d_tor_call(Obj1, Parent, Params). - tolist(X) when is_atom(X) -> [X]; tolist(X) -> X. @@ -418,88 +394,94 @@ trigger_executor(Object) -> executor() -> receive {go, Object} -> executor_loop(Object); - Other -> io:format("Executor[~w]: Invalid message ~w\n", - [self(), Other]) + Other -> + io:format("Executor[~w]: Invalid message ~w\n", + [self(), Other]) end. executor_loop(Object) -> %%io:format("Executor: ~w\n", [Object]), V = get(Object, ?PROPERTY_STATUS), - T = not(get(Object, ?TERMINATING)), + T = not get(Object, ?TERMINATING), %%io:format("Value: ~w,~w\n", [Object, V]), - if - T -> - case catch(executor_do(Object, V)) of + if T -> + case catch executor_do(Object, V) of {'EXIT', Reason} -> - io:format("\n=ERROR REPORT====\nError in object behaviour ~w, state ~w, error value: ~w\n", [Object, V, Reason]), + io:format("\n=ERROR REPORT====\nError in object " + "behaviour ~w, state ~w, error value: " + "~w\n", + [Object, V, Reason]), set(Object, ?TERMINATING, true); Other -> nil end, executor_loop(Object); - true -> - case catch(object:call(Object, on_stopping)) of + true -> + case catch object:call(Object, on_stopping) of {'EXIT', {undef, _}} -> ok; {'EXIT', Error} -> - io:format("Error in 'on_stopping' for object ~w: ~w\n", + io:format("Error in 'on_stopping' for object ~w: " + "~w\n", [Object, Error]); _ -> ok end, S = get(Object, ?JOINING_SYNC), - if - S =/= nil -> object:call(S, signal_all); - true -> nil + if S =/= nil -> object:call(S, signal_all); + true -> nil end - %%io:format("Behaviour[~w]: Stopped.\n", [Object]) end. +%%io:format("Behaviour[~w]: Stopped.\n", [Object]) + executor_do(Object, State) -> %%io:format("Executor_Do: ~w,~w\n", [Object, State]), Class = Object#object.class, %% get the event & proc list EventProc = call(Object, action, [State]), %% convert event-proc to a list(if not) - if - is_list(EventProc) -> EventProcList = EventProc; - true -> EventProcList = [EventProc] + if is_list(EventProc) -> EventProcList = EventProc; + true -> EventProcList = [EventProc] end, - CompleteEventList = make_event_list(Object, EventProcList), + CompleteEventList = make_event_list(Object, + EventProcList), %% %% CompleteEventList is made of: %% [ {EventType, Pattern, Proc}, .... ] %% %% now get the bound agent %% - case catch(agentof(Object)) of - {'EXIT', _ } -> Agent = ?NO_AGENT; + case catch agentof(Object) of + {'EXIT', _} -> Agent = (?NO_AGENT); Other -> Agent = Other end, %%io:format("Event list = ~w\n", [CompleteEventList]), M = multisync:new(), set(Object, ?MULTISYNC, M), make_multi_sync_tasks(M, Agent, CompleteEventList), - {FiredEvent, PatternValue, Proc} = multisync:wait_one(M), + {FiredEvent, PatternValue, Proc} = + multisync:wait_one(M), set(Object, ?MULTISYNC, nil), %%io:format("~w,~w\n", [FiredEvent, PatternValue]), call(Object, Proc, [FiredEvent, PatternValue, State]). - make_event_list(Object, []) -> []; -make_event_list(Object, [{Event, Proc}|T]) -> +make_event_list(Object, [{Event, Proc} | T]) -> {EventType, PatternName} = call(Object, event, [Event]), Pattern = getpattern(Object, PatternName), - [ {EventType, Pattern, Proc} | make_event_list(Object, T)]. + [{EventType, Pattern, Proc} | make_event_list(Object, + T)]. make_multi_sync_tasks(M, Agent, []) -> ok; -make_multi_sync_tasks(M, Agent, [{acl, Pattern, Proc}|T]) -> - if - Agent =/= ?NO_AGENT -> +make_multi_sync_tasks(M, Agent, + [{acl, Pattern, Proc} | T]) -> + if Agent =/= (?NO_AGENT) -> multisync:add_task(M, eventmanager, eventmanager:eventof(acl), [Agent, Pattern, Proc]); - true -> nil + true -> nil end, make_multi_sync_tasks(M, Agent, T); -make_multi_sync_tasks(M, Agent, [{EventType, Pattern, Proc}|T]) -> +make_multi_sync_tasks(M, Agent, + [{EventType, Pattern, Proc} | T]) -> multisync:add_task(M, eventmanager, eventmanager:eventof(EventType), [Agent, Pattern, Proc]), @@ -507,7 +489,9 @@ make_multi_sync_tasks(M, Agent, [{EventType, Pattern, Proc}|T]) -> getpattern(Object, $_) -> nil; getpattern(Object, nil) -> nil; -getpattern(Object, PatternName) -> call(Object, pattern, [PatternName]). +getpattern(Object, PatternName) -> + call(Object, pattern, [PatternName]). + %% get_matching_acl_message(AclQueue, Pattern) -> %% %Message = lq:dequeue(AclQueue), @@ -527,22 +511,24 @@ server_call(Server, Data) -> Server ! Data, receive {ack, X} -> X; - Other -> io:format("Invalid reply = ~p on call ~p: ~p\n", - [Server, Data, Other]), - exit({badtransaction, Other}) + Other -> + io:format("Invalid reply = ~p on call ~p: ~p\n", + [Server, Data, Other]), + exit({badtransaction, Other}) end. property_server(Dict) -> receive {From, get, AttributeName} -> - case catch(dict:fetch(AttributeName, Dict)) of + case catch dict:fetch(AttributeName, Dict) of {'EXIT', _} -> From ! {ack, undef}; Other -> From ! {ack, {value, Other}} end, property_server(Dict); {From, set, AttributeName, AttributeValue} -> From ! {ack, ok}, - property_server(dict:store(AttributeName, AttributeValue, Dict)); + property_server(dict:store(AttributeName, + AttributeValue, Dict)); {From, list} -> X = dict:fetch_keys(Dict), From ! {ack, X}, @@ -551,8 +537,6 @@ property_server(Dict) -> X = dict:to_list(Dict), From ! {ack, X}, property_server(Dict); - {From, exit } -> - From ! {ack, ok}; - Other -> - property_server(Dict) + {From, exit} -> From ! {ack, ok}; + Other -> property_server(Dict) end. diff --git a/src/ontology.erl b/src/ontology.erl index 9c9b272..4c563eb 100644 --- a/src/ontology.erl +++ b/src/ontology.erl @@ -1,36 +1,37 @@ -% -% ontology.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (ontology). +%% +%%ontology.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(ontology). %%==================================================================== %% Include files %%==================================================================== --include ("ontology.hrl"). +-include("ontology.hrl"). %%==================================================================== %% External exports %%==================================================================== --export ([compile/4, compile/2, sl_decode_term/2, sl_encode_term/2]). +-export([compile/2, compile/4, sl_decode_term/2, + sl_encode_term/2]). %%==================================================================== %% External functions @@ -39,38 +40,35 @@ %% Function: compile/2 %% Description: Compiles an ontology file %%==================================================================== -compile (PathName, Options) -> - FileName = filename:basename (PathName), - DirName = filename:dirname (PathName), - compile (FileName, DirName, DirName, Options). - +compile(PathName, Options) -> + FileName = filename:basename(PathName), + DirName = filename:dirname(PathName), + compile(FileName, DirName, DirName, Options). %%==================================================================== %% Function: compile/4 %% Description: Compiles an ontology file %%==================================================================== -compile (FileName, SrcPath, DestPath, Options) -> - {ok, AbstractErlangForm} = epp:parse_file (SrcPath ++ "/" ++ - FileName ++ ".onto", "", []), - %%io:format ("~w~n", [AbstractErlangForm]), - {ok, Classes} = compile_lines ([], list_to_atom (FileName), - AbstractErlangForm), - - %%io:format ("~p~n", [Classes]), - NewClasses = resolve_inheritance (Classes), - %%io:format ("~p~n", [NewClasses]), - generate_include (DestPath, FileName, NewClasses, - lists:member (include, Options)), - %% - generate_erlang (DestPath, FileName, Classes, NewClasses, - lists:member (source, Options)), - %% - generate_sl_codec (DestPath, FileName, NewClasses, - lists:member (sl_codec, Options)), - %% - ok. - - +compile(FileName, SrcPath, DestPath, Options) -> + {ok, AbstractErlangForm} = epp:parse_file(SrcPath ++ + "/" ++ FileName ++ ".onto", + "", []), + %%io:format ("~w~n", [AbstractErlangForm]), + {ok, Classes} = compile_lines([], + list_to_atom(FileName), AbstractErlangForm), + %%io:format ("~p~n", [Classes]), + NewClasses = resolve_inheritance(Classes), + %%io:format ("~p~n", [NewClasses]), + generate_include(DestPath, FileName, NewClasses, + lists:member(include, Options)), + %% + generate_erlang(DestPath, FileName, Classes, NewClasses, + lists:member(source, Options)), + %% + generate_sl_codec(DestPath, FileName, NewClasses, + lists:member(sl_codec, Options)), + %% + ok. %%==================================================================== %% Internal functions @@ -83,14 +81,15 @@ compile (FileName, SrcPath, DestPath, Options) -> %%==================================================================== %% Func: generate_include/4 %%==================================================================== -generate_include (_, _, _, false) -> ok; -generate_include (DestPath, FileName, Classes, _) -> - IncludeLines = generate_include_file (Classes), - {ok, IncludeFile} = file:open (DestPath ++ "/" ++ FileName ++ ".hrl", - [write]), - io:format (IncludeFile, "~s", [IncludeLines]), - file:close (IncludeFile), - ok. +generate_include(_, _, _, false) -> ok; +generate_include(DestPath, FileName, Classes, _) -> + IncludeLines = generate_include_file(Classes), + {ok, IncludeFile} = file:open(DestPath ++ + "/" ++ FileName ++ ".hrl", + [write]), + io:format(IncludeFile, "~s", [IncludeLines]), + file:close(IncludeFile), + ok. %%==================================================================== %% Func: compile_lines/3 @@ -99,26 +98,31 @@ generate_include (DestPath, FileName, Classes, _) -> %% Returns: {ok, [#ontology_class]} | %% {error, Reason} %%==================================================================== -compile_lines (Accumulator, _, []) -> {ok, - lists:flatten ( - lists:reverse (Accumulator))}; -compile_lines (Accumulator, OntoName, - [{function, _, class, _, Clauses} | Tail]) -> - compile_lines ([compile_clauses ([], Clauses) | Accumulator], - OntoName, Tail); -compile_lines (Accumulator, OntoName, - [{attribute, _, ontology, OntoName} | Tail]) -> - compile_lines (Accumulator, OntoName, Tail); -compile_lines (Accumulator, OntoName, - [{attribute, Line, ontology, _} | Tail]) -> - {error,{"ontology name does not match with filename in line", Line}}; -compile_lines (Accumulator, OntoName, [{attribute, _, file, _} | Tail]) -> - compile_lines (Accumulator, OntoName, Tail); -compile_lines (Accumulator, OntoName, [{eof, _} | Tail]) -> - compile_lines (Accumulator, OntoName, Tail); -compile_lines (Accumulator, _, [{_, Line, _, _} | Tail]) -> - {error,{"syntax error in line", Line}}. - +compile_lines(Accumulator, _, []) -> + {ok, lists:flatten(lists:reverse(Accumulator))}; +compile_lines(Accumulator, OntoName, + [{function, _, class, _, Clauses} | Tail]) -> + compile_lines([compile_clauses([], Clauses) + | Accumulator], + OntoName, Tail); +compile_lines(Accumulator, OntoName, + [{attribute, _, ontology, OntoName} | Tail]) -> + compile_lines(Accumulator, OntoName, Tail); +compile_lines(Accumulator, OntoName, + [{attribute, Line, ontology, _} | Tail]) -> + {error, + {"ontology name does not match with filename " + "in line", + Line}}; +compile_lines(Accumulator, OntoName, + [{attribute, _, file, _} | Tail]) -> + compile_lines(Accumulator, OntoName, Tail); +compile_lines(Accumulator, OntoName, + [{eof, _} | Tail]) -> + compile_lines(Accumulator, OntoName, Tail); +compile_lines(Accumulator, _, + [{_, Line, _, _} | Tail]) -> + {error, {"syntax error in line", Line}}. %%==================================================================== %% Func: compile_clauses/2 @@ -126,11 +130,9 @@ compile_lines (Accumulator, _, [{_, Line, _, _} | Tail]) -> %% given its erlang abstract form %% Returns: [#ontology_class] %%==================================================================== -compile_clauses (Acc, []) -> lists:reverse (Acc); -compile_clauses (Acc, [H|T]) -> - compile_clauses ([compile_clause (H) | Acc], T). - - +compile_clauses(Acc, []) -> lists:reverse(Acc); +compile_clauses(Acc, [H | T]) -> + compile_clauses([compile_clause(H) | Acc], T). %%==================================================================== %% Func: compile_clause/1 @@ -138,25 +140,25 @@ compile_clauses (Acc, [H|T]) -> %% given its erlang abstract form %% Returns: #ontology_class %%==================================================================== -compile_clause ({clause, LineNum, - [{atom, _, ClassName}], [], [{tuple, _, ClassDef}]}) -> - #ontology_class { name = ClassName, - superclass = nil, - properties = compile_properties ([], ClassName, ClassDef)}; -compile_clause ({clause, LineNum, - [{atom, _, ClassName}], [], - [{call,_, {atom, _, is_a}, [{atom, _, SuperClass}]}]}) -> - #ontology_class { name = ClassName, - superclass = SuperClass, - properties = []}; -compile_clause ({clause, LineNum, - [{atom, _, ClassName}], [], - [{call,_, {atom, _, is_a}, [{atom, _, SuperClass}]}, - {tuple, _, ClassDef}]}) -> - #ontology_class { name = ClassName, +compile_clause({clause, LineNum, [{atom, _, ClassName}], + [], [{tuple, _, ClassDef}]}) -> + #ontology_class{name = ClassName, superclass = nil, + properties = + compile_properties([], ClassName, ClassDef)}; +compile_clause({clause, LineNum, [{atom, _, ClassName}], + [], + [{call, _, {atom, _, is_a}, + [{atom, _, SuperClass}]}]}) -> + #ontology_class{name = ClassName, + superclass = SuperClass, properties = []}; +compile_clause({clause, LineNum, [{atom, _, ClassName}], + [], + [{call, _, {atom, _, is_a}, [{atom, _, SuperClass}]}, + {tuple, _, ClassDef}]}) -> + #ontology_class{name = ClassName, superclass = SuperClass, - properties = compile_properties ([], ClassName, ClassDef)}. - + properties = + compile_properties([], ClassName, ClassDef)}. %%==================================================================== %% Func: compile_properties/3 @@ -164,10 +166,11 @@ compile_clause ({clause, LineNum, %% given the erlang abstract form %% Returns: [#ontology_property] %%==================================================================== -compile_properties (Acc, _, []) -> lists:reverse (Acc); -compile_properties (Acc, ClassName, [H|T]) -> - compile_properties ([compile_property (ClassName, H) | Acc], - ClassName, T). +compile_properties(Acc, _, []) -> lists:reverse(Acc); +compile_properties(Acc, ClassName, [H | T]) -> + compile_properties([compile_property(ClassName, H) + | Acc], + ClassName, T). %%==================================================================== %% Func: compile_properties/2 @@ -175,214 +178,214 @@ compile_properties (Acc, ClassName, [H|T]) -> %% given the erlang abstract form %% Returns: #ontology_property %%==================================================================== -compile_property (ClassName, - {match, _, {atom, _, FieldName}, FieldDef}) -> - L = cons_to_erl_list (FieldDef), - %%io:format ("~p~n", [L]), - [FieldType, FieldRequirement, Default |_] = L, - #ontology_property {name = FieldName, - type = FieldType, - requirement = FieldRequirement, - is_primitive = is_primitive (FieldType), - is_digit = is_digit (FieldName), - default = Default}. +compile_property(ClassName, + {match, _, {atom, _, FieldName}, FieldDef}) -> + L = cons_to_erl_list(FieldDef), + %%io:format ("~p~n", [L]), + [FieldType, FieldRequirement, Default | _] = L, + #ontology_property{name = FieldName, type = FieldType, + requirement = FieldRequirement, + is_primitive = is_primitive(FieldType), + is_digit = is_digit(FieldName), default = Default}. %%==================================================================== %% Func: cons_to_erl_list/1 %% Description: transforms a "cons" abstract erlang construct to a list %% Returns: [term()] %%==================================================================== -cons_to_erl_list ({cons, Line, OP1, OP2}) -> [cons_decode (OP1) | - cons_to_erl_list (OP2)]; -cons_to_erl_list (X) -> [cons_decode(X)]. - - +cons_to_erl_list({cons, Line, OP1, OP2}) -> + [cons_decode(OP1) | cons_to_erl_list(OP2)]; +cons_to_erl_list(X) -> [cons_decode(X)]. %%==================================================================== %% Func: cons_decode/1 %% Description: decodes a single abstract erlang term %% Returns: term() %%==================================================================== -cons_decode ({atom, _, nodefault}) -> ?NO_DEFAULT; -cons_decode ({atom, _, Option}) -> Option; -cons_decode ({nil, _}) -> nil; -cons_decode ({call, _, {atom, _, set_of}, [{atom,_,Type}]}) -> - {set_of, Type}; -cons_decode ({call, _, {atom, _, sequence_of}, [{atom,_,Type}]}) -> - {sequence_of, Type}; -cons_decode ({call,_, {atom, _, default}, [{atom, _, Value}]}) -> - Value. -%cons_decode ({match,_, {atom, _, cardinality}, -% {tuple,_,[{_, _, Low},{_, _, High}]}}) -> -% {cardinality, Low, High}. - - +cons_decode({atom, _, nodefault}) -> ?NO_DEFAULT; +cons_decode({atom, _, Option}) -> Option; +cons_decode({nil, _}) -> nil; +cons_decode({call, _, {atom, _, set_of}, + [{atom, _, Type}]}) -> + {set_of, Type}; +cons_decode({call, _, {atom, _, sequence_of}, + [{atom, _, Type}]}) -> + {sequence_of, Type}; +cons_decode({call, _, {atom, _, default}, + [{atom, _, Value}]}) -> + Value.%cons_decode ({match,_, {atom, _, cardinality}, +%% {tuple,_,[{_, _, Low},{_, _, High}]}}) -> +%% {cardinality, Low, High}. %%==================================================================== %% Func: is_primitive/1 %% Description: checks if a type is primitive %% Returns: true | false %%==================================================================== -is_primitive (string) -> true; -is_primitive (number) -> true; -is_primitive (integer) -> true; -is_primitive (boolean) -> true; -is_primitive (any) -> true; -is_primitive ({sequence_of, X}) -> is_primitive (X); -is_primitive ({set_of, X}) -> is_primitive (X); -is_primitive (_) -> false. - - +is_primitive(string) -> true; +is_primitive(number) -> true; +is_primitive(integer) -> true; +is_primitive(boolean) -> true; +is_primitive(any) -> true; +is_primitive({sequence_of, X}) -> is_primitive(X); +is_primitive({set_of, X}) -> is_primitive(X); +is_primitive(_) -> false. %%==================================================================== %% Func: is_digit/1 %% Description: checks if a slot name is a digit %% Returns: true | false %%==================================================================== -is_digit ('0') -> true; -is_digit ('1') -> true; -is_digit ('2') -> true; -is_digit ('3') -> true; -is_digit ('4') -> true; -is_digit ('5') -> true; -is_digit ('6') -> true; -is_digit ('7') -> true; -is_digit ('8') -> true; -is_digit ('9') -> true; -is_digit (_) -> false. - +is_digit('0') -> true; +is_digit('1') -> true; +is_digit('2') -> true; +is_digit('3') -> true; +is_digit('4') -> true; +is_digit('5') -> true; +is_digit('6') -> true; +is_digit('7') -> true; +is_digit('8') -> true; +is_digit('9') -> true; +is_digit(_) -> false. %%==================================================================== %% Func: resolve_inheritance/1 %% Description: resolves the inheritances in the list of #ontology_class %% Returns: [#ontology_class] %%==================================================================== -resolve_inheritance (Classes) -> - case resolve_inheritance ([], Classes, Classes) of - {false, NewClassList} -> resolve_inheritance (NewClassList); - {true, NewClassList} -> NewClassList - end. - +resolve_inheritance(Classes) -> + case resolve_inheritance([], Classes, Classes) of + {false, NewClassList} -> + resolve_inheritance(NewClassList); + {true, NewClassList} -> NewClassList + end. %%==================================================================== %% Func: resolve_inheritance/3 %% Description: resolves the inheritances in the list of #ontology_class %% Returns: {Solved, [#ontology_class]} %%==================================================================== -resolve_inheritance (Acc, _, []) -> {true, lists:reverse (Acc)}; -resolve_inheritance (Acc, Classes, - [Class = #ontology_class { superclass = nil} | T]) -> - resolve_inheritance ([Class | Acc], Classes, T); -resolve_inheritance (Acc, Classes, [Class | T]) -> - SuperClass = get_class (Class#ontology_class.superclass, Classes), - NewClass = Class#ontology_class { - properties = - lists:foldl (fun (X, A) -> - override_property ([], A, X) - end, - SuperClass#ontology_class.properties, - Class#ontology_class.properties), - superclass = nil}, - {false, lists:reverse ([NewClass | Acc]) ++ T}. - - -override_property (Acc, [], nil) -> lists:reverse (Acc); -override_property (Acc, [], NewProperty = #ontology_property{}) -> - lists:reverse ([NewProperty | Acc]); -override_property (Acc, - [P = #ontology_property { name = N } | T], - NewProperty = #ontology_property {name = N }) -> - override_property ([NewProperty | Acc], T, nil); -override_property (Acc, [P | T], NewProperty) -> - override_property ([P | Acc], T, NewProperty). - +resolve_inheritance(Acc, _, []) -> + {true, lists:reverse(Acc)}; +resolve_inheritance(Acc, Classes, + [Class = #ontology_class{superclass = nil} | T]) -> + resolve_inheritance([Class | Acc], Classes, T); +resolve_inheritance(Acc, Classes, [Class | T]) -> + SuperClass = get_class(Class#ontology_class.superclass, + Classes), + NewClass = Class#ontology_class{properties = + lists:foldl(fun (X, A) -> + override_property([], + A, + X) + end, + SuperClass#ontology_class.properties, + Class#ontology_class.properties), + superclass = nil}, + {false, lists:reverse([NewClass | Acc]) ++ T}. + +override_property(Acc, [], nil) -> lists:reverse(Acc); +override_property(Acc, [], + NewProperty = #ontology_property{}) -> + lists:reverse([NewProperty | Acc]); +override_property(Acc, + [P = #ontology_property{name = N} | T], + NewProperty = #ontology_property{name = N}) -> + override_property([NewProperty | Acc], T, nil); +override_property(Acc, [P | T], NewProperty) -> + override_property([P | Acc], T, NewProperty). %%==================================================================== %% Func: get_class/2 %% Description: Searches for a class in the list %% Returns: #ontology_class %%==================================================================== -get_class (ClassName, []) -> nil; -get_class (ClassName, [Class = #ontology_class { name = ClassName } | T]) -> - Class; -get_class (ClassName, [_ | T]) -> - get_class (ClassName, T). - - +get_class(ClassName, []) -> nil; +get_class(ClassName, + [Class = #ontology_class{name = ClassName} | T]) -> + Class; +get_class(ClassName, [_ | T]) -> + get_class(ClassName, T). %%==================================================================== %% Func: generate_hierarchy_tree/3 %% Description: generates the tree of hierarchies %% Returns: [{classname, [classname]}] %%==================================================================== -generate_hierarchy_tree (Acc, [], _) -> lists:reverse (Acc); -generate_hierarchy_tree (Acc, [Class | T], Classes) -> - Item = {Class#ontology_class.name, - ancestors_list ([], Class#ontology_class.superclass, Classes)}, - generate_hierarchy_tree ([Item | Acc], T, Classes). - - -ancestors_list (Acc, nil, Classes) -> lists:reverse (Acc); -ancestors_list (Acc, X, Classes) -> - C = get_class (X, Classes), - ancestors_list ([X | Acc], C#ontology_class.superclass, Classes). - - - - -reverse_hierarchy_tree (Acc, [], _) -> lists:reverse (Acc); -reverse_hierarchy_tree (Acc, [{Father, _} | T], Classes) -> - Item = {Father, child_list (Father, Classes)}, - reverse_hierarchy_tree ([Item | Acc], T, Classes). - -child_list (Father, Classes) -> - [ C || {C, Ancestors} <- Classes, lists:member (Father, Ancestors)]. - +generate_hierarchy_tree(Acc, [], _) -> + lists:reverse(Acc); +generate_hierarchy_tree(Acc, [Class | T], Classes) -> + Item = {Class#ontology_class.name, + ancestors_list([], Class#ontology_class.superclass, + Classes)}, + generate_hierarchy_tree([Item | Acc], T, Classes). + +ancestors_list(Acc, nil, Classes) -> lists:reverse(Acc); +ancestors_list(Acc, X, Classes) -> + C = get_class(X, Classes), + ancestors_list([X | Acc], C#ontology_class.superclass, + Classes). + +reverse_hierarchy_tree(Acc, [], _) -> + lists:reverse(Acc); +reverse_hierarchy_tree(Acc, [{Father, _} | T], + Classes) -> + Item = {Father, child_list(Father, Classes)}, + reverse_hierarchy_tree([Item | Acc], T, Classes). + +child_list(Father, Classes) -> + [C + || {C, Ancestors} <- Classes, + lists:member(Father, Ancestors)]. %%==================================================================== %% Func: generate_include_file/1 %% Description: generates the include file from a list of #ontology_class %% Returns: [string()] %%==================================================================== -generate_include_file (Classes) -> generate_include_file ([], Classes). - -generate_include_file (Acc, []) -> lists:flatten (lists:reverse (Acc)); -generate_include_file (Acc, [Class | T]) -> - Head = io_lib:format ("-record('~s',{~n", [Class#ontology_class.name]), - Properties = generate_include_lines ([], Class#ontology_class.properties), - Line = lists:flatten ([Head, Properties, "\n"]), - generate_include_file ([Line | Acc], T). +generate_include_file(Classes) -> + generate_include_file([], Classes). +generate_include_file(Acc, []) -> + lists:flatten(lists:reverse(Acc)); +generate_include_file(Acc, [Class | T]) -> + Head = io_lib:format("-record('~s',{~n", + [Class#ontology_class.name]), + Properties = generate_include_lines([], + Class#ontology_class.properties), + Line = lists:flatten([Head, Properties, "\n"]), + generate_include_file([Line | Acc], T). %%==================================================================== %% Func: generate_include_lines/1 %% Description: generates the lines of properties for an include file %% Returns: [string()] %%==================================================================== -generate_include_lines (Acc, []) -> - Line = io_lib:format ("}).~n", []), - lists:reverse ([Line | Acc]); -generate_include_lines (Acc, [Property = #ontology_property - { default = ?NO_DEFAULT }]) -> - Line = io_lib:format (" '~s'", [Property#ontology_property.name]), - generate_include_lines ([Line | Acc], []); -generate_include_lines (Acc, [Property = #ontology_property - { default = ?NO_DEFAULT } | T]) -> - Line = io_lib:format (" '~s',~n", [Property#ontology_property.name]), - generate_include_lines ([Line | Acc], T); -generate_include_lines (Acc, [Property]) -> - Line = io_lib:format (" '~s' = '~s'", - [Property#ontology_property.name, - Property#ontology_property.default]), - generate_include_lines ([Line | Acc], []); -generate_include_lines (Acc, [Property | T]) -> - Line = io_lib:format (" '~s' = '~s',~n", - [Property#ontology_property.name, - Property#ontology_property.default]), - generate_include_lines ([Line | Acc], T). - - - +generate_include_lines(Acc, []) -> + Line = io_lib:format("}).~n", []), + lists:reverse([Line | Acc]); +generate_include_lines(Acc, + [Property = #ontology_property{default = + ?NO_DEFAULT}]) -> + Line = io_lib:format(" '~s'", + [Property#ontology_property.name]), + generate_include_lines([Line | Acc], []); +generate_include_lines(Acc, + [Property = #ontology_property{default = ?NO_DEFAULT} + | T]) -> + Line = io_lib:format(" '~s',~n", + [Property#ontology_property.name]), + generate_include_lines([Line | Acc], T); +generate_include_lines(Acc, [Property]) -> + Line = io_lib:format(" '~s' = '~s'", + [Property#ontology_property.name, + Property#ontology_property.default]), + generate_include_lines([Line | Acc], []); +generate_include_lines(Acc, [Property | T]) -> + Line = io_lib:format(" '~s' = '~s',~n", + [Property#ontology_property.name, + Property#ontology_property.default]), + generate_include_lines([Line | Acc], T). %%==================================================================== %% @@ -394,136 +397,134 @@ generate_include_lines (Acc, [Property | T]) -> %%==================================================================== %% Func: generate_erlang/5 %%==================================================================== -generate_erlang (_, _, _, _, false) -> ok; -generate_erlang (DestPath, FileName, Classes, NewClasses, _) -> - IsAHierarchy = generate_hierarchy_tree ([], Classes, Classes), - %%io:format ("~p~n", [IsAHierarchy]), - FatherOfHierarchy = reverse_hierarchy_tree ([], IsAHierarchy, IsAHierarchy), - %%io:format ("~p~n", [FatherOfHierarchy]), - - IsClassLines = generate_is_class ([], IsAHierarchy), - IsALines = generate_is_a ([], IsAHierarchy), - {CastClasses, CastLines} = - generate_cast ({[],[]}, FatherOfHierarchy, NewClasses), - ChildOfLines = generate_childof ([], FatherOfHierarchy), - - %% - {ok, ErlangFile} = file:open (DestPath ++ "/" ++ - FileName ++ ".erl", [write]), - io:format (ErlangFile, "-module (~s).~n", [FileName]), - io:format (ErlangFile, "-include (\"~s.hrl\").~n", [FileName]), - io:format (ErlangFile, - "-export ([is_class/1, is_a/2, ~s childof/1]).~n~n", - [lists:flatten ( - [io_lib:format ("'~s'/1,", [X]) || X <- CastClasses] - )]), - io:format (ErlangFile, "~s", [IsClassLines]), - io:format (ErlangFile, "~s", [IsALines]), - io:format (ErlangFile, "~s", [ChildOfLines]), - io:format (ErlangFile, "~s", [CastLines]), - file:close (ErlangFile), - ok. +generate_erlang(_, _, _, _, false) -> ok; +generate_erlang(DestPath, FileName, Classes, NewClasses, + _) -> + IsAHierarchy = generate_hierarchy_tree([], Classes, + Classes), + %%io:format ("~p~n", [IsAHierarchy]), + FatherOfHierarchy = reverse_hierarchy_tree([], + IsAHierarchy, IsAHierarchy), + %%io:format ("~p~n", [FatherOfHierarchy]), + IsClassLines = generate_is_class([], IsAHierarchy), + IsALines = generate_is_a([], IsAHierarchy), + {CastClasses, CastLines} = generate_cast({[], []}, + FatherOfHierarchy, NewClasses), + ChildOfLines = generate_childof([], FatherOfHierarchy), + %% + {ok, ErlangFile} = file:open(DestPath ++ + "/" ++ FileName ++ ".erl", + [write]), + io:format(ErlangFile, "-module (~s).~n", [FileName]), + io:format(ErlangFile, "-include (\"~s.hrl\").~n", + [FileName]), + io:format(ErlangFile, + "-export ([is_class/1, is_a/2, ~s childof/1])." + "~n~n", + [lists:flatten([io_lib:format("'~s'/1,", [X]) + || X <- CastClasses])]), + io:format(ErlangFile, "~s", [IsClassLines]), + io:format(ErlangFile, "~s", [IsALines]), + io:format(ErlangFile, "~s", [ChildOfLines]), + io:format(ErlangFile, "~s", [CastLines]), + file:close(ErlangFile), + ok. %%==================================================================== %% Func: generate_childof/2 %% Description: generates the lines for 'childof' functions %% Returns: [string()] %%==================================================================== -generate_childof (Acc, []) -> - lists:flatten ( - lists:reverse (["childof (_) -> exit (undef_class).\n\n" | Acc])); -generate_childof (Acc, [{FatherClassName, Children} | T]) -> - Line = lists:flatten ( - io_lib:format ("childof ('~s') -> ~p;\n", - [FatherClassName, Children])), - generate_childof ([Line | Acc], T). - - +generate_childof(Acc, []) -> + lists:flatten(lists:reverse(["childof (_) -> exit (undef_class).\n\n" + | Acc])); +generate_childof(Acc, + [{FatherClassName, Children} | T]) -> + Line = + lists:flatten(io_lib:format("childof ('~s') -> ~p;\n", + [FatherClassName, Children])), + generate_childof([Line | Acc], T). %%==================================================================== %% Func: generate_is_a/2 %% Description: generates the lines for 'is_a' functions %% Returns: [string()] %%==================================================================== -generate_is_a (Acc, []) -> - lists:flatten (lists:reverse (["is_a (_,_) -> false.\n\n" | Acc])); -generate_is_a (Acc, [{ClassName, []} | T]) -> - generate_is_a (Acc, T); -generate_is_a (Acc, [{ClassName, Ancestors} | T]) -> - Line = [lists:flatten ( - io_lib:format ("is_a ('~s','~s') -> true;\n", - [ClassName, Ancestor])) - || Ancestor <- Ancestors], - generate_is_a ([Line | Acc], T). - +generate_is_a(Acc, []) -> + lists:flatten(lists:reverse(["is_a (_,_) -> false.\n\n" + | Acc])); +generate_is_a(Acc, [{ClassName, []} | T]) -> + generate_is_a(Acc, T); +generate_is_a(Acc, [{ClassName, Ancestors} | T]) -> + Line = + [lists:flatten(io_lib:format("is_a ('~s','~s') -> true;\n", + [ClassName, Ancestor])) + || Ancestor <- Ancestors], + generate_is_a([Line | Acc], T). %%==================================================================== %% Func: generate_is_class/1 %% Description: generates the lines for 'is_class' functions %% Returns: boolean %%==================================================================== -generate_is_class (Acc, []) -> - lists:flatten (lists:reverse (["is_class (_) -> false.\n\n" | Acc])); -generate_is_class (Acc, [{ClassName, _} | T]) -> - Line = lists:flatten ( - io_lib:format ("is_class ('~s') -> true;\n", - [ClassName])), - generate_is_class ([Line | Acc], T). - +generate_is_class(Acc, []) -> + lists:flatten(lists:reverse(["is_class (_) -> false.\n\n" + | Acc])); +generate_is_class(Acc, [{ClassName, _} | T]) -> + Line = + lists:flatten(io_lib:format("is_class ('~s') -> true;\n", + [ClassName])), + generate_is_class([Line | Acc], T). %%==================================================================== %% Func: generate_cast/2 %% Description: generates the lines for cast functions %% Returns: [string()] %%==================================================================== -generate_cast ({Acc1, Acc2}, [], _) -> - {lists:reverse (Acc1), lists:reverse (Acc2)}; -generate_cast ({Acc1, Acc2}, [{ClassName, []} | T], ResolvedClasses) -> - generate_cast ({Acc1, Acc2}, T, ResolvedClasses); -generate_cast ({Acc1, Acc2}, [{ClassName, Children} | T], - ResolvedClasses) -> - - Lines = lists:flatten ( - lists:map ( - fun (X) -> - DestinationClass = get_class (ClassName, ResolvedClasses), - SourceClass = get_class (X, ResolvedClasses), - generate_translation_lines (SourceClass, - DestinationClass) - end, Children)), - [CR, CR, _ | ReversedList] = lists:reverse (Lines), - %%replace last semicolon with a dot to end the clause - NewLines = lists:reverse ([CR, CR, $. | ReversedList]), - generate_cast ({[ClassName | Acc1] , [NewLines | Acc2]}, T, ResolvedClasses). - - - -generate_translation_lines (SourceClass, DestinationClass) -> - Lines = - [ lists:flatten (io_lib:format (" '~s' = X#'~s'.'~s'", - [X#ontology_property.name, +generate_cast({Acc1, Acc2}, [], _) -> + {lists:reverse(Acc1), lists:reverse(Acc2)}; +generate_cast({Acc1, Acc2}, [{ClassName, []} | T], + ResolvedClasses) -> + generate_cast({Acc1, Acc2}, T, ResolvedClasses); +generate_cast({Acc1, Acc2}, [{ClassName, Children} | T], + ResolvedClasses) -> + Lines = lists:flatten([generate_cast_1(V1, ClassName, + ResolvedClasses) + || V1 <- Children]), + [CR, CR, _ | ReversedList] = lists:reverse(Lines), + %%replace last semicolon with a dot to end the clause + NewLines = lists:reverse([CR, CR, $. | ReversedList]), + generate_cast({[ClassName | Acc1], [NewLines | Acc2]}, + T, ResolvedClasses). + +generate_cast_1(X, ClassName, ResolvedClasses) -> + DestinationClass = get_class(ClassName, + ResolvedClasses), + SourceClass = get_class(X, ResolvedClasses), + generate_translation_lines(SourceClass, + DestinationClass). + +generate_translation_lines(SourceClass, + DestinationClass) -> + Lines = + [lists:flatten(io_lib:format(" '~s' = X#'~s'.'~s'", + [X#ontology_property.name, + SourceClass#ontology_class.name, + X#ontology_property.name])) + || X <- DestinationClass#ontology_class.properties], + %%io:format ("~p~n", [Lines]), + XLines = lists:foldl(fun (X, Sum) -> + lists:concat([Sum, ",\n", X]) + end, + "", Lines), + %%io:format ("~p~n", [XLines]), + [_, _ | YLines] = XLines, + Head = + lists:flatten(io_lib:format("'~s' (X = #'~s'{}) ->\n #'~s'{\n", + [DestinationClass#ontology_class.name, SourceClass#ontology_class.name, - X#ontology_property.name])) - || X <- DestinationClass#ontology_class.properties], - %%io:format ("~p~n", [Lines]), - XLines = lists:foldl (fun (X, Sum) -> - lists:concat ([Sum, ",\n", X]) - end, - "", - Lines), - %%io:format ("~p~n", [XLines]), - [_,_ | YLines] = XLines, - Head = lists:flatten ( - io_lib:format ("'~s' (X = #'~s'{}) ->\n #'~s'{\n", - [DestinationClass#ontology_class.name, - SourceClass#ontology_class.name, - DestinationClass#ontology_class.name])), - lists:concat ([Head , - lists:flatten (YLines), - "};\n\n"]). - - - + DestinationClass#ontology_class.name])), + lists:concat([Head, lists:flatten(YLines), "};\n\n"]). %%==================================================================== %% @@ -535,77 +536,76 @@ generate_translation_lines (SourceClass, DestinationClass) -> %%==================================================================== %% Func: generate_sl_codec/4 %%==================================================================== -generate_sl_codec (_, _, _, false) -> ok; -generate_sl_codec (DestPath, FileName, NewClasses, _) -> - EncoderLines = generate_sl_encoder_file (NewClasses), - DecoderLines = generate_sl_decoder_file (NewClasses), - CodecName = FileName ++ "_sl_codec", - {ok, ConversionFile} = file:open (DestPath ++ "/" ++ - CodecName ++ ".erl", [write]), - io:format (ConversionFile, "-module (~s).~n", [CodecName]), - io:format (ConversionFile, "-include (\"acl.hrl\").~n", []), - io:format (ConversionFile, "-include (\"~s.hrl\").~n", - [FileName]), - io:format (ConversionFile, "-export ([encode/1, decode/1]).~n~n", - []), - io:format (ConversionFile, "~s", [EncoderLines]), - io:format (ConversionFile, "~s", [DecoderLines]), - file:close (ConversionFile), - ok. +generate_sl_codec(_, _, _, false) -> ok; +generate_sl_codec(DestPath, FileName, NewClasses, _) -> + EncoderLines = generate_sl_encoder_file(NewClasses), + DecoderLines = generate_sl_decoder_file(NewClasses), + CodecName = FileName ++ "_sl_codec", + {ok, ConversionFile} = file:open(DestPath ++ + "/" ++ CodecName ++ ".erl", + [write]), + io:format(ConversionFile, "-module (~s).~n", + [CodecName]), + io:format(ConversionFile, "-include (\"acl.hrl\").~n", + []), + io:format(ConversionFile, "-include (\"~s.hrl\").~n", + [FileName]), + io:format(ConversionFile, + "-export ([encode/1, decode/1]).~n~n", []), + io:format(ConversionFile, "~s", [EncoderLines]), + io:format(ConversionFile, "~s", [DecoderLines]), + file:close(ConversionFile), + ok. %%==================================================================== %% Func: generate_sl_encoder_file/1 %% Description: generates the SL encode file from a list of #ontology_class %% Returns: [string()] %%==================================================================== -generate_sl_encoder_file (Classes) -> generate_sl_encoder_file ([], Classes). - -generate_sl_encoder_file (Acc, []) -> - lists:flatten ( - lists:reverse ( - [[ - "encode(X) when is_list (X) -> [encode (Y) || Y <- X];\n\n", -%% "encode(X) when is_integer (X) -> integer_to_list (X);\n\n", -%% "encode(X) when is_float (X) -> float_to_list (X);\n\n", - "encode(nil) -> nil;\n\n", - "encode(X) -> exit ({ontology_error,X}).\n\n" - ] | Acc])); -generate_sl_encoder_file (Acc, [Class | T]) -> - Head = io_lib:format ("encode(X) when is_record (X,'~s') ->~n [\"~s\"", - [Class#ontology_class.name, - Class#ontology_class.name]), - Properties = generate_sl_encoder_lines ([], - Class#ontology_class.name, - Class#ontology_class.properties), - Line = lists:flatten ([Head, Properties, "];\n\n"]), - generate_sl_encoder_file ([Line | Acc], T). - +generate_sl_encoder_file(Classes) -> + generate_sl_encoder_file([], Classes). + +generate_sl_encoder_file(Acc, []) -> + lists:flatten(lists:reverse([["encode(X) when is_list (X) -> [encode " + "(Y) || Y <- X];\n\n", + "encode(nil) -> nil;\n\n", + "encode(X) -> exit ({ontology_error,X}).\n\n"] + | Acc])); +generate_sl_encoder_file(Acc, [Class | T]) -> + Head = + io_lib:format("encode(X) when is_record (X,'~s') ->~n " + " [\"~s\"", + [Class#ontology_class.name, Class#ontology_class.name]), + Properties = generate_sl_encoder_lines([], + Class#ontology_class.name, + Class#ontology_class.properties), + Line = lists:flatten([Head, Properties, "];\n\n"]), + generate_sl_encoder_file([Line | Acc], T). %%==================================================================== %% Func: generate_sl_encoder_lines/3 %% Description: generates the lines of the encoder %% Returns: [string()] %%==================================================================== -generate_sl_encoder_lines (Acc, _, []) -> lists:reverse (Acc); -generate_sl_encoder_lines (Acc, ClassName, [Property]) -> - Line = - io_lib:format (",~s", - [field_sl_encode (ClassName, - Property#ontology_property.name, - Property#ontology_property.type, - Property#ontology_property.is_primitive, - Property#ontology_property.is_digit)]), - generate_sl_encoder_lines ([Line | Acc], ClassName, []); -generate_sl_encoder_lines (Acc, ClassName, [Property | T]) -> - Line = - io_lib:format (",~s", - [field_sl_encode (ClassName, - Property#ontology_property.name, - Property#ontology_property.type, - Property#ontology_property.is_primitive, - Property#ontology_property.is_digit)]), - generate_sl_encoder_lines ([Line | Acc], ClassName, T). - +generate_sl_encoder_lines(Acc, _, []) -> + lists:reverse(Acc); +generate_sl_encoder_lines(Acc, ClassName, [Property]) -> + Line = io_lib:format(",~s", + [field_sl_encode(ClassName, + Property#ontology_property.name, + Property#ontology_property.type, + Property#ontology_property.is_primitive, + Property#ontology_property.is_digit)]), + generate_sl_encoder_lines([Line | Acc], ClassName, []); +generate_sl_encoder_lines(Acc, ClassName, + [Property | T]) -> + Line = io_lib:format(",~s", + [field_sl_encode(ClassName, + Property#ontology_property.name, + Property#ontology_property.type, + Property#ontology_property.is_primitive, + Property#ontology_property.is_digit)]), + generate_sl_encoder_lines([Line | Acc], ClassName, T). %%==================================================================== %% Func: field_sl_encode/5 @@ -613,113 +613,94 @@ generate_sl_encoder_lines (Acc, ClassName, [Property | T]) -> %% Returns: string() %%==================================================================== %% field_sl_encode (ClassName, FieldName, Type, IsPrimitive, IsDigit) -field_sl_encode (ClassName, FieldName, {sequence_of, _}, false, false) -> - lists:flatten ( - io_lib:format ("{'~s', [\"sequence\" | encode (X#'~s'.'~s')]}", - [FieldName, ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, {sequence_of, _}, false, true) -> - lists:flatten ( - io_lib:format ("[\"sequence\" | encode (X#'~s'.'~s')]", - [ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, {sequence_of, _}, true, false) -> - lists:flatten ( - io_lib:format ("{'~s', [\"sequence\" | X#'~s'.'~s']}", - [FieldName, ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, {sequence_of, _}, true, true) -> - lists:flatten ( - io_lib:format ("[\"sequence\" | X#'~s'.'~s']", - [ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, {set_of, _}, false, _) -> - lists:flatten ( - io_lib:format ("{'~s', [\"set\" | encode (X#'~s'.'~s') ]}", - [FieldName, ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, {set_of, _}, true, _) -> - lists:flatten ( - io_lib:format ("{'~s',[\"set\" | X#'~s'.'~s' ]}", - [FieldName, ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, _, false, false) -> - lists:flatten ( - io_lib:format ("{'~s', encode (X#'~s'.'~s')}", - [FieldName, ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, FieldType, true, false) -> - lists:flatten ( - io_lib:format ( - "{'~s', ontology:sl_encode_term (X#'~s'.'~s', ~s)}", - [FieldName, ClassName, FieldName, FieldType])); - -field_sl_encode (ClassName, FieldName, _, false, true) -> - lists:flatten ( - io_lib:format ("encode (X#'~s'.'~s')", - [ClassName, FieldName])); - -field_sl_encode (ClassName, FieldName, FieldType, true, true) -> - lists:flatten ( - io_lib:format ("ontology:sl_encode_term (X#'~s'.'~s', ~s)", - [ClassName, FieldName, FieldType])). - +field_sl_encode(ClassName, FieldName, {sequence_of, _}, + false, false) -> + lists:flatten(io_lib:format("{'~s', [\"sequence\" | encode (X#'~s'.'~s')]}", + [FieldName, ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, {sequence_of, _}, + false, true) -> + lists:flatten(io_lib:format("[\"sequence\" | encode (X#'~s'.'~s')]", + [ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, {sequence_of, _}, + true, false) -> + lists:flatten(io_lib:format("{'~s', [\"sequence\" | X#'~s'.'~s']}", + [FieldName, ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, {sequence_of, _}, + true, true) -> + lists:flatten(io_lib:format("[\"sequence\" | X#'~s'.'~s']", + [ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, {set_of, _}, + false, _) -> + lists:flatten(io_lib:format("{'~s', [\"set\" | encode (X#'~s'.'~s') ]}", + [FieldName, ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, {set_of, _}, true, + _) -> + lists:flatten(io_lib:format("{'~s',[\"set\" | X#'~s'.'~s' ]}", + [FieldName, ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, _, false, + false) -> + lists:flatten(io_lib:format("{'~s', encode (X#'~s'.'~s')}", + [FieldName, ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, FieldType, true, + false) -> + lists:flatten(io_lib:format("{'~s', ontology:sl_encode_term (X#'~s'.'~s', " + "~s)}", + [FieldName, ClassName, FieldName, FieldType])); +field_sl_encode(ClassName, FieldName, _, false, true) -> + lists:flatten(io_lib:format("encode (X#'~s'.'~s')", + [ClassName, FieldName])); +field_sl_encode(ClassName, FieldName, FieldType, true, + true) -> + lists:flatten(io_lib:format("ontology:sl_encode_term (X#'~s'.'~s', " + "~s)", + [ClassName, FieldName, FieldType])). %%==================================================================== %% Func: generate_sl_decoder_file/1 %% Description: generates the SL encode file from a list of #ontology_class %% Returns: [string()] %%==================================================================== -generate_sl_decoder_file (Classes) -> generate_sl_decoder_file ([], Classes). - -generate_sl_decoder_file (Acc, []) -> - lists:flatten ( - lists:reverse ( - [["decode(nil) -> nil;\n\n", - "decode(X) -> \n", - " case sl:isList (X) of\n", - " true -> [decode (Y) || Y <- X];\n", - " _ -> X\n", -% " _ -> exit ({ontology_error,X})\n", - " end.\n\n", -% "decode(X) -> exit ({ontology_error,X}).\n\n", - "set_of ([ \"set\" | L]) -> decode (L);\n", - "set_of ([ \"set\", L]) -> decode (L).\n\n", - "sequence_of ([ \"sequence\" | L]) -> decode (L).\n", - "\n"] - | Acc])); -generate_sl_decoder_file (Acc, [Class | T]) -> - -%% PropertyList = -%% [if -%% X#ontology_property.requirement == mandatory -> -%% {'M', X}; -%% true -> -%% {0, X} -%% end || X <- Class#ontology_class.properties], - -%% OptionalPropertyLists = build_optional ([], PropertyList), -%% io:format ("~w~n", [OptionalPropertyLists]), - - OptionalPropertyLists = [Class#ontology_class.properties], - - Line = [generate_sl_decoder_clause (Class, X) || X <- OptionalPropertyLists], - - generate_sl_decoder_file ([Line | Acc], T). - - -generate_sl_decoder_clause (Class, Properties) -> - Head = io_lib:format ("decode([\"~s\" | T]) ->\n", - [Class#ontology_class.name]), - Lines = generate_sl_decoder_lines ([], - Class#ontology_class.name, - Properties), - Line = lists:flatten ([Head, - io_lib:format ( - " #'~s'{", [Class#ontology_class.name]), - Lines, "};\n\n"]), - Line. - +generate_sl_decoder_file(Classes) -> + generate_sl_decoder_file([], Classes). + +generate_sl_decoder_file(Acc, []) -> + lists:flatten(lists:reverse([["decode(nil) -> nil;\n\n", + "decode(X) -> \n", + " case sl:isList (X) of\n", + " true -> [decode (Y) || Y <- X];\n", + " _ -> X\n", " end.\n\n", + "set_of ([ \"set\" | L]) -> decode (L);\n", + "set_of ([ \"set\", L]) -> decode (L).\n\n", + "sequence_of ([ \"sequence\" | L]) -> " + "decode (L).\n", + "\n"] + | Acc])); +generate_sl_decoder_file(Acc, [Class | T]) -> + %% PropertyList = + %% [if + %% X#ontology_property.requirement == mandatory -> + %% {'M', X}; + %% true -> + %% {0, X} + %% end || X <- Class#ontology_class.properties], + %% OptionalPropertyLists = build_optional ([], PropertyList), + %% io:format ("~w~n", [OptionalPropertyLists]), + OptionalPropertyLists = + [Class#ontology_class.properties], + Line = [generate_sl_decoder_clause(Class, X) + || X <- OptionalPropertyLists], + generate_sl_decoder_file([Line | Acc], T). + +generate_sl_decoder_clause(Class, Properties) -> + Head = io_lib:format("decode([\"~s\" | T]) ->\n", + [Class#ontology_class.name]), + Lines = generate_sl_decoder_lines([], + Class#ontology_class.name, Properties), + Line = lists:flatten([Head, + io_lib:format(" #'~s'{", + [Class#ontology_class.name]), + Lines, "};\n\n"]), + Line. %% increment ([]) -> throw (eof); %% increment ([{'M',X} | T]) -> [{'M',X}] ++ increment (T); @@ -741,93 +722,90 @@ generate_sl_decoder_clause (Class, Properties) -> %% Description: generates the lines of the decoder %% Returns: [string()] %%==================================================================== -generate_sl_decoder_lines (Acc, _, []) -> lists:reverse (Acc); -generate_sl_decoder_lines (Acc, ClassName, [Property]) -> - Line = - io_lib:format ("~s", - [sl_decode_term (ClassName, - Property#ontology_property.name, - Property#ontology_property.type, - Property#ontology_property.is_primitive, - Property#ontology_property.is_digit)]), - generate_sl_decoder_lines ([Line | Acc], ClassName, []); -generate_sl_decoder_lines (Acc, ClassName, [Property | T]) -> - Line = - io_lib:format ("~s,", - [sl_decode_term (ClassName, - Property#ontology_property.name, - Property#ontology_property.type, - Property#ontology_property.is_primitive, - Property#ontology_property.is_digit)]), - generate_sl_decoder_lines ([Line | Acc], ClassName, T). - - - -sl_decode_term (ClassName, FieldName, {set_of, _}, false, false) -> - lists:flatten ( - io_lib:format ("'~s' = decode (set_of (sl:get_slot ('~s', T)))", - [FieldName, FieldName])); -sl_decode_term (ClassName, FieldName, {set_of, _}, true, false) -> - lists:flatten (io_lib:format ("'~s' = set_of (sl:get_slot ('~s', T))", +generate_sl_decoder_lines(Acc, _, []) -> + lists:reverse(Acc); +generate_sl_decoder_lines(Acc, ClassName, [Property]) -> + Line = io_lib:format("~s", + [sl_decode_term(ClassName, + Property#ontology_property.name, + Property#ontology_property.type, + Property#ontology_property.is_primitive, + Property#ontology_property.is_digit)]), + generate_sl_decoder_lines([Line | Acc], ClassName, []); +generate_sl_decoder_lines(Acc, ClassName, + [Property | T]) -> + Line = io_lib:format("~s,", + [sl_decode_term(ClassName, + Property#ontology_property.name, + Property#ontology_property.type, + Property#ontology_property.is_primitive, + Property#ontology_property.is_digit)]), + generate_sl_decoder_lines([Line | Acc], ClassName, T). + +sl_decode_term(ClassName, FieldName, {set_of, _}, false, + false) -> + lists:flatten(io_lib:format("'~s' = decode (set_of (sl:get_slot ('~s', " + "T)))", [FieldName, FieldName])); - -sl_decode_term (ClassName, FieldName, {sequence_of, _}, false, false) -> - lists:flatten ( - io_lib:format ("'~s' = decode (sequence_of (sl:get_slot ('~s', T)))", - [FieldName, FieldName])); -sl_decode_term (ClassName, FieldName, {sequence_of, _}, true, false) -> - lists:flatten (io_lib:format ("'~s' = sequence_of (sl:get_slot ('~s', T))", +sl_decode_term(ClassName, FieldName, {set_of, _}, true, + false) -> + lists:flatten(io_lib:format("'~s' = set_of (sl:get_slot ('~s', T))", [FieldName, FieldName])); - -sl_decode_term (ClassName, FieldName, _, false, false) -> - lists:flatten (io_lib:format ("'~s' = decode (sl:get_slot ('~s', T))", +sl_decode_term(ClassName, FieldName, {sequence_of, _}, + false, false) -> + lists:flatten(io_lib:format("'~s' = decode (sequence_of (sl:get_slot " + "('~s', T)))", [FieldName, FieldName])); -sl_decode_term (ClassName, FieldName, FieldType, true, false) -> - lists:flatten ( - io_lib:format ( - "'~s' = ontology:sl_decode_term (sl:get_slot ('~s', T), ~s)", - [FieldName, FieldName, FieldType])); -sl_decode_term (ClassName, FieldName, _, false, true) -> - lists:flatten (io_lib:format ("'~s' = decode (lists:nth (~w, T))", - [FieldName, - digit_of (FieldName) + 1])); -sl_decode_term (ClassName, FieldName, FieldType, true, true) -> - lists:flatten ( - io_lib:format ( - "'~s' = ontology:sl_decode_term (lists:nth (~w,T), ~w)", - [FieldName, digit_of (FieldName) + 1, FieldType])). - - -digit_of ('0') -> 0; -digit_of ('1') -> 1; -digit_of ('2') -> 2; -digit_of ('3') -> 3; -digit_of ('4') -> 4; -digit_of ('5') -> 5; -digit_of ('6') -> 6; -digit_of ('7') -> 7; -digit_of ('8') -> 8; -digit_of ('9') -> 9. - +sl_decode_term(ClassName, FieldName, {sequence_of, _}, + true, false) -> + lists:flatten(io_lib:format("'~s' = sequence_of (sl:get_slot ('~s', " + "T))", + [FieldName, FieldName])); +sl_decode_term(ClassName, FieldName, _, false, false) -> + lists:flatten(io_lib:format("'~s' = decode (sl:get_slot ('~s', T))", + [FieldName, FieldName])); +sl_decode_term(ClassName, FieldName, FieldType, true, + false) -> + lists:flatten(io_lib:format("'~s' = ontology:sl_decode_term (sl:get_slot " + "('~s', T), ~s)", + [FieldName, FieldName, FieldType])); +sl_decode_term(ClassName, FieldName, _, false, true) -> + lists:flatten(io_lib:format("'~s' = decode (lists:nth (~w, T))", + [FieldName, digit_of(FieldName) + 1])); +sl_decode_term(ClassName, FieldName, FieldType, true, + true) -> + lists:flatten(io_lib:format("'~s' = ontology:sl_decode_term (lists:nth " + "(~w,T), ~w)", + [FieldName, digit_of(FieldName) + 1, + FieldType])). + +digit_of('0') -> 0; +digit_of('1') -> 1; +digit_of('2') -> 2; +digit_of('3') -> 3; +digit_of('4') -> 4; +digit_of('5') -> 5; +digit_of('6') -> 6; +digit_of('7') -> 7; +digit_of('8') -> 8; +digit_of('9') -> 9. %%==================================================================== %% Func: sl_encode_term/2 %% Description: converts a generic term into a string %% Returns: string() | nil %%==================================================================== -sl_encode_term (nil, _) -> nil; -sl_encode_term (X, integer) -> integer_to_list (X); -sl_encode_term (X, float) -> float_to_list (X); -sl_encode_term (X, _) -> X. - +sl_encode_term(nil, _) -> nil; +sl_encode_term(X, integer) -> integer_to_list(X); +sl_encode_term(X, float) -> float_to_list(X); +sl_encode_term(X, _) -> X. %%==================================================================== %% Func: sl_decode_term/2 %% Description: converts a string into a generic term %% Returns: term() | nil %%==================================================================== -sl_decode_term (nil, _) -> nil; -sl_decode_term (X, integer) -> list_to_integer (X); -sl_decode_term (X, float) -> list_to_float (X); -sl_decode_term (X, _) -> X. - +sl_decode_term(nil, _) -> nil; +sl_decode_term(X, integer) -> list_to_integer(X); +sl_decode_term(X, float) -> list_to_float(X); +sl_decode_term(X, _) -> X. diff --git a/src/ontology_service.erl b/src/ontology_service.erl index d7380e7..7844ee5 100644 --- a/src/ontology_service.erl +++ b/src/ontology_service.erl @@ -1,27 +1,28 @@ -% -% ontology_service.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (ontology_service). --behaviour (gen_server). +%% +%%ontology_service.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(ontology_service). + +-behaviour(gen_server). %%==================================================================== %% Include files @@ -30,14 +31,10 @@ %%==================================================================== %% External exports %%==================================================================== --export ([register_codec/2, - get_codec/1]). +-export([get_codec/1, register_codec/2]). --export ([init/1, - handle_call/3, - handle_info/2, - terminate/2, - code_change/3]). +-export([code_change/3, handle_call/3, handle_info/2, + init/1, terminate/2]). %%==================================================================== %% External functions @@ -46,9 +43,9 @@ %% Function: register_codec/2 %% Description: registers a new ontology codec %%==================================================================== -register_codec (OntologyName, Codec) -> - gen_server:call (ontology_service, {register, OntologyName, Codec}). - +register_codec(OntologyName, Codec) -> + gen_server:call(ontology_service, + {register, OntologyName, Codec}). %%==================================================================== %% Function: register_codec/2 @@ -56,57 +53,51 @@ register_codec (OntologyName, Codec) -> %% Returns: {ok, CodecName} | %% error %%==================================================================== -get_codec (OntologyName) -> - gen_server:call (ontology_service, {get_codec, OntologyName}). - - +get_codec(OntologyName) -> + gen_server:call(ontology_service, + {get_codec, OntologyName}). %%==================================================================== %% Function: init/1 %% Description: Intializes the server %%==================================================================== -init (_) -> - logger:start ('ONTOLOGY'), - logger:log ('ONTOLOGY', "Started"), - {ok, dict:new ()}. +init(_) -> + logger:start('ONTOLOGY'), + logger:log('ONTOLOGY', "Started"), + {ok, dict:new()}. %%==================================================================== %% Function: handle_call/3 %% Description: handles the requests %%==================================================================== -handle_call ({register, OntologyName, Codec} ,_, Dict) -> - logger:log ('ONTOLOGY', {"Registering Codec ~s for ontology ~s", - [Codec, OntologyName]}), - {reply, ok, dict:store (OntologyName, Codec, Dict)}; - -handle_call ({get_codec, OntologyName} ,_, Dict) -> - Result = dict:find (OntologyName, Dict), +handle_call({register, OntologyName, Codec}, _, Dict) -> + logger:log('ONTOLOGY', + {"Registering Codec ~s for ontology ~s", + [Codec, OntologyName]}), + {reply, ok, dict:store(OntologyName, Codec, Dict)}; +handle_call({get_codec, OntologyName}, _, Dict) -> + Result = dict:find(OntologyName, Dict), case {Result, OntologyName} of - {error, '_'} -> - ok; + {error, '_'} -> ok; {error, _} -> - logger:log ('ONTOLOGY', {"Codec not found for ontology ~s", - [OntologyName]}), + logger:log('ONTOLOGY', + {"Codec not found for ontology ~s", [OntologyName]}), ok; _ -> ok end, {reply, Result, Dict}. - %%==================================================================== %% Function: handle_info/2 %%==================================================================== -handle_info (_, State) -> {noreply, State}. - +handle_info(_, State) -> {noreply, State}. %%==================================================================== %% Function: terminate/2 %%==================================================================== -terminate (_, _) -> ok. - +terminate(_, _) -> ok. %%==================================================================== %% Function: code_change/3 %%==================================================================== -code_change (OldVsn, State, Extra) -> {ok, State}. - +code_change(OldVsn, State, Extra) -> {ok, State}. diff --git a/src/semantics.erl b/src/semantics.erl index 648424c..34b32a4 100644 --- a/src/semantics.erl +++ b/src/semantics.erl @@ -1,37 +1,38 @@ -% -% semantics.erl -% -% ---------------------------------------------------------------------- -% -% eXAT, an erlang eXperimental Agent Tool -% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) -% -% This program is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see -% -% --module (semantics). --export ([extends/0, semantics/1, semantics_/1, - is_feasible/4, rational_effect/4]). --include ("acl.hrl"). +%% +%%semantics.erl +%% +%%---------------------------------------------------------------------- +%% +%% eXAT, an erlang eXperimental Agent Tool +%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it) +%% +%% This program is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation, either version 3 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program. If not, see +%% +%% +-module(semantics). -extends () -> nil. +-export([extends/0, is_feasible/4, rational_effect/4, + semantics/1, semantics_/1]). -semantics (Self) -> nil. +-include("acl.hrl"). -semantics_ (Self) -> nil. +extends() -> nil. -is_feasible (Self, Agent, KB, AclMessage) -> true. +semantics(Self) -> nil. -rational_effect (Self, Agent, KB, AclMessage) -> true. +semantics_(Self) -> nil. +is_feasible(Self, Agent, KB, AclMessage) -> true. + +rational_effect(Self, Agent, KB, AclMessage) -> true. diff --git a/src/simple_agent.erl b/src/simple_agent.erl index 92ed172..0a09bd0 100644 --- a/src/simple_agent.erl +++ b/src/simple_agent.erl @@ -19,63 +19,43 @@ %% You should have received a copy of the GNU General Public License %% along with this program. If not, see - -module(simple_agent). + -behaviour(gen_server). + -include("acl.hrl"). + -include("fipa_ontology.hrl"). --export([new/2, - new/3, - - join/1, - stop/1, - kill/1, - set_rational/3, - get_mind/1, - get_acl_semantics/1, - set_property/3, - get_property/2, - - %% send_message/4, - %% get_message/1, - %% match_message/2, - - init/1, - handle_call/3, - handle_cast/2, - handle_info/2, - code_change/3, - terminate/2]). - --spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}]. -behaviour_info(callbacks) -> - [{init,1},{handle_call,3},{handle_cast,2},{handle_info,2}, - {terminate,2},{code_change,3}]; -behaviour_info(_Other) -> - undefined. - --record(state, {name, - callback, - int_state, - acl_queue, - dict, - process_queue}). + +-export([code_change/3, get_acl_semantics/1, get_mind/1, + get_property/2, handle_call/3, handle_cast/2, + handle_info/2, init/1, join/1, kill/1, new/2, new/3, + set_property/3, set_rational/3, stop/1, terminate/2]). + +%% send_message/4, +%% get_message/1, +%% match_message/2, + +- spec ( { { behaviour_info , 1 } , [ { type , 50 , 'fun' , [ { type , 50 , product , [ { type , 50 , atom , [ ] } ] } , { type , 50 , union , [ { atom , 50 , undefined } , { type , 50 , list , [ { type , 50 , tuple , [ { type , 50 , atom , [ ] } , { type , 50 , arity , [ ] } ] } ] } ] } ] } ] } ) . + + +-record(state, + {name, callback, int_state, acl_queue, dict, + process_queue}). new(AgentName, Callback) -> new(AgentName, Callback, []). new(AgentName, Callback, Parameters) -> {ok, _} = gen_server:start({local, AgentName}, - simple_agent, - [AgentName, Callback, Parameters], []), + simple_agent, [AgentName, Callback, Parameters], + []), ok. - %% %% MAIN CALLS %% -join(_Agent) -> - erlang:error(notimpl). +join(_Agent) -> erlang:error(notimpl). set_property(_Agent, _Property, _Value) -> erlang:error(notimpl). @@ -83,23 +63,17 @@ set_property(_Agent, _Property, _Value) -> get_property(_Agent, _Property) -> erlang:error(notimpl). - set_rational(_Pid, _EngineName, _SemanticsClass) -> erlang:error(notimpl). -get_mind(_Pid) -> - erlang:error(notimpl). - -get_acl_semantics(_Pid) -> - erlang:error(notimpl). +get_mind(_Pid) -> erlang:error(notimpl). +get_acl_semantics(_Pid) -> erlang:error(notimpl). stop(Agent) -> gen_server:cast(Agent, '$simple_agent_stop'). -kill(Agent) -> - stop(Agent). - +kill(Agent) -> stop(Agent). %% %% CALLBACKS @@ -110,17 +84,20 @@ kill(Agent) -> %% init(Args) -> process_flag(trap_exit, true), - [ AgentName, Callback, Parameters | _ ] = Args, + [AgentName, Callback, Parameters | _] = Args, ams:register_agent(AgentName), {ok, IntState} = Callback:init(AgentName, Parameters), - {ok, #state{name = AgentName, - callback = Callback, - int_state = IntState}}. + {ok, + #state{name = AgentName, callback = Callback, + int_state = IntState}}. %% %% Terminate %% -terminate(Reason, #state{callback = Callback, name = AgentName, int_state = IntState} = _State) -> +terminate(Reason, + #state{callback = Callback, name = AgentName, + int_state = IntState} = + _State) -> ams:de_register_agent(AgentName), ok = Callback:terminate(Reason, IntState), ok. @@ -128,41 +105,46 @@ terminate(Reason, #state{callback = Callback, name = AgentName, int_state = IntS %% %% Gets a property from agent %% -handle_call({get_property, _PropertyName}, _From, #state{} = State) -> +handle_call({get_property, _PropertyName}, _From, + #state{} = State) -> {reply, {error, notimpl}, State}; - %% %% Sets a property %% -handle_call({set_property, _PropertyName, _PropertyValue}, _From, #state{} = State) -> +handle_call({set_property, _PropertyName, + _PropertyValue}, + _From, #state{} = State) -> {reply, {error, notimpl}, State}; - - - %% %% Receives an ACL message in String format %% -handle_call([acl, AclStr], _From, #state{int_state = IntState, callback = Callback} = State) -> +handle_call([acl, AclStr], _From, + #state{int_state = IntState, callback = Callback} = + State) -> %%io:format("[Agent] Received ACL=~s\n", [Acl]), - case catch(acl:parse_message(AclStr)) of - {'EXIT', _Reason} -> - {reply, ok, State}; + case catch acl:parse_message(AclStr) of + {'EXIT', _Reason} -> {reply, ok, State}; Acl -> - {noreply, IntState2} = Callback:handle_acl(Acl, IntState), + {noreply, IntState2} = Callback:handle_acl(Acl, + IntState), {reply, ok, State#state{int_state = IntState2}} end; - %% %% Receives an ACL message in Erlang format %% -handle_call([acl_erl_native, Acl], _From, #state{int_state = IntState, callback = Callback} = State) -> - {noreply, IntState2} = Callback:handle_acl(Acl, IntState), +handle_call([acl_erl_native, Acl], _From, + #state{int_state = IntState, callback = Callback} = + State) -> + {noreply, IntState2} = Callback:handle_acl(Acl, + IntState), {reply, ok, State#state{int_state = IntState2}}; - -handle_call(Call, From, #state{int_state = IntState, callback = Callback} = State) -> +handle_call(Call, From, + #state{int_state = IntState, callback = Callback} = + State) -> R = Callback:handle_call(Call, From, IntState), IntState2 = element(size(R), R), - setelement(size(R), R, State#state{int_state = IntState2}). + setelement(size(R), R, + State#state{int_state = IntState2}). %% %% Stops the agent process @@ -170,23 +152,30 @@ handle_call(Call, From, #state{int_state = IntState, callback = Callback} = Stat handle_cast('$simple_agent_stop', State) -> {stop, normal, State}; - -handle_cast(Cast, #state{int_state = IntState, callback = Callback} = State) -> +handle_cast(Cast, + #state{int_state = IntState, callback = Callback} = + State) -> R = Callback:handle_cast(Cast, IntState), IntState2 = element(size(R), R), - setelement(size(R), R, State#state{int_state = IntState2}). + setelement(size(R), R, + State#state{int_state = IntState2}). - -handle_info(Msg, #state{int_state = IntState, callback = Callback} = State) -> +handle_info(Msg, + #state{int_state = IntState, callback = Callback} = + State) -> R = Callback:handle_info(Msg, IntState), IntState2 = element(size(R), R), - setelement(size(R), R, State#state{int_state = IntState2}). - -code_change(OldVsn, #state{int_state = IntState, callback = Callback} = State, Extra) -> - {ok, IntState2} = Callback:code_change(OldVsn, IntState, Extra), + setelement(size(R), R, + State#state{int_state = IntState2}). + +code_change(OldVsn, + #state{int_state = IntState, callback = Callback} = + State, + Extra) -> + {ok, IntState2} = Callback:code_change(OldVsn, IntState, + Extra), {ok, State#state{int_state = IntState2}}. - %% extract_agent_identifier(AgentOrObject) when record(AgentOrObject, 'agent-identifier') -> %% AgentOrObject#'agent-identifier'.name; %% extract_agent_identifier(AgentOrObject) when record(AgentOrObject, object) -> diff --git a/src/sl.erl b/src/sl.erl index 69ce350..23705b7 100644 --- a/src/sl.erl +++ b/src/sl.erl @@ -20,47 +20,41 @@ %% along with this program. If not, see %% %% --module (sl). +-module(sl). + %%==================================================================== %% Include files %%==================================================================== --include ("acl.hrl"). --include ("ontology.hrl"). +-include("acl.hrl"). + +-include("ontology.hrl"). %%==================================================================== %% External exports %%==================================================================== --export ([decode/1, - decode/3, - encode/1, - isList/1, - isString/1, - get_slot/2, - replace_slot/3]). - +-export([decode/1, decode/3, encode/1, get_slot/2, + isList/1, isString/1, replace_slot/3]). %%==================================================================== %% Func: decode/1 %%==================================================================== -decode (Message) -> - decode (Message, ascii_sl, ontology). +decode(Message) -> decode(Message, ascii_sl, ontology). %%==================================================================== %% Func: decode/3 %%==================================================================== -decode (AsciiMessage, ascii_sl, erlang_sl) -> +decode(AsciiMessage, ascii_sl, erlang_sl) -> %%io:format ("ASCII ~s~n", [AsciiMessage]), - T = tokenize (AsciiMessage), - sl_parser:parse (T); -decode (SLMessage, erlang_sl, ontology) -> - fipa_ontology_sl_codec:decode (SLMessage); -decode (AsciiMessage, ascii_sl, ontology) -> - {ok, ErlangSL} = decode (AsciiMessage, ascii_sl, erlang_sl), + T = tokenize(AsciiMessage), + sl_parser:parse(T); +decode(SLMessage, erlang_sl, ontology) -> + fipa_ontology_sl_codec:decode(SLMessage); +decode(AsciiMessage, ascii_sl, ontology) -> + {ok, ErlangSL} = decode(AsciiMessage, ascii_sl, + erlang_sl), %%io:format ("~w~n", [ErlangSL]), - decode (ErlangSL, erlang_sl, ontology). - - + decode(ErlangSL, erlang_sl, ontology). %%==================================================================== %% Func: encode/1 @@ -68,33 +62,35 @@ decode (AsciiMessage, ascii_sl, ontology) -> %% Returns: ASCIIForm %%==================================================================== encode(Message) -> - binary_to_list(iolist_to_binary(encode (Message, isList (Message)))). - - -encode (X, true) -> % isList - [ "(", encode_list_terms ([], X), ")" ]; -encode ({_, ?ACL_ANY}, false) -> % is not List - [ ]; -encode ({SlotName, SlotValue}, false) -> % is not List - [ ":", atom_to_list (SlotName), " ", - encode (SlotValue, isList (SlotValue)) , " " ]; -encode (TermValue, false) -> % is String + binary_to_list(iolist_to_binary(encode(Message, + isList(Message)))). + +encode(X, + true) -> % isList + ["(", encode_list_terms([], X), ")"]; +encode({_, ?ACL_ANY}, + false) -> % is not List + []; +encode({SlotName, SlotValue}, + false) -> % is not List + [":", atom_to_list(SlotName), " ", + encode(SlotValue, isList(SlotValue)), " "]; +encode(TermValue, + false) -> % is String [TermValue, " "]. - -encode_list_terms (Acc, []) -> lists:reverse (Acc); -encode_list_terms (Acc, [H|T]) -> - Encoding = encode (H, isList (H)), - encode_list_terms ([Encoding | Acc], T). - +encode_list_terms(Acc, []) -> lists:reverse(Acc); +encode_list_terms(Acc, [H | T]) -> + Encoding = encode(H, isList(H)), + encode_list_terms([Encoding | Acc], T). %%==================================================================== %% Func: get_slot/2 %% Description: returns the value of a given slot name %% Returns: Value | ?ACL_ANY %%==================================================================== -get_slot (Key, List) -> - case lists:keysearch (Key, 1, List) of +get_slot(Key, List) -> + case lists:keysearch(Key, 1, List) of {value, {_, Value}} -> Value; _ -> ?ACL_ANY end. @@ -104,39 +100,36 @@ get_slot (Key, List) -> %% Description: changes the value of a given slot name %% Returns: None %%==================================================================== -replace_slot (Key, List, NewValue) -> - lists:keyreplace (Key, 1, List, {Key, NewValue}). +replace_slot(Key, List, NewValue) -> + lists:keyreplace(Key, 1, List, {Key, NewValue}). %%==================================================================== %% Func: isList/1 %% Description: Checks if the given data is a list of strings %% Returns: true | false %%==================================================================== -isList ([]) -> false; -isList ([H | _]) when is_number (H) -> false; -isList ([H | _]) when is_binary (H) -> true; -isList ([H | _]) when is_list (H) -> true; -isList (X) when is_binary (X) -> false; -isList (X) when is_tuple (X) -> false; -isList (_) -> true. - +isList([]) -> false; +isList([H | _]) when is_number(H) -> false; +isList([H | _]) when is_binary(H) -> true; +isList([H | _]) when is_list(H) -> true; +isList(X) when is_binary(X) -> false; +isList(X) when is_tuple(X) -> false; +isList(_) -> true. %%==================================================================== %% Func: isString/1 %% Description: Checks if the given data is a strings %% Returns: true | false %%==================================================================== -isString ([]) -> true; -isString ([H | T]) when is_number (H) -> isString (T); -isString ([H | T]) when is_binary (H) -> isString (T); -isString (_) -> false. - +isString([]) -> true; +isString([H | T]) when is_number(H) -> isString(T); +isString([H | T]) when is_binary(H) -> isString(T); +isString(_) -> false. %%==================================================================== %% Internal functions %%==================================================================== -tokenize ([]) -> [{'$end',1}]; -tokenize ([H|T]) -> [ {list_to_atom ([H]),1} | tokenize (T) ]. - - +tokenize([]) -> [{'$end', 1}]; +tokenize([H | T]) -> + [{list_to_atom([H]), 1} | tokenize(T)]. diff --git a/src/sync.erl b/src/sync.erl index 8e5d74a..02f4fd7 100644 --- a/src/sync.erl +++ b/src/sync.erl @@ -1,145 +1,130 @@ -% -% sync.erl -% -% A synchronizer object -% -% ---------------------------------------------------------------------- -% Copyright (c) 2003-04, Corrado Santoro -% Department of Computer and Telecommunication Engineering, -% University of Catania, Italy. All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% -% * Redistributions of source code must retain the above copyright notice, -% this list of conditions and the following disclaimer. -% -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% -% * Neither the name of Corrado Santoro nor the names of its -% contributors may be used to endorse or promote products derived from this -% software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% --module (sync). --export ([extends/0, - sync/1, - sync_/1, - wait/1, - signal/1, - signal/2, - signal_all/1, - signal_all/2, - wait_queue/2]). - --define (SYNC_PID, '__sync_pid__'). - -extends () -> nil. - -sync (Self) -> - object:set (Self, ?SYNC_PID, spawn (?MODULE, wait_queue, [[],[]])). - -sync_ (Self) -> - Pid = object:get (Self, ?SYNC_PID), - catch (exit (Pid, kill)). - -wait (Self) -> - Pid = object:get (Self, ?SYNC_PID), - Pid ! {wait, self()}, - receive - X -> X - end. - -signal (Self, Data) -> - Pid = object:get (Self, ?SYNC_PID), - Pid ! {signal, Data}. - -signal (Self) -> signal (Self, ok). - -signal_all (Self, Data) -> - Pid = object:get (Self, ?SYNC_PID), - Pid ! {signal_all, Data}. - -signal_all (Self) -> signal_all (Self, ok). - -% -% the wait server -% -wait_queue (AwaitingProcesses, AwaitingTokens) -> - receive - {wait, P} -> - if - length (AwaitingTokens) == 0 -> - wait_queue (AwaitingProcesses ++ [P], []); - true -> - [Token | _] = AwaitingTokens, - self () ! Token, - wait_queue (AwaitingProcesses ++ [P], []) - end; - {signal, Data} -> - %io:format ("AwaitingProcesses = ~w\n", [AwaitingProcesses]), - if - length (AwaitingProcesses) == 0 -> - wait_queue (AwaitingProcesses, [{signal, Data}]); - true -> - [First | Tail] = AwaitingProcesses, - do_signal (First, Data), - wait_queue (Tail, []) - end; - {signal_all, Data} -> - if - length (AwaitingProcesses) == 0 -> - wait_queue (AwaitingProcesses, [{signal_all, Data}]); - true -> - do_signal_all (AwaitingProcesses, Data), - wait_queue ([], []) - end; - _ -> - wait_queue (AwaitingProcesses, AwaitingTokens) - end. - - -do_signal (P, Data) -> - %io:format ("Signalling to ~w\n", [P]), - P ! Data. - -do_signal_all ([], Data) -> ok; -do_signal_all ([H|T], Data) -> - do_signal (H, Data), - do_signal_all (T, Data). - -% -% CONSTRAINT!!! The 'wait' method MUST BE called from the same process -% that created the 'sync' object! -% -% public () -> [wait, signal]. - -% sync (Self) -> -% object:set (Self, ?SYNC_PID, self ()). - -% wait (Self) -> -% receive -% X -> X -% end. - -% signal (Self, Data) -> -% case catch (object:get (Self, ?SYNC_PID)) of -% {'EXIT', _} -> ok; -% Pid -> catch (Pid ! Data), ok -% end. - -% signal (Self) -> signal (Self, ok). - +%% +%%sync.erl +%% +%%A synchronizer object +%% +%%---------------------------------------------------------------------- +%%Copyright (c) 2003-04, Corrado Santoro +%%Department of Computer and Telecommunication Engineering, +%%University of Catania, Italy. All rights reserved. +%% +%%Redistribution and use in source and binary forms, with or without +%%modification, are permitted provided that the following conditions are met: +%% +%%* Redistributions of source code must retain the above copyright notice, +%% this list of conditions and the following disclaimer. +%% +%%* Redistributions in binary form must reproduce the above copyright +%% notice, this list of conditions and the following disclaimer in the +%% documentation and/or other materials provided with the distribution. +%% +%%* Neither the name of Corrado Santoro nor the names of its +%% contributors may be used to endorse or promote products derived from this +%% software without specific prior written permission. +%% +%%THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +%%AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +%%IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +%%ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +%%LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +%%CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +%%SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +%%INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +%%CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +%%ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +%%POSSIBILITY OF SUCH DAMAGE. +%% +-module(sync). + +-export([extends/0, signal/1, signal/2, signal_all/1, + signal_all/2, sync/1, sync_/1, wait/1, wait_queue/2]). + +-define(SYNC_PID, '__sync_pid__'). + +extends() -> nil. + +sync(Self) -> + object:set(Self, ?SYNC_PID, + spawn(?MODULE, wait_queue, [[], []])). + +sync_(Self) -> + Pid = object:get(Self, ?SYNC_PID), + catch exit(Pid, kill). + +wait(Self) -> + Pid = object:get(Self, ?SYNC_PID), + Pid ! {wait, self()}, + receive X -> X end. + +signal(Self, Data) -> + Pid = object:get(Self, ?SYNC_PID), Pid ! {signal, Data}. + +signal(Self) -> signal(Self, ok). + +signal_all(Self, Data) -> + Pid = object:get(Self, ?SYNC_PID), + Pid ! {signal_all, Data}. + +signal_all(Self) -> signal_all(Self, ok). + +%% +%%the wait server +%% +wait_queue(AwaitingProcesses, AwaitingTokens) -> + receive + {wait, P} -> + if length(AwaitingTokens) == 0 -> + wait_queue(AwaitingProcesses ++ [P], []); + true -> + [Token | _] = AwaitingTokens, + self() ! Token, + wait_queue(AwaitingProcesses ++ [P], []) + end; + {signal, Data} -> + %%io:format ("AwaitingProcesses = ~w\n", [AwaitingProcesses]), + if length(AwaitingProcesses) == 0 -> + wait_queue(AwaitingProcesses, [{signal, Data}]); + true -> + [First | Tail] = AwaitingProcesses, + do_signal(First, Data), + wait_queue(Tail, []) + end; + {signal_all, Data} -> + if length(AwaitingProcesses) == 0 -> + wait_queue(AwaitingProcesses, [{signal_all, Data}]); + true -> + do_signal_all(AwaitingProcesses, Data), + wait_queue([], []) + end; + _ -> wait_queue(AwaitingProcesses, AwaitingTokens) + end. + +do_signal(P, Data) -> + %%io:format ("Signalling to ~w\n", [P]), + P ! Data. + +do_signal_all([], Data) -> ok; +do_signal_all([H | T], Data) -> + do_signal(H, Data), do_signal_all(T, Data). + +%% +%%CONSTRAINT!!! The 'wait' method MUST BE called from the same process +%%that created the 'sync' object! +%% +%%public () -> [wait, signal]. + +%%sync (Self) -> +%% object:set (Self, ?SYNC_PID, self ()). + +%%wait (Self) -> +%% receive +%% X -> X +%% end. + +%%signal (Self, Data) -> +%% case catch (object:get (Self, ?SYNC_PID)) of +%% {'EXIT', _} -> ok; +%% Pid -> catch (Pid ! Data), ok +%% end. + +%%signal (Self) -> signal (Self, ok).