<commit_before>%% -------------------------------------------------------------------
%%
%% riak_kv_mutators - Storage and retrieval for get/put mutation
%% functions
%%
%% Copyright (c) 2013 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 There are circumstances where the object stored on disk is not
%% the object to return; and there are times the object written to the
%% data storage backend is not meant to be the object given. An
%% example would be storing only meta data for an object on a remote
%% cluster. This module is an interface to register mutators that will
%% can be run.
%%
%% This doubles as a behavior defining module for the mutators.
%%
%% == Callbacks ==
%%
%% A mutator callback must implement 2 function: mutate_put/5 and mutate_get/1.
%%
%% <code><b>mutate_put(MetaData, Value, ExposedMeta,
%% FullObject, BucketProperties) -> Result</b></code>
%%
%% Types:
%% ```
%%     MetaData = dict()
%%     Value = term()
%%     ExposedMeta = dict()
%%     FullObject = riak_object:riak_object()
%%     BucketProperties = orddict:orddict()
%%     Result = {NewMeta, NewValue, NewExposedMeta}
%%         NewMeta = dict()
%%         NewValue = term()
%%         NewExposedMeta = dict()'''
%%
%% The mutate_put callback is called for each metadata/value pair a riak_object
%% has. The return value of NewMeta and NewValue are used by the storage backend
%% while the NewExposedMeta is used for the client return where NewMeta would
%% normally. The NewExposedMeta is merged with the NewMeta to generate the
%% exposed metadata; if the same key is found, the NewExposedMeta value is used.
%%
%% The mutations are run in the same process as the vnode.
%%
%% <code><b>mutate_get(Object) -> Result</b></code>
%%
%% Types:
%% ```
%%     Object = riak_object:riak_object()
%%     Result = riak_object:riak_object() | 'notfound'
%% '''
%% Take the object from storage and reverse whatever mutation was applied. Note
%% the bucket properties are not part of this callback, so if some data is
%% important to reverse a mutation, it must be put in the metadata by the
%% `mutate_put' function. Also note how the entire object is given as opposed to
%% simply a metadata/value pair. Care must be taken not to corrupt the object.
%%
%% A return of ``'notfound''' stops the mutator chain and returns immediately. This
%% provides an escape hatch of sorts; if the mutator cannot reverse the mutation
%% effectively, return ``'notfound'''.

-module(riak_kv_mutator).

-export([register/1, register/2, unregister/1]).
-export([get/0]).
-export([mutate_put/2, mutate_get/1]).

-callback mutate_put(Meta :: dict(), Value :: any(), ExposedMeta :: dict(), FullObject :: riak_object:riak_object(), BucketProps :: orddict:orddict()) -> {dict(), any(), dict()}.
-callback mutate_get(FullObject :: riak_object:riak_object()) -> riak_object:riak_object() | 'notfound'.

-define(DEFAULT_PRIORITY, 0).

%% @doc Register the given module as a mutator with the default priority of 0.
%% @see register/2
-spec register(Module :: atom()) -> 'ok'.
register(Module) ->
    ?MODULE:register(Module, ?DEFAULT_PRIORITY).

%% @doc Register a module as a mutator with the given priority. Modules with
%% equal priority are done in sort sort (alphabetical) order. A module
%% can only be registered once. When there is a conflict (two different
%% lists), those lists are merged.
-spec register(Module :: atom(), Priority :: term()) -> 'ok'.
register(Module, Priority) ->
    Modifier = fun
        (undefined) ->
            [{Module, Priority}];
        (Values) ->
            Values2 = merge_values(Values),
            orddict:store(Module, Priority, Values2)
    end,
    riak_core_metadata:put({riak_kv, mutators}, list, Modifier).

%% @doc Remove a module from the mutator list.
-spec unregister(Module :: atom()) -> 'ok'.
unregister(Module) ->
    Modifier = fun
        (undefined) ->
            [];<commit_msg>Fixed grammatical errors in docs.<commit_after>%% -------------------------------------------------------------------
