1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.adservices.service.signals.updateprocessors;
18 
19 import com.android.adservices.data.signals.DBProtectedSignal;
20 
21 import org.json.JSONException;
22 import org.json.JSONObject;
23 
24 import java.nio.ByteBuffer;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.Set;
28 
29 /**
30  * Adds a new signal, overwriting any existing signals with the same key.
31  *
32  * <p>The value for this is a JSON object where the JSON keys are base 64 strings corresponding to
33  * the signal key to put for and the values are base 64 string corresponding to the value to put.
34  */
35 public class Put implements UpdateProcessor {
36 
37     private static final String PUT = "put";
38 
39     @Override
getName()40     public String getName() {
41         return PUT;
42     }
43 
44     @Override
processUpdates( Object updates, Map<ByteBuffer, Set<DBProtectedSignal>> current)45     public UpdateOutput processUpdates(
46             Object updates, Map<ByteBuffer, Set<DBProtectedSignal>> current) throws JSONException {
47         UpdateOutput toReturn = new UpdateOutput();
48         JSONObject updatesObject = UpdateProcessorUtils.castToJSONObject(PUT, updates);
49         for (Iterator<String> iter = updatesObject.keys(); iter.hasNext(); ) {
50             String stringKey = iter.next();
51             ByteBuffer key = UpdateProcessorUtils.decodeKey(PUT, stringKey);
52             processKey(key, updatesObject.getString(stringKey), current, toReturn);
53         }
54         return toReturn;
55     }
56 
57     /** Process the update for one key. */
processKey( ByteBuffer key, String value, Map<ByteBuffer, Set<DBProtectedSignal>> current, UpdateOutput toReturn)58     private void processKey(
59             ByteBuffer key,
60             String value,
61             Map<ByteBuffer, Set<DBProtectedSignal>> current,
62             UpdateOutput toReturn) {
63         UpdateProcessorUtils.touchKey(key, toReturn.getKeysTouched());
64         // Remove any existing signals for the key
65         if (current.containsKey(key)) {
66             toReturn.getToRemove().addAll(current.get(key));
67         }
68         // Add the new signal
69         DBProtectedSignal.Builder newSignalBuilder =
70                 DBProtectedSignal.builder()
71                         .setKey(UpdateProcessorUtils.getByteArrayFromBuffer(key))
72                         .setValue(UpdateProcessorUtils.decodeValue(PUT, value));
73         toReturn.getToAdd().add(newSignalBuilder);
74     }
75 }
76