PageRenderTime 322ms CodeModel.GetById 121ms app.highlight 85ms RepoModel.GetById 76ms app.codeStats 0ms

/ucengine/src/helpers/json_helpers.erl

http://github.com/AF83/ucengine
Erlang | 200 lines | 157 code | 23 blank | 20 comment | 1 complexity | 511752514ac4d842121cd675f319bb2a MD5 | raw file
  1%%
  2%%  U.C.Engine - Unified Collaboration Engine
  3%%  Copyright (C) 2011 af83
  4%%
  5%%  This program is free software: you can redistribute it and/or modify
  6%%  it under the terms of the GNU Affero General Public License as published by
  7%%  the Free Software Foundation, either version 3 of the License, or
  8%%  (at your option) any later version.
  9%%
 10%%  This program is distributed in the hope that it will be useful,
 11%%  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12%%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13%%  GNU Affero General Public License for more details.
 14%%
 15%%  You should have received a copy of the GNU Affero General Public License
 16%%  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 17%%
 18-module(json_helpers).
 19
 20-compile({no_auto_import,[error/2]}).
 21
 22-include("uce.hrl").
 23
 24-export([format_response/4,
 25         unexpected_error/1,
 26         error/2,
 27         error/3,
 28         ok/1,
 29         true/1,
 30         false/1,
 31         created/1,
 32         created/2,
 33         json/2,
 34         json/3,
 35         to_json/2,
 36         to_struct/1]).
 37
 38format_response(Status, Headers, Content) ->
 39    format_response(Status, "application/json", Headers, to_struct(Content)).
 40
 41format_response(Status, ContentType, Headers, Content) ->
 42    Body = mochijson:encode(Content),
 43    [{status, Status},
 44     {content, ContentType, lists:flatten(Body)}] ++ Headers.
 45
 46add_cors_headers(Domain) ->
 47    cors_helpers:format_cors_headers(Domain).
 48
 49unexpected_error(Domain) ->
 50    format_response(500, add_cors_headers(Domain), [{error, unexpected_error}]).
 51
 52error(Domain, Reason) ->
 53    Code = http_helpers:error_to_code(Reason),
 54    format_response(Code, add_cors_headers(Domain), [{error, Reason}]).
 55error(Domain, Reason, Infos) ->
 56    Code = http_helpers:error_to_code(Reason),
 57    format_response(Code, add_cors_headers(Domain), [{error, Reason}, {infos, Infos}]).
 58
 59ok(Domain) ->
 60    format_response(200, add_cors_headers(Domain), [{result, ok}]).
 61
 62true(Domain) ->
 63    format_response(200, add_cors_headers(Domain), [{result, "true"}]).
 64
 65false(Domain) ->
 66    format_response(200, add_cors_headers(Domain), [{result, "false"}]).
 67
 68created(Domain) ->
 69    format_response(201, add_cors_headers(Domain), [{result, created}]).
 70
 71created(Domain, Id) ->
 72    format_response(201, add_cors_headers(Domain), [{result, Id}]).
 73
 74json(Domain, Content) ->
 75    json(Domain, 200, Content).
 76
 77json(Domain, Status, Content) ->
 78    format_response(Status, add_cors_headers(Domain), [{result, to_json(Domain, Content)}]).
 79%%
 80%% Transform usual records to JSON
 81%%
 82to_json(Domain, Records) when is_list(Records) ->
 83    {array, [to_json(Domain, Record) || Record <- Records]};
 84to_json(_Domain, #uce_access{action=Action,
 85                             object=Object,
 86                             conditions=Conditions}) ->
 87    {struct,
 88     [{action, Action},
 89      {object, Object},
 90      {conditions, Conditions}]};
 91to_json(Domain, #uce_meeting{id=Name,
 92                             metadata=Metadata}) ->
 93    {struct, [{name, Name},
 94              {domain, Domain},
 95              {metadata, Metadata}]};
 96to_json(Domain, #uce_event{id=Id,
 97                           datetime=Datetime,
 98                           location=Location,
 99                           from=From,
100                           type=Type,
101                           to=To,
102                           parent=Parent,
103                           metadata=Metadata}) ->
104    JSONTo = case To of
105                 "" ->
106                     [];
107                 ToId ->
108                     [{to, ToId}]
109             end,
110
111    JSONLocation = case Location of
112                       "" ->
113                           [];
114                       Meeting ->
115                           [{location, Meeting}]
116                   end,
117    JSONParent = case Parent of
118                     "" ->
119                         [];
120                     _ ->
121                         [{parent, Parent}]
122                 end,
123    Metadata2 = case Metadata of
124                    {struct, _} ->
125                        Metadata;
126                    _ ->
127                        {struct, Metadata}
128                end,
129    {struct,
130     [{type, Type},
131      {domain, Domain},
132      {datetime, Datetime},
133      {id, Id}] ++
134         JSONLocation ++
135         JSONTo ++
136         [{from, From}] ++
137         JSONParent ++
138         [{metadata, Metadata2}]};
139to_json(Domain, #uce_file{id=Id,
140                          name=Name,
141                          location=Location,
142                          uri=Uri,
143                          metadata=Metadata}) ->
144    JSONLocation = [{location, Location}],
145    {struct, [{id, Id},
146              {domain, Domain},
147              {name, Name},
148              {uri, Uri}] ++ JSONLocation ++
149         [{metadata, Metadata}]};
150to_json(Domain, #uce_presence{id=Id,
151                              user=User,
152                              auth=Auth}) ->
153    {struct,
154     [{id, Id},
155      {domain, Domain},
156      {user, User},
157      {auth, Auth}]};
158to_json(Domain, #uce_user{id=Id,
159                          name=Name,
160                          auth=Auth,
161                          metadata=Metadata}) ->
162    {struct, [{uid, Id},
163              {name, Name},
164              {domain, Domain},
165              {auth, Auth},
166              {metadata, to_struct(Metadata)}]};
167to_json(_Domain, Json) ->
168    Json.
169
170-spec to_struct([{string() | atom(), any()}]) -> {struct, [{string() | atom(), any()}]}.
171to_struct({struct, _} = Struct) ->
172    Struct;
173to_struct(Proplist) ->
174    {struct, Proplist}.
175
176
177-ifdef(TEST).
178-include_lib("eunit/include/eunit.hrl").
179
180unexpected_error_test() ->
181    ?assertMatch([{status, 500}, {content, "application/json", "{\"error\":\"unexpected_error\"}"},
182                 {header, "Access-Control-Allow-Origin: *"},
183                 {header, "Access-Control-Allow-Methods: GET, POST, PUT, DELETE"},
184                 {header, "Access-Control-Allow-Headers: X-Requested-With"}], unexpected_error("")).
185
186error_test() ->
187    ?assertMatch([{status, 400}, {content, "application/json", "{\"error\":\"bad_parameters\"}"},
188                  {header, "Access-Control-Allow-Origin: *"},
189                  {header, "Access-Control-Allow-Methods: GET, POST, PUT, DELETE"},
190                  {header, "Access-Control-Allow-Headers: X-Requested-With"}], error("", bad_parameters)),
191    ?assertMatch([{status, 500}, {content, "application/json", "{\"error\":\"hello_world\"}"},
192                  {header, "Access-Control-Allow-Origin: *"},
193                  {header, "Access-Control-Allow-Methods: GET, POST, PUT, DELETE"},
194                  {header, "Access-Control-Allow-Headers: X-Requested-With"}], error("", "hello_world")).
195
196format_response_test() ->
197    ?assertMatch([{status, 200}, {content, "application/json", "{}"}], format_response(200, [], [])),
198    ?assertMatch([{status, 200}, {content, "application/json", "{}"}, {header, "X-Plop: plop"}, {header, "Host: ucengine.org"}], format_response(200, [{header, "X-Plop: plop"}, {header, "Host: ucengine.org"}], [])).
199
200-endif.