1 |
|
%%% ==================================================================== |
2 |
|
%%% ``The contents of this file are subject to the Erlang Public License, |
3 |
|
%%% Version 1.1, (the "License"); you may not use this file except in |
4 |
|
%%% compliance with the License. You should have received a copy of the |
5 |
|
%%% Erlang Public License along with this software. If not, it can be |
6 |
|
%%% retrieved via the world wide web at http://www.erlang.org/. |
7 |
|
%%% |
8 |
|
%%% |
9 |
|
%%% Software distributed under the License is distributed on an "AS IS" |
10 |
|
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See |
11 |
|
%%% the License for the specific language governing rights and limitations |
12 |
|
%%% under the License. |
13 |
|
%%% |
14 |
|
%%% |
15 |
|
%%% The Initial Developer of the Original Code is ProcessOne. |
16 |
|
%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne |
17 |
|
%%% All Rights Reserved.'' |
18 |
|
%%% This software is copyright 2006-2015, ProcessOne. |
19 |
|
%%% |
20 |
|
%%% |
21 |
|
%%% @copyright 2006-2015 ProcessOne |
22 |
|
%%% @author Christophe Romain <christophe.romain@process-one.net> |
23 |
|
%%% [http://www.process-one.net/] |
24 |
|
%%% @end |
25 |
|
%%% ==================================================================== |
26 |
|
|
27 |
|
%%% @doc The module <strong>{@module}</strong> is the default PubSub node tree plugin. |
28 |
|
%%% <p>It is used as a default for all unknown PubSub node type. It can serve |
29 |
|
%%% as a developer basis and reference to build its own custom pubsub node tree |
30 |
|
%%% types.</p> |
31 |
|
%%% <p>PubSub node tree plugins are using the {@link gen_nodetree} behaviour.</p> |
32 |
|
%%% <p><strong>The API isn't stabilized yet</strong>. The pubsub plugin |
33 |
|
%%% development is still a work in progress. However, the system is already |
34 |
|
%%% useable and useful as is. Please, send us comments, feedback and |
35 |
|
%%% improvements.</p> |
36 |
|
|
37 |
|
-module(nodetree_tree). |
38 |
|
-behaviour(gen_pubsub_nodetree). |
39 |
|
-author('christophe.romain@process-one.net'). |
40 |
|
|
41 |
|
-include_lib("stdlib/include/qlc.hrl"). |
42 |
|
|
43 |
|
-include("pubsub.hrl"). |
44 |
|
-include("jlib.hrl"). |
45 |
|
|
46 |
|
-export([init/2, terminate/2, set_node/1, |
47 |
|
get_node/2, get_node/1, get_nodes/2, |
48 |
|
get_parentnodes_tree/3, |
49 |
|
get_subnodes/3, create_node/6, |
50 |
|
delete_node/2]). |
51 |
|
|
52 |
|
-define(MOD_PUBSUB_DB_BACKEND, mod_pubsub_db_backend). |
53 |
|
-ignore_xref([ |
54 |
|
{?MOD_PUBSUB_DB_BACKEND, set_node, 1}, |
55 |
|
{?MOD_PUBSUB_DB_BACKEND, get_subnodes, 2}, |
56 |
|
{?MOD_PUBSUB_DB_BACKEND, find_node_by_name, 2}, |
57 |
|
{?MOD_PUBSUB_DB_BACKEND, find_nodes_by_key, 1}, |
58 |
|
{?MOD_PUBSUB_DB_BACKEND, get_subnodes_tree, 2}, |
59 |
|
{?MOD_PUBSUB_DB_BACKEND, find_node_by_id, 1} |
60 |
|
]). |
61 |
|
|
62 |
|
init(_HostType, _Options) -> |
63 |
35 |
ok. |
64 |
|
|
65 |
|
terminate(_Host, _ServerHost) -> |
66 |
35 |
ok. |
67 |
|
|
68 |
|
set_node(Node) -> |
69 |
91 |
mod_pubsub_db_backend:set_node(Node). |
70 |
|
|
71 |
|
get_node(Host, Node) -> |
72 |
242 |
case catch mod_pubsub_db_backend:find_node_by_name(Host, Node) of |
73 |
235 |
#pubsub_node{} = Record -> Record; |
74 |
7 |
_ -> {error, mongoose_xmpp_errors:item_not_found()} |
75 |
|
end. |
76 |
|
|
77 |
|
get_node(Nidx) -> |
78 |
242 |
case catch mod_pubsub_db_backend:find_node_by_id(Nidx) of |
79 |
242 |
{ok, Node} -> Node; |
80 |
:-( |
_ -> {error, mongoose_xmpp_errors:item_not_found()} |
81 |
|
end. |
82 |
|
|
83 |
|
get_nodes(Key, _From) -> |
84 |
32 |
mod_pubsub_db_backend:find_nodes_by_key(Key). |
85 |
|
|
86 |
|
%% @doc <p>Default node tree does not handle parents, return a list |
87 |
|
%% containing just this node.</p> |
88 |
|
get_parentnodes_tree(Host, Node, _From) -> |
89 |
210 |
case catch mod_pubsub_db_backend:find_node_by_name(Host, Node) of |
90 |
210 |
#pubsub_node{} = Record -> [{0, [Record]}]; |
91 |
:-( |
_ -> [] |
92 |
|
end. |
93 |
|
|
94 |
|
get_subnodes(Host, Node, _From) -> |
95 |
6 |
mod_pubsub_db_backend:get_subnodes(Host, Node). |
96 |
|
|
97 |
|
create_node(Host, NodeName, Type, Owner, Options, Parents) -> |
98 |
87 |
BJID = jid:to_lower(jid:to_bare(Owner)), |
99 |
87 |
case catch mod_pubsub_db_backend:find_node_by_name(Host, NodeName) of |
100 |
|
false -> |
101 |
87 |
case check_parent_and_its_owner_list(Host, Parents, BJID) of |
102 |
|
true -> |
103 |
86 |
Node = #pubsub_node{nodeid = {Host, NodeName}, |
104 |
|
parents = Parents, |
105 |
|
type = Type, owners = [BJID], |
106 |
|
options = Options}, |
107 |
86 |
set_node(Node); |
108 |
|
false -> |
109 |
1 |
{error, mongoose_xmpp_errors:forbidden()} |
110 |
|
end; |
111 |
|
_ -> |
112 |
:-( |
{error, mongoose_xmpp_errors:conflict()} |
113 |
|
end. |
114 |
|
|
115 |
|
check_parent_and_its_owner_list({_U, _S, _R}, _Parents, _BJID) -> |
116 |
|
%% This is special case for PEP handling |
117 |
|
%% PEP does not uses hierarchy |
118 |
3 |
true; |
119 |
|
check_parent_and_its_owner_list(_Host, [], _BJID) -> |
120 |
76 |
true; |
121 |
|
check_parent_and_its_owner_list(Host, [Parent | _], BJID) -> |
122 |
8 |
case catch mod_pubsub_db_backend:find_node_by_name(Host, Parent) of |
123 |
|
#pubsub_node{owners = [{<<>>, Host, <<>>}]} -> |
124 |
4 |
true; |
125 |
|
#pubsub_node{owners = Owners} -> |
126 |
3 |
lists:member(BJID, Owners); |
127 |
|
_ -> |
128 |
1 |
false |
129 |
|
end; |
130 |
|
check_parent_and_its_owner_list(_Host, _Parents, _BJID) -> |
131 |
:-( |
false. |
132 |
|
|
133 |
|
delete_node(Host, Node) -> |
134 |
69 |
SubNodesTree = mod_pubsub_db_backend:get_subnodes_tree(Host, Node), |
135 |
69 |
Removed = lists:flatten([Nodes || {_, Nodes} <- SubNodesTree]), |
136 |
69 |
lists:foreach(fun (NodeToDel) -> |
137 |
70 |
mod_pubsub_db_backend:delete_node(NodeToDel) |
138 |
|
end, |
139 |
|
Removed), |
140 |
69 |
Removed. |
141 |
|
|