<commit_before>%% -------------------------------------------------------------------
%%
%% lasp_orset: A convergent, replicated, state based observe remove set
%%
%% Copyright (c) 2007-2012 Basho Technologies, Inc.  All Rights Reserved.
%%
%% This file is provided to you under the Apache License,
%% Version 2.0 (the "License"); you may not use this file
%% except in compliance with the License.  You may obtain
%% a copy of the License at
%%
%%   http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied.  See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%
%% -------------------------------------------------------------------

%% @doc This module is a fork of the riak_dt_orset, which is modified to
%%      support some additional update functions needed for correctly
%%      composing objects in Riak.

-module(lasp_orset).

-behaviour(riak_dt).

%% API
-export([new/0, value/1, update/3, update_delta/3, merge/2, equal/2,
         to_binary/1, from_binary/1, value/2, precondition_context/1,
         stats/1, stat/2]).
-export([update/4, parent_clock/2]).
-export([to_binary/2]).
-export([to_version/2]).
-export([intersect/2, map/2, filter/2]).

-ifdef(EQC).
-include_lib("eqc/include/eqc.hrl").
-endif.

-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.

%% EQC API
-ifdef(EQC).
-export([init_state/0, gen_op/0, update_expected/3, eqc_state_value/1]).
-endif.

-export_type([orset/0, binary_orset/0, orset_op/0]).
-opaque orset() :: orddict:orddict().

%% A binary that from_binary/1 will operate on.
-type binary_orset() :: binary().

-type orset_op() :: {add, member()} | {remove, member()} |
                    {add_all, [member()]} | {remove_all, [member()]} |
                    {update, [orset_op()]} | {add_by_token, term(), member()}.

-type actor() :: riak_dt:actor().
-type member() :: term().

-spec new() -> orset().
new() ->
    orddict:new().

-spec value(orset()) -> [member()].
value(ORDict0) ->
    ORDict1 = orddict:filter(fun(_Elem, Tokens) ->
            ValidTokens = [Token || {Token, false} <- orddict:to_list(Tokens)],
            length(ValidTokens) > 0
        end, ORDict0),
    orddict:fetch_keys(ORDict1).

-spec value(any(), orset()) -> [member()] | orddict:orddict().
value({fragment, Elem}, ORSet) ->
    case value({tokens, Elem}, ORSet) of
        [] ->
            orddict:new();
        Tokens ->
            orddict:store(Elem, Tokens, orddict:new())
    end;
value({tokens, Elem}, ORSet) ->
    case orddict:find(Elem, ORSet) of
        error ->
            orddict:new();
        {ok, Tokens} ->
            Tokens
    end;
value(removed, ORDict0) ->
    ORDict1 = orddict:filter(fun(_Elem, Tokens) ->
                                     ValidTokens = [Token || {Token, true} <- orddict:to_list(Tokens)],
                                     length(ValidTokens) > 0
                             end, ORDict0),
    orddict:fetch_keys(ORDict1);
value(_, ORSet) ->
    value(ORSet).

-spec update(orset_op(), actor(), orset()) -> {ok, orset()} |
                                              {ok, {delta, orset()}} |
                                              {error, {precondition, {not_present, member()}}}.
update({add_by_token, Token, Elem}, _Actor, ORDict) ->
    add_elem(Elem, Token, ORDict);
update({add, Elem}, Actor, ORDict) ->
    Token = unique(Actor),
    add_elem(Elem, Token, ORDict);
update({add_all, Elems}, Actor, ORDict0) ->
    OD = lists:foldl(fun(Elem, ORDict) ->
                {ok, ORDict1} = update({add, Elem}, Actor, ORDict),
                ORDict1
            end, ORDict0, Elems),
    {ok, OD};
update({remove, Elem}, _Actor, ORDict) ->
    remove_elem(Elem, ORDict);
update({remove_all, Elems}, _Actor, ORDict0) ->
    remove_elems(Elems, ORDict0);