%%
%% riak_kv_mutators - Storage and retrieval for get/put mutation
%% functions
%%
%% Copyright (c) 2013 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 There are circumstances where the object stored on disk is not
%% the object to return; and there are times the object written to the
%% data storage backend is not meant to be the object given. An
%% example would be storing only meta data for an object on a remote
%% cluster. This module is an interface to register mutators that will
%% be run.
%%
%% This doubles as a behavior defining module for the mutators.
%%
%% == Callbacks ==
%%
%% A mutator callback must implement 2 function: mutate_put/5 and mutate_get/1.
%%
%% <code><b>mutate_put(MetaData, Value, ExposedMeta,
%% FullObject, BucketProperties) -> Result</b></code>
%%
%% Types:
%% ```
%%     MetaData = dict()
%%     Value = term()
%%     ExposedMeta = dict()
%%     FullObject = riak_object:riak_object()
%%     BucketProperties = orddict:orddict()
%%     Result = {NewMeta, NewValue, NewExposedMeta}
%%         NewMeta = dict()
%%         NewValue = term()
%%         NewExposedMeta = dict()'''
%%
%% The mutate_put callback is called for each metadata/value pair a riak_object
%% has. The return value of NewMeta and NewValue are used by the storage backend
%% while the NewExposedMeta is used for the client return where NewMeta would
%% normally. The NewExposedMeta is merged with the NewMeta to generate the
%% exposed metadata; if the same key is found, the NewExposedMeta value is used.
%%
%% The mutations are run in the same process as the vnode.
%%
%% <code><b>mutate_get(Object) -> Result</b></code>
%%
%% Types:
%% ```
%%     Object = riak_object:riak_object()
%%     Result = riak_object:riak_object() | 'notfound'
%% '''
%% Take the object from storage and reverse whatever mutation was applied. Note
%% the bucket properties are not part of this callback, so if some data is
%% important to reverse a mutation, it must be put in the metadata by the
%% `mutate_put' function. Also note how the entire object is given as opposed to
%% simply a metadata/value pair. Care must be taken not to corrupt the object.
%%
%% A return of ``'notfound''' stops the mutator chain and returns immediately. This
%% provides an escape hatch of sorts; if the mutator cannot reverse the mutation
%% effectively, return ``'notfound'''.

-module(riak_kv_mutator).

-export([register/1, register/2, unregister/1]).
-export([get/0]).
-export([mutate_put/2, mutate_get/1]).

-callback mutate_put(Meta :: dict(), Value :: any(), ExposedMeta :: dict(), FullObject :: riak_object:riak_object(), BucketProps :: orddict:orddict()) -> {dict(), any(), dict()}.
-callback mutate_get(FullObject :: riak_object:riak_object()) -> riak_object:riak_object() | 'notfound'.

-define(DEFAULT_PRIORITY, 0).

%% @doc Register the given module as a mutator with the default priority of 0.
%% @see register/2
-spec register(Module :: atom()) -> 'ok'.
register(Module) ->
    ?MODULE:register(Module, ?DEFAULT_PRIORITY).

%% @doc Register a module as a mutator with the given priority. Modules with
%% equal priority are done in default (alphabetical) order. A module
%% can only be registered once. When there is a conflict (two different
%% lists), those lists are merged.
-spec register(Module :: atom(), Priority :: term()) -> 'ok'.
register(Module, Priority) ->
    Modifier = fun
        (undefined) ->
            [{Module, Priority}];
        (Values) ->
            Values2 = merge_values(Values),
            orddict:store(Module, Priority, Values2)
    end,
    riak_core_metadata:put({riak_kv, mutators}, list, Modifier).

%% @doc Remove a module from the mutator list.
-spec unregister(Module :: atom()) -> 'ok'.
unregister(Module) ->
    Modifier = fun
        (undefined) ->
            [];
{'fraction_non_alphanumeric': 0.1483708725125738, 'fraction_numerical': 0.004810846271594139, 'mean_word_length': 3.4402912621359225, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1170182', 'n_tokens_mistral': 2548, 'n_tokens_neox': 2501, 'n_words': 1042}