Current section

Files

Jump to
couchbeam src couchbeam_doc.erl
Raw

src/couchbeam_doc.erl

%%% -*- erlang -*-
%%%
%%% This file is part of couchbeam released under the MIT license.
%%% See the NOTICE for more information.
-module(couchbeam_doc).
-author('Benoit Chesneau').
-include("couchbeam.hrl").
-export([set_value/3, get_value/2, get_value/3,
take_value/2, take_value/3,
delete_value/2, extend/2, extend/3]).
-export([get_id/1, get_rev/1, get_idrev/1, is_saved/1]).
-spec get_id(doc()) -> binary().
%% @doc get document id.
get_id(Doc) ->
get_value(<<"_id">>, Doc).
-spec get_rev(doc()) -> binary().
%% @doc get document revision.
get_rev(Doc) ->
get_value(<<"_rev">>, Doc).
-spec get_idrev(doc()) -> {binary(), binary()}.
%% @doc get a tuple containing docucment id and revision.
get_idrev(Doc) ->
DocId = get_value(<<"_id">>, Doc),
DocRev = get_value(<<"_rev">>, Doc),
{DocId, DocRev}.
-spec is_saved(doc()) -> boolean().
%% @doc If document have been saved (revision is defined) return true,
%% else, return false.
is_saved(Doc) ->
case get_value(<<"_rev">>, Doc) of
undefined -> false;
_ -> true
end.
-spec set_value(binary() | list(), term(), doc()) -> doc().
%% @doc set a value for a key in jsonobj. If key exists it will be updated.
set_value(Key, Value, JsonObj) when is_list(Key)->
set_value(list_to_binary(Key), Value, JsonObj);
set_value(Key, Value, JsonObj) when is_binary(Key), is_map(JsonObj) ->
maps:put(Key, Value, JsonObj).
-spec get_value(binary() | list(), doc()) -> term().
%% @doc Returns the value of a simple key/value property in json object
%% Equivalent to get_value(Key, JsonObj, undefined).
get_value(Key, JsonObj) ->
get_value(Key, JsonObj, undefined).
-spec get_value(binary() | list(), doc(), term()) -> term().
%% @doc Returns the value of a simple key/value property in json object
get_value(Key, JsonObj, Default) when is_list(Key) ->
get_value(list_to_binary(Key), JsonObj, Default);
get_value(Key, JsonObj, Default) when is_binary(Key), is_map(JsonObj) ->
maps:get(Key, JsonObj, Default).
-spec take_value(binary() | list(), doc()) -> {term(), doc()}.
%% @doc Returns the value of a simple key/value property in json object and deletes
%% it form json object
%% Equivalent to take_value(Key, JsonObj, undefined).
take_value(Key, JsonObj) ->
take_value(Key, JsonObj, undefined).
-spec take_value(binary() | list(), doc(), term()) -> {term(), doc()}.
%% @doc Returns the value of a simple key/value property in json object and deletes
%% it from json object
take_value(Key, JsonObj, Default) when is_list(Key) ->
take_value(list_to_binary(Key), JsonObj, Default);
take_value(Key, JsonObj, Default) when is_binary(Key), is_map(JsonObj) ->
case maps:is_key(Key, JsonObj) of
true ->
{maps:get(Key, JsonObj), maps:remove(Key, JsonObj)};
false ->
{Default, JsonObj}
end.
-spec delete_value(binary() | list(), doc()) -> doc().
%% @doc Deletes all entries associated with Key in json object.
delete_value(Key, JsonObj) when is_list(Key) ->
delete_value(list_to_binary(Key), JsonObj);
delete_value(Key, JsonObj) when is_binary(Key), is_map(JsonObj) ->
maps:remove(Key, JsonObj).
-spec extend(binary(), ejson_term(), doc()) -> doc().
%% @doc extend a jsonobject by key, value
extend(Key, Value, JsonObj) ->
extend({Key, Value}, JsonObj).
-spec extend(term(), doc()) -> doc().
%% @doc extend a jsonobject by a property, list of property or another jsonobject
extend([], JsonObj) ->
JsonObj;
extend({List}, JsonObj) when is_list(List) ->
extend(List, JsonObj);
extend([Prop|R], JsonObj)->
NewObj = extend(Prop, JsonObj),
extend(R, NewObj);
extend({Key, Value}, JsonObj) ->
set_value(Key, Value, JsonObj).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
get_value_test() ->
Doc = #{<<"a">> => 1},
?assertEqual(1, couchbeam_doc:get_value(<<"a">>, Doc)),
?assertEqual(1, couchbeam_doc:get_value(<<"a">>, Doc)),
?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc)),
?assertEqual(nil, couchbeam_doc:get_value(<<"b">>, Doc, nil)),
ok.
set_value_test() ->
Doc = #{<<"a">> => 1},
?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc)),
Doc1 = couchbeam_doc:set_value(<<"b">>, 1, Doc),
?assertEqual(1, couchbeam_doc:get_value(<<"b">>, Doc1)),
Doc2 = couchbeam_doc:set_value(<<"b">>, 0, Doc1),
?assertEqual(0, couchbeam_doc:get_value(<<"b">>, Doc2)),
ok.
delete_value_test() ->
Doc = #{<<"a">> => 1, <<"b">> => 1},
Doc1 = couchbeam_doc:delete_value("b", Doc),
?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc1)),
ok.
extend_test() ->
Doc = #{<<"a">> => 1},
?assertEqual(1, couchbeam_doc:get_value(<<"a">>, Doc)),
?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc)),
?assertEqual(undefined, couchbeam_doc:get_value(<<"c">>, Doc)),
Doc1 = couchbeam_doc:extend([{<<"b">>, 1}, {<<"c">>, 1}], Doc),
?assertEqual(1, couchbeam_doc:get_value(<<"b">>, Doc1)),
?assertEqual(1, couchbeam_doc:get_value(<<"c">>, Doc1)),
Doc2 = couchbeam_doc:extend([{<<"b">>, 3}, {<<"d">>, 1}], Doc1),
?assertEqual(3, couchbeam_doc:get_value(<<"b">>, Doc2)),
?assertEqual(1, couchbeam_doc:get_value(<<"d">>, Doc2)),
ok.
id_rev_test() ->
Doc = #{<<"a">> => 1},
?assertEqual(undefined, couchbeam_doc:get_id(Doc)),
?assertEqual(undefined, couchbeam_doc:get_rev(Doc)),
?assertEqual({undefined, undefined}, couchbeam_doc:get_idrev(Doc)),
Doc1 = couchbeam_doc:extend([{<<"_id">>, 1}, {<<"_rev">>, 1}], Doc),
?assertEqual(1, couchbeam_doc:get_id(Doc1)),
?assertEqual(1, couchbeam_doc:get_rev(Doc1)),
?assertEqual({1, 1}, couchbeam_doc:get_idrev(Doc1)),
ok.
is_saved_test() ->
Doc = #{<<"a">> => 1},
?assertEqual(false, couchbeam_doc:is_saved(Doc)),
Doc1 = couchbeam_doc:set_value(<<"_rev">>, <<"x">>, Doc),
?assertEqual(true, couchbeam_doc:is_saved(Doc1)),
ok.
take_value_test() ->
Doc = #{<<"a">> => 1, <<"b">> => 2},
?assertEqual({undefined, Doc}, couchbeam_doc:take_value(<<"c">>, Doc)),
?assertEqual({1, #{<<"b">> => 2}}, couchbeam_doc:take_value(<<"a">>, Doc)),
ok.
-endif.