update({update, Ops}, Actor, ORDict) ->
    apply_ops(Ops, Actor, ORDict).

update_delta({remove, Elem}, Actor, ORDict) ->
    case orddict:find(Elem, ORDict) of
        {ok, Tokens} ->
            {ok, Delta} = update({remove, Elem},
                                 Actor,
                                 orddict:store(Elem, Tokens, orddict:new())),
            {ok, {delta, Delta}};
        error ->
            {error, {precondition, {not_present, Elem}}}
    end;
update_delta({remove_all, Elems}, _Actor, ORDict0) ->
    SmallOD = lists:foldl(fun(Elem, ORDict) ->
                                  case orddict:find(Elem, ORDict0) of
                                      {ok, Tokens} ->
                                          orddict:store(Elem, Tokens, ORDict);
                                      error ->
                                          ORDict
                                  end
                          end, orddict:new(), Elems),
    {ok, Delta} = update({remove_all, Elems}, _Actor, SmallOD),
    {ok, {delta, Delta}};
update_delta({update, Ops}, Actor, ORDict) ->
    apply_ops(Ops, Actor, ORDict);
update_delta(Op, Actor, _ORDict) ->
    {ok, Delta} = update(Op, Actor, orddict:new()),
    {ok, {delta, Delta}}.

-spec update(orset_op(), actor(), orset(), riak_dt:context()) ->
                    {ok, orset()} | {error, {precondition, {not_present, member()}}}.
update(Op, Actor, ORDict, _Ctx) ->
    update(Op, Actor, ORDict).

-spec parent_clock(riak_dt_vclock:vclock(), orset()) -> orset().
parent_clock(_Clock, ORSet) ->
    ORSet.
<commit_msg>Add missing error checking of the update_delta() for the or-set<commit_after>%% -------------------------------------------------------------------
%%
%% lasp_orset: A convergent, replicated, state based observe remove set
%%
%% Copyright (c) 2007-2012 <NAME>, Inc.  All Rights Reserved.
%%
%% This file is provided to you under the Apache License,
%% Version 2.0 (the "License"); you may not use this file
%% except in compliance with the License.  You may obtain
%% a copy of the License at
%%
%%   http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied.  See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%
%% -------------------------------------------------------------------

%% @doc This module is a fork of the riak_dt_orset, which is modified to
%%      support some additional update functions needed for correctly
%%      composing objects in Riak.

-module(lasp_orset).

-behaviour(riak_dt).

%% API
-export([new/0, value/1, update/3, update_delta/3, merge/2, equal/2,
         to_binary/1, from_binary/1, value/2, precondition_context/1,
         stats/1, stat/2]).
-export([update/4, parent_clock/2]).
-export([to_binary/2]).
-export([to_version/2]).
-export([intersect/2, map/2, filter/2]).

-ifdef(EQC).
-include_lib("eqc/include/eqc.hrl").
-endif.

-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.

%% EQC API
-ifdef(EQC).
-export([init_state/0, gen_op/0, update_expected/3, eqc_state_value/1]).
-endif.

-export_type([orset/0, binary_orset/0, orset_op/0]).
-opaque orset() :: orddict:orddict().

%% A binary that from_binary/1 will operate on.
-type binary_orset() :: binary().

-type orset_op() :: {add, member()} | {remove, member()} |
                    {add_all, [member()]} | {remove_all, [member()]} |
                    {update, [orset_op()]} | {add_by_token, term(), member()}.

-type actor() :: riak_dt:actor().
-type member() :: term().

-spec new() -> orset().
new() ->
    orddict:new().

-spec value(orset()) -> [member()].
value(ORDict0) ->
    ORDict1 = orddict:filter(fun(_Elem, Tokens) ->
            ValidTokens = [Token || {Token, false} <- orddict:to_list(Tokens)],
            length(ValidTokens) > 0
        end, ORDict0),
    orddict:fetch_keys(ORDict1).

