diff options
author | Badlop <badlop@process-one.net> | 2013-03-14 10:33:02 +0100 |
---|---|---|
committer | Badlop <badlop@process-one.net> | 2013-03-14 10:33:02 +0100 |
commit | 9deb294328bb3f9eb6bd2c0e7cd500732e9b5830 (patch) | |
tree | 7e1066c130250627ee0abab44a135f583a28d07f /src/mod_pubsub/nodetree_tree_odbc.erl | |
parent | list_to_integer/2 only works in OTP R14 and newer (diff) |
Accumulated patch to binarize and indent code
Diffstat (limited to '')
-rw-r--r-- | src/mod_pubsub/nodetree_tree_odbc.erl | 533 |
1 files changed, 314 insertions, 219 deletions
diff --git a/src/mod_pubsub/nodetree_tree_odbc.erl b/src/mod_pubsub/nodetree_tree_odbc.erl index f4b9737c9..9756b897b 100644 --- a/src/mod_pubsub/nodetree_tree_odbc.erl +++ b/src/mod_pubsub/nodetree_tree_odbc.erl @@ -5,11 +5,13 @@ %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. %%% +%%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. %%% +%%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2013, ProcessOne %%% All Rights Reserved.'' @@ -34,32 +36,24 @@ %%% improvements.</p> -module(nodetree_tree_odbc). + -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). + -include("jlib.hrl"). -define(PUBSUB, mod_pubsub_odbc). --define(PLUGIN_PREFIX, "node_"). + +-define(PLUGIN_PREFIX, <<"node_">>). -behaviour(gen_pubsub_nodetree). --export([init/3, - terminate/2, - options/0, - set_node/1, - get_node/3, - get_node/2, - get_node/1, - get_nodes/2, - get_nodes/1, - get_parentnodes/3, - get_parentnodes_tree/3, - get_subnodes/3, - get_subnodes_tree/3, - create_node/6, - delete_node/2 - ]). +-export([init/3, terminate/2, options/0, set_node/1, + get_node/3, get_node/2, get_node/1, get_nodes/2, + get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, + get_subnodes/3, get_subnodes_tree/3, create_node/6, + delete_node/2]). -export([raw_to_node/2]). @@ -76,67 +70,87 @@ %% <p>This function is mainly used to trigger the setup task necessary for the %% plugin. It can be used for example by the developer to create the specific %% module database schema if it does not exists yet.</p> -init(_Host, _ServerHost, _Opts) -> - ok. -terminate(_Host, _ServerHost) -> - ok. - %% @spec () -> [Option] %% Option = mod_pubsub:nodetreeOption() %% @doc Returns the default pubsub node tree options. -options() -> - [{virtual_tree, false}, - {odbc, true}]. - %% @spec (Host, Node, From) -> pubsubNode() | {error, Reason} %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() -get_node(Host, Node, _From) -> - get_node(Host, Node). +init(_Host, _ServerHost, _Opts) -> ok. + +terminate(_Host, _ServerHost) -> ok. + +options() -> [{virtual_tree, false}, {odbc, true}]. + +get_node(Host, Node, _From) -> get_node(Host, Node). + +-spec(get_node/2 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId()) + -> mod_pubsub:pubsubNode() + | {error, _} +). get_node(Host, Node) -> - H = ?PUBSUB:escape(Host), - N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), - case catch ejabberd_odbc:sql_query_t( - ["select node, parent, type, nodeid " - "from pubsub_node " - "where host='", H, "' and node='", N, "';"]) + H = (?PUBSUB):escape(Host), + N = (?PUBSUB):escape(Node), + case catch + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"' and node='">>, N, <<"';">>]) of - {selected, ["node", "parent", "type", "nodeid"], [RItem]} -> - raw_to_node(Host, RItem); - {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], + [RItem]} -> + raw_to_node(Host, RItem); + {'EXIT', _Reason} -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} end. -get_node(NodeId) -> - case catch ejabberd_odbc:sql_query_t( - ["select host, node, parent, type " - "from pubsub_node " - "where nodeid='", NodeId, "';"]) + +-spec(get_node/1 :: +( + NodeIdx::mod_pubsub:nodeIdx()) + -> mod_pubsub:pubsubNode() + | {error, _} +). +get_node(NodeIdx) -> + case catch + ejabberd_odbc:sql_query_t([<<"select host, node, parent, type from " + "pubsub_node where nodeid='">>, + NodeIdx, <<"';">>]) of - {selected, ["host", "node", "parent", "type"], [{Host, Node, Parent, Type}]} -> - raw_to_node(Host, {Node, Parent, Type, NodeId}); - {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {selected, + [<<"host">>, <<"node">>, <<"parent">>, <<"type">>], + [{Host, Node, Parent, Type}]} -> + raw_to_node(Host, {Node, Parent, Type, NodeIdx}); + {'EXIT', _Reason} -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} end. %% @spec (Host, From) -> [pubsubNode()] | {error, Reason} %% Host = mod_pubsub:host() | mod_pubsub:jid() -get_nodes(Host, _From) -> - get_nodes(Host). +get_nodes(Host, _From) -> get_nodes(Host). + +-spec(get_nodes/1 :: +( + Host::mod_pubsub:host()) + -> [mod_pubsub:pubsubNode()] +). get_nodes(Host) -> - H = ?PUBSUB:escape(Host), - case catch ejabberd_odbc:sql_query_t( - ["select node, parent, type, nodeid " - "from pubsub_node " - "where host='", H, "';"]) + H = (?PUBSUB):escape(Host), + case catch + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"';">>]) of - {selected, ["node", "parent", "type", "nodeid"], RItems} -> - lists:map(fun(Item) -> raw_to_node(Host, Item) end, RItems); - _ -> - [] + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], + RItems} -> + lists:map(fun (Item) -> raw_to_node(Host, Item) end, + RItems); + _ -> [] end. %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} @@ -146,9 +160,6 @@ get_nodes(Host) -> %% Depth = integer() %% Record = pubsubNode() %% @doc <p>Default node tree does not handle parents, return empty list.</p> -get_parentnodes(_Host, _Node, _From) -> - []. - %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} %% Host = mod_pubsub:host() | mod_pubsub:jid() %% Node = mod_pubsub:pubsubNode() @@ -157,10 +168,20 @@ get_parentnodes(_Host, _Node, _From) -> %% Record = pubsubNode() %% @doc <p>Default node tree does not handle parents, return a list %% containing just this node.</p> +get_parentnodes(_Host, _Node, _From) -> []. + +-spec(get_parentnodes_tree/3 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId(), + From :: jid()) + -> [{0, [mod_pubsub:pubsubNode(),...]}] +). + get_parentnodes_tree(Host, Node, From) -> case get_node(Host, Node, From) of - N when is_record(N, pubsub_node) -> [{0, [N]}]; - _Error -> [] + N when is_record(N, pubsub_node) -> [{0, [N]}]; + _Error -> [] end. get_subnodes(Host, Node, _From) -> @@ -169,18 +190,26 @@ get_subnodes(Host, Node, _From) -> %% @spec (Host, Index) -> [pubsubNode()] | {error, Reason} %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() +-spec(get_subnodes/2 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId()) + -> [mod_pubsub:pubsubNode()] +). get_subnodes(Host, Node) -> - H = ?PUBSUB:escape(Host), - N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), - case catch ejabberd_odbc:sql_query_t( - ["select node, parent, type, nodeid " - "from pubsub_node " - "where host='", H, "' and parent='", N, "';"]) + H = (?PUBSUB):escape(Host), + N = (?PUBSUB):escape(Node), + case catch + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"' and parent='">>, N, <<"';">>]) of - {selected, ["node", "parent", "type", "nodeid"], RItems} -> - lists:map(fun(Item) -> raw_to_node(Host, Item) end, RItems); - _ -> - [] + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], + RItems} -> + lists:map(fun (Item) -> raw_to_node(Host, Item) end, + RItems); + _ -> [] end. get_subnodes_tree(Host, Node, _From) -> @@ -189,18 +218,27 @@ get_subnodes_tree(Host, Node, _From) -> %% @spec (Host, Index) -> [pubsubNode()] | {error, Reason} %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() +-spec(get_subnodes_tree/2 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId()) + -> [mod_pubsub:pubsubNode()] +). + get_subnodes_tree(Host, Node) -> - H = ?PUBSUB:escape(Host), - N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), - case catch ejabberd_odbc:sql_query_t( - ["select node, parent, type, nodeid " - "from pubsub_node " - "where host='", H, "' and node like '", N, "%';"]) + H = (?PUBSUB):escape(Host), + N = (?PUBSUB):escape(Node), + case catch + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"' and node like '">>, N, <<"%';">>]) of - {selected, ["node", "parent", "type", "nodeid"], RItems} -> - lists:map(fun(Item) -> raw_to_node(Host, Item) end, RItems); - _ -> - [] + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], + RItems} -> + lists:map(fun (Item) -> raw_to_node(Host, Item) end, + RItems); + _ -> [] end. %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason} @@ -210,162 +248,219 @@ get_subnodes_tree(Host, Node) -> %% Owner = mod_pubsub:jid() %% Options = list() %% Parents = list() + +-spec(create_node/6 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId(), + Type :: binary(), + Owner :: jid(), + Options :: mod_pubsub:nodeOptions(), + Parents :: [mod_pubsub:nodeId()]) + -> {ok, NodeIdx::mod_pubsub:nodeIdx()} + %%% + | {error, _} +). + create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), case nodeid(Host, Node) of - {error, ?ERR_ITEM_NOT_FOUND} -> - ParentExists = - case Host of - {_U, _S, _R} -> - %% This is special case for PEP handling - %% PEP does not uses hierarchy - true; - _ -> - case Parents of - [] -> true; - [Parent|_] -> - case nodeid(Host, Parent) of - {result, PNodeId} -> - case nodeowners(PNodeId) of - [{[], Host, []}] -> true; - Owners -> lists:member(BJID, Owners) - end; - _ -> - false - end; - _ -> - false - end - end, - case ParentExists of - true -> - case set_node(#pubsub_node{ - nodeid={Host, Node}, - parents=Parents, - type=Type, - options=Options}) of - {result, NodeId} -> {ok, NodeId}; - Other -> Other - end; - false -> - %% Requesting entity is prohibited from creating nodes - {error, ?ERR_FORBIDDEN} - end; - {result, _} -> - %% NodeID already exists - {error, ?ERR_CONFLICT}; - Error -> - Error + {error, ?ERR_ITEM_NOT_FOUND} -> + ParentExists = case Host of + {_U, _S, _R} -> + %% This is special case for PEP handling + %% PEP does not uses hierarchy + true; + _ -> + case Parents of + [] -> true; + [Parent | _] -> + case nodeid(Host, Parent) of + {result, PNodeId} -> + case nodeowners(PNodeId) of + [{<<>>, Host, <<>>}] -> true; + Owners -> + lists:member(BJID, Owners) + end; + _ -> false + end; + _ -> false + end + end, + case ParentExists of + true -> + case set_node(#pubsub_node{nodeid = {Host, Node}, + parents = Parents, type = Type, + options = Options}) + of + {result, NodeId} -> {ok, NodeId}; + Other -> Other + end; + false -> {error, ?ERR_FORBIDDEN} + end; + {result, _} -> {error, ?ERR_CONFLICT}; + Error -> Error end. %% @spec (Host, Node) -> [mod_pubsub:node()] %% Host = mod_pubsub:host() | mod_pubsub:jid() %% Node = mod_pubsub:pubsubNode() +-spec(delete_node/2 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId()) + -> [mod_pubsub:pubsubNode()] +). + delete_node(Host, Node) -> - H = ?PUBSUB:escape(Host), - N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), + H = (?PUBSUB):escape(Host), + N = (?PUBSUB):escape(Node), Removed = get_subnodes_tree(Host, Node), - catch ejabberd_odbc:sql_query_t( - ["delete from pubsub_node " - "where host='", H, "' and node like '", N, "%';"]), + catch + ejabberd_odbc:sql_query_t([<<"delete from pubsub_node where host='">>, + H, <<"' and node like '">>, N, <<"%';">>]), Removed. %% helpers - -raw_to_node(Host, {Node, Parent, Type, NodeId}) -> - Options = case catch ejabberd_odbc:sql_query_t( - ["select name,val " - "from pubsub_node_option " - "where nodeid='", NodeId, "';"]) +-spec(raw_to_node/2 :: +( + Host :: mod_pubus:host(), + _ :: {NodeId::mod_pubsub:nodeId(), + Parent::mod_pubsub:nodeId(), + Type::binary(), + NodeIdx::mod_pubsub:nodeIdx()}) + -> mod_pubsub:pubsubNode() +). +raw_to_node(Host, {Node, Parent, Type, NodeIdx}) -> + Options = case catch + ejabberd_odbc:sql_query_t([<<"select name,val from pubsub_node_option " + "where nodeid='">>, + NodeIdx, <<"';">>]) of - {selected, ["name", "val"], ROptions} -> - DbOpts = lists:map(fun({Key, Value}) -> - RKey = list_to_atom(Key), - Tokens = element(2, erl_scan:string(Value++".")), - RValue = element(2, erl_parse:parse_term(Tokens)), - {RKey, RValue} - end, ROptions), - Module = list_to_atom(?PLUGIN_PREFIX++Type), - StdOpts = Module:options(), - lists:foldl(fun({Key, Value}, Acc)-> - lists:keyreplace(Key, 1, Acc, {Key, Value}) - end, StdOpts, DbOpts); - _ -> - [] + {selected, [<<"name">>, <<"val">>], ROptions} -> + DbOpts = lists:map(fun ({Key, Value}) -> + RKey = + jlib:binary_to_atom(Key), + Tokens = element(2, + erl_scan:string(<<Value/binary, + ".">>)), + RValue = element(2, + erl_parse:parse_term(Tokens)), + {RKey, RValue} + end, + ROptions), + Module = + jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, + Type/binary>>), + StdOpts = Module:options(), + lists:foldl(fun ({Key, Value}, Acc) -> + lists:keyreplace(Key, 1, Acc, + {Key, Value}) + end, + StdOpts, DbOpts); + _ -> [] end, - #pubsub_node{ - nodeid = {Host, ?PUBSUB:string_to_node(Node)}, - parents = [?PUBSUB:string_to_node(Parent)], - id = NodeId, - type = Type, - options = Options}. - %% @spec (NodeRecord) -> ok | {error, Reason} %% Record = mod_pubsub:pubsub_node() + #pubsub_node{nodeid = + {Host, Node}, + parents = [Parent], + id = NodeIdx, type = Type, options = Options}. + +-spec(set_node/1 :: +( + Record::mod_pubsub:pubsubNode()) + -> {result, NodeIdx::mod_pubsub:nodeIdx()} + %%% + | {error, _} +). set_node(Record) -> {Host, Node} = Record#pubsub_node.nodeid, Parent = case Record#pubsub_node.parents of - [] -> <<>>; - [First|_] -> First - end, + [] -> <<>>; + [First | _] -> First + end, Type = Record#pubsub_node.type, - H = ?PUBSUB:escape(Host), - N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), - P = ?PUBSUB:escape(?PUBSUB:node_to_string(Parent)), - NodeId = case nodeid(Host, Node) of - {result, OldNodeId} -> - catch ejabberd_odbc:sql_query_t( - ["delete from pubsub_node_option " - "where nodeid='", OldNodeId, "';"]), - catch ejabberd_odbc:sql_query_t( - ["update pubsub_node " - "set host='", H, "' " - "node='", N, "' " - "parent='", P, "' " - "type='", Type, "' " - "where nodeid='", OldNodeId, "';"]), - OldNodeId; - _ -> - catch ejabberd_odbc:sql_query_t( - ["insert into pubsub_node(host, node, parent, type) " - "values('", H, "', '", N, "', '", P, "', '", Type, "');"]), - case nodeid(Host, Node) of - {result, NewNodeId} -> NewNodeId; - _ -> none % this should not happen - end + H = (?PUBSUB):escape(Host), + N = (?PUBSUB):escape(Node), + P = (?PUBSUB):escape(Parent), + NodeIdx = case nodeid(Host, Node) of + {result, OldNodeIdx} -> + catch + ejabberd_odbc:sql_query_t([<<"delete from pubsub_node_option where " + "nodeid='">>, + OldNodeIdx, <<"';">>]), + catch + ejabberd_odbc:sql_query_t([<<"update pubsub_node set host='">>, + H, <<"' node='">>, N, + <<"' parent='">>, P, + <<"' type='">>, Type, + <<"' where nodeid='">>, + OldNodeIdx, <<"';">>]), + OldNodeIdx; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_node(host, node, " + "parent, type) values('">>, + H, <<"', '">>, N, <<"', '">>, P, + <<"', '">>, Type, <<"');">>]), + case nodeid(Host, Node) of + {result, NewNodeIdx} -> NewNodeIdx; + _ -> none % this should not happen + end end, - case NodeId of - none -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> - lists:foreach(fun({Key, Value}) -> - SKey = atom_to_list(Key), - SValue = ?PUBSUB:escape(lists:flatten(io_lib:fwrite("~p",[Value]))), - catch ejabberd_odbc:sql_query_t( - ["insert into pubsub_node_option(nodeid, name, val) " - "values('", NodeId, "', '", SKey, "', '", SValue, "');"]) - end, Record#pubsub_node.options), - {result, NodeId} + case NodeIdx of + none -> {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> + lists:foreach(fun ({Key, Value}) -> + SKey = iolist_to_binary(atom_to_list(Key)), + SValue = + (?PUBSUB):escape(lists:flatten(io_lib:fwrite("~p", + [Value]))), + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_node_option(nodeid, " + "name, val) values('">>, + NodeIdx, <<"', '">>, + SKey, <<"', '">>, + SValue, <<"');">>]) + end, + Record#pubsub_node.options), + {result, NodeIdx} end. -nodeid(Host, Node) -> - H = ?PUBSUB:escape(Host), - N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), - case catch ejabberd_odbc:sql_query_t( - ["select nodeid " - "from pubsub_node " - "where host='", H, "' and node='", N, "';"]) +-spec(nodeid/2 :: +( + Host :: mod_pubsub:host(), + NodeId :: mod_pubsub:nodeId()) + -> {result, NodeIdx::mod_pubsub:nodeIdx()} + %%% + | {error, _} +). + +nodeid(Host, NodeId) -> + H = (?PUBSUB):escape(Host), + N = (?PUBSUB):escape(NodeId), + case catch + ejabberd_odbc:sql_query_t([<<"select nodeid from pubsub_node where " + "host='">>, + H, <<"' and node='">>, N, <<"';">>]) of - {selected, ["nodeid"], [{NodeId}]} -> - {result, NodeId}; - {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {selected, [<<"nodeid">>], [{NodeIdx}]} -> + {result, NodeIdx}; + {'EXIT', _Reason} -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} end. -nodeowners(NodeId) -> - {result, Res} = node_hometree_odbc:get_node_affiliations(NodeId), - lists:foldl(fun({LJID, owner}, Acc) -> [LJID|Acc]; - (_, Acc) -> Acc - end, [], Res). +-spec(nodeowners/1 :: +( + NodeIdx::mod_pubsub:nodeIdx()) + -> Node_Owners::[ljid()] +). + +nodeowners(NodeIdx) -> + {result, Res} = node_hometree_odbc:get_node_affiliations(NodeIdx), + lists:foldl(fun ({LJID, owner}, Acc) -> [LJID | Acc]; + (_, Acc) -> Acc + end, + [], Res). |