• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 package com.android.adservices.service.measurement.aggregation;
17 
18 import android.annotation.Nullable;
19 
20 import com.android.adservices.service.Flags;
21 import com.android.adservices.service.measurement.FilterMap;
22 import com.android.adservices.service.measurement.util.Filter;
23 import com.android.adservices.service.measurement.util.Filter.FilterContract;
24 import com.android.adservices.service.measurement.util.UnsignedLong;
25 
26 import org.json.JSONArray;
27 import org.json.JSONException;
28 import org.json.JSONObject;
29 
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Objects;
35 
36 /** POJO for AggregatableValuesConfig */
37 public class AggregatableValuesConfig {
38     private final Map<String, AggregatableKeyValue> mValues;
39     @Nullable private final List<FilterMap> mFilterSet;
40     @Nullable private final List<FilterMap> mNotFilterSet;
41 
AggregatableValuesConfig(AggregatableValuesConfig.Builder builder)42     private AggregatableValuesConfig(AggregatableValuesConfig.Builder builder) {
43         mValues = builder.mValues;
44         mFilterSet = builder.mFilterSet;
45         mNotFilterSet = builder.mNotFilterSet;
46     }
47 
48     /**
49      * Returns a map of key and aggregatable_value's values. Example: {"campaignCounts":
50      * AggregatableKeyValue{"value":1664}}
51      */
getValues()52     public Map<String, AggregatableKeyValue> getValues() {
53         return mValues;
54     }
55 
56     /**
57      * Returns a map of key and int value of aggregatable_values's values. Example:
58      * {"campaignCounts": 1664}
59      */
getConfigValuesMap()60     public Map<String, Integer> getConfigValuesMap() {
61         Map<String, Integer> configValuesMap = new HashMap<>();
62         for (String key : mValues.keySet()) {
63             configValuesMap.put(key, mValues.get(key).getValue());
64         }
65         return configValuesMap;
66     }
67 
68     /** Returns AggregateKeyValue filters. Example: [{"category": ["filter_1", "filter_2"]}] */
69     @Nullable
getFilterSet()70     public List<FilterMap> getFilterSet() {
71         return mFilterSet;
72     }
73 
74     /** Returns AggregateKeyValue not_filters. Example: [{"category": ["filter_2", "filter_3"]}] */
75     @Nullable
getNotFilterSet()76     public List<FilterMap> getNotFilterSet() {
77         return mNotFilterSet;
78     }
79 
80     @Override
equals(Object o)81     public boolean equals(Object o) {
82         if (this == o) return true;
83         if (!(o instanceof AggregatableValuesConfig)) return false;
84         AggregatableValuesConfig that = (AggregatableValuesConfig) o;
85         return Objects.equals(mValues, that.mValues)
86                 && Objects.equals(mFilterSet, that.mFilterSet)
87                 && Objects.equals(mNotFilterSet, that.mNotFilterSet);
88     }
89 
90     @Override
hashCode()91     public int hashCode() {
92         return Objects.hash(mValues, mFilterSet, mNotFilterSet);
93     }
94 
95     public static final class Builder {
96         private Map<String, AggregatableKeyValue> mValues;
97         @Nullable private List<FilterMap> mFilterSet;
98         @Nullable private List<FilterMap> mNotFilterSet;
99 
Builder(Map<String, AggregatableKeyValue> values)100         public Builder(Map<String, AggregatableKeyValue> values) {
101             mValues = values;
102         }
103 
Builder(JSONObject aggregateKeyValuesJson, Flags flags)104         public Builder(JSONObject aggregateKeyValuesJson, Flags flags) throws JSONException {
105             if (!aggregateKeyValuesJson.isNull(AggregatableValuesConfigContract.VALUES)) {
106                 mValues =
107                         buildValues(
108                                 aggregateKeyValuesJson.getJSONObject(
109                                         AggregatableValuesConfigContract.VALUES),
110                                 flags);
111             } else {
112                 mValues = buildValues(aggregateKeyValuesJson, flags);
113             }
114             Filter filter = new Filter(flags);
115             if (!aggregateKeyValuesJson.isNull(FilterContract.FILTERS)) {
116                 JSONArray filterSet =
117                         Filter.maybeWrapFilters(aggregateKeyValuesJson, FilterContract.FILTERS);
118                 mFilterSet = filter.deserializeFilterSet(filterSet);
119             }
120             if (!aggregateKeyValuesJson.isNull(FilterContract.NOT_FILTERS)) {
121                 JSONArray notFilterSet =
122                         Filter.maybeWrapFilters(aggregateKeyValuesJson, FilterContract.NOT_FILTERS);
123                 mNotFilterSet = filter.deserializeFilterSet(notFilterSet);
124             }
125         }
126 
127         /**
128          * Create {@link AggregatableValuesConfigContract#getValues} from a JSONObject that has
129          * Integer typed values.
130          */
buildValues( JSONObject aggregateKeyValuesJson, Flags flags)131         private Map<String, AggregatableKeyValue> buildValues(
132                 JSONObject aggregateKeyValuesJson, Flags flags) throws JSONException {
133             Iterator<String> valuesKeySet = aggregateKeyValuesJson.keys();
134             Map<String, AggregatableKeyValue> mValues = new HashMap<>();
135             while (valuesKeySet.hasNext()) {
136                 String key = valuesKeySet.next();
137                 AggregatableKeyValue.Builder aggregatableKeyValueBuilder;
138                 if (flags.getMeasurementEnableFlexibleContributionFiltering()) {
139                     int value;
140                     UnsignedLong filteringId = UnsignedLong.ZERO;
141                     if (aggregateKeyValuesJson.get(key) instanceof JSONObject) {
142                         JSONObject obj = aggregateKeyValuesJson.getJSONObject(key);
143                         value = obj.getInt(AggregatableKeyValue.AggregatableKeyValueContract.VALUE);
144                         if (!obj.isNull(
145                                 AggregatableKeyValue.AggregatableKeyValueContract.FILTERING_ID)) {
146                             filteringId =
147                                     new UnsignedLong(
148                                             obj.getString(
149                                                     AggregatableKeyValue
150                                                             .AggregatableKeyValueContract
151                                                             .FILTERING_ID));
152                         }
153                     } else {
154                         value = aggregateKeyValuesJson.getInt(key);
155                     }
156                     aggregatableKeyValueBuilder =
157                             new AggregatableKeyValue.Builder(value).setFilteringId(filteringId);
158                 } else {
159                     // This will throw JSONException if a JSONObject was previously persisted, and
160                     // flag MEASUREMENT_ENABLE_FLEXIBLE_CONTRIBUTION_FILTERING gets set to false.
161                     aggregatableKeyValueBuilder =
162                             new AggregatableKeyValue.Builder(aggregateKeyValuesJson.getInt(key));
163                 }
164                 mValues.put(key, aggregatableKeyValueBuilder.build());
165             }
166             return mValues;
167         }
168 
169         /** See {@link AggregatableValuesConfig#getFilterSet()} */
setFilterSet(@ullable List<FilterMap> filterSet)170         public Builder setFilterSet(@Nullable List<FilterMap> filterSet) {
171             mFilterSet = filterSet;
172             return this;
173         }
174 
175         /** See {@link AggregatableValuesConfig#getNotFilterSet()} */
setNotFilterSet(@ullable List<FilterMap> notFilterSet)176         public Builder setNotFilterSet(@Nullable List<FilterMap> notFilterSet) {
177             mNotFilterSet = notFilterSet;
178             return this;
179         }
180 
181         /** Build the {@link AggregatableValuesConfig}. */
build()182         public AggregatableValuesConfig build() throws JSONException {
183             Objects.requireNonNull(mValues);
184             return new AggregatableValuesConfig(this);
185         }
186     }
187 
188     public interface AggregatableValuesConfigContract {
189         String VALUES = "values";
190     }
191 }
192