-spec value(any(), orset()) -> [member()] | orddict:orddict().
value({fragment, Elem}, ORSet) ->
    case value({tokens, Elem}, ORSet) of
        [] ->
            orddict:new();
        Tokens ->
            orddict:store(Elem, Tokens, orddict:new())
    end;
value({tokens, Elem}, ORSet) ->
    case orddict:find(Elem, ORSet) of
        error ->
            orddict:new();
        {ok, Tokens} ->
            Tokens
    end;
value(removed, ORDict0) ->
    ORDict1 = orddict:filter(fun(_Elem, Tokens) ->
                                     ValidTokens = [Token || {Token, true} <- orddict:to_list(Tokens)],
                                     length(ValidTokens) > 0
                             end, ORDict0),
    orddict:fetch_keys(ORDict1);
value(_, ORSet) ->
    value(ORSet).

-spec update(orset_op(), actor(), orset()) -> {ok, orset()} |
                                              {ok, {delta, orset()}} |
                                              {error, {precondition, {not_present, member()}}}.
update({add_by_token, Token, Elem}, _Actor, ORDict) ->
    add_elem(Elem, Token, ORDict);
update({add, Elem}, Actor, ORDict) ->
    Token = unique(Actor),
    add_elem(Elem, Token, ORDict);
update({add_all, Elems}, Actor, ORDict0) ->
    OD = lists:foldl(fun(Elem, ORDict) ->
                {ok, ORDict1} = update({add, Elem}, Actor, ORDict),
                ORDict1
            end, ORDict0, Elems),
    {ok, OD};
update({remove, Elem}, _Actor, ORDict) ->
    remove_elem(Elem, ORDict);
update({remove_all, Elems}, _Actor, ORDict0) ->
    remove_elems(Elems, ORDict0);
update({update, Ops}, Actor, ORDict) ->
    apply_ops(Ops, Actor, ORDict).

update_delta({remove, Elem}, Actor, ORDict) ->
    case orddict:find(Elem, ORDict) of
        {ok, Tokens} ->
            {ok, Delta} = update({remove, Elem},
                                 Actor,
                                 orddict:store(Elem, Tokens, orddict:new())),
            {ok, {delta, Delta}};
        error ->
            {error, {precondition, {not_present, Elem}}}
    end;
update_delta({remove_all, Elems}, _Actor, ORDict0) ->
    SmallOD = lists:foldl(fun(Elem, ORDict) ->
                                  case orddict:find(Elem, ORDict0) of
                                      {ok, Tokens} ->
                                          orddict:store(Elem, Tokens, ORDict);
                                      error ->
                                          ORDict
                                  end
                          end, orddict:new(), Elems),
    case update({remove_all, Elems}, _Actor, SmallOD) of
        {ok, Delta} ->
            {ok, {delta, Delta}};
        Error ->
            Error
    end;
update_delta({update, Ops}, Actor, ORDict) ->
    apply_ops(Ops, Actor, ORDict);
update_delta(Op, Actor, _ORDict) ->
    {ok, Delta} = update(Op, Actor, orddict:new()),
    {ok, {delta, Delta}}.

-spec update(orset_op(), actor(), orset(), riak_dt:context()) ->
                    {ok, orset()} | {error, {precondition, {not_present, member()}}}.
update(Op, Actor, ORDict, _Ctx) ->
    update(Op, Actor, ORDict).

-spec parent_clock(riak_dt_vclock:vclock(), orset()) -> orset().
parent_clock(_Clock, ORSet) ->
    ORSet.

{'fraction_non_alphanumeric': 0.17802158909927446, 'fraction_numerical': 0.010086710316758096, 'mean_word_length': 2.1449638286032275, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 82, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 34, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4199609', 'n_tokens_mistral': 3625, 'n_tokens_neox': 3540, 'n_words': 895}