anchor.diff:      end;
   
   handle_cast({{put, Field, Value}, ReplyTo}, S) ->
  -    {OldUrls, OldUser} = if is_record(S#state.data, tagcontent) ->
  -                                 C = S#state.data,
  -                                 {C#tagcontent.urls, C#tagcontent.user};
  -                            true ->
  -                                 {[], []}
  -                         end,
  -    Check = case Field of
  -                urls ->
  -                    case validate_urls(Value) of
  -                        true ->
  -                            {ok, {Value, OldUser}};
  -                        false ->
  -                            {error, invalid_url_object}
  -                    end;
  -                {user, K} ->
  -                    {ok, {OldUrls,
  -                          [{K, Value} | proplists:delete(K, OldUser)]}}
  -            end,
  -    case Check of
  +    case get_new_values(S, Field, Value) of
           {ok, {Urls, User}} ->
               TagName = ddfs_util:pack_objname(S#state.tag, now()),
               TagContent = #tagcontent{id = TagName,
  
positive.code:                                      user = UserData}};
                  _ -> {error, invalid_object}
              end
      end.
  
  % THOUGHT: Eventually we want to partition tag keyspace instead
  
negative.code:         handle_info/2, terminate/2, code_change/3]).
  
  -type replica() :: {timer:timestamp(), nonempty_string()}.
  -type user_attr() :: [{binary(), binary()}].
  -record(tagcontent, {id :: binary(),
                       last_modified :: binary(),
                       urls :: [binary()],
                       user :: user_attr()}).
  -type tagcontent() :: #tagcontent{}.
  -record(state, {tag, % :: binary(),
                  data :: 'false'  | 'notfound' | 'deleted' | {'error', _}
  