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.measurement;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 
22 import java.util.Objects;
23 
24 /**
25  * POJO for key-value data.
26  *
27  * <p>This class is useful for creating & storing arbitrary key-value-dataType combinations. The
28  * corresponding table {@code
29  * com.android.adservices.data.measurement.MeasurementTables.KeyValueDataContract} is used to
30  * persist these objects.
31  */
32 public class KeyValueData {
33 
34 
35     public enum DataType {
36         REGISTRATION_REDIRECT_COUNT,
37         EVENT_REPORT_RETRY_COUNT,
38         DEBUG_EVENT_REPORT_RETRY_COUNT,
39         AGGREGATE_REPORT_RETRY_COUNT,
40         DEBUG_AGGREGATE_REPORT_RETRY_COUNT,
41         DEBUG_REPORT_RETRY_COUNT,
42         JOB_LAST_EXECUTION_TIME,
43         JOB_NEXT_EXECUTION_TIME,
44     }
45 
46     private DataType mDataType = null;
47     private String mKey = null;
48     private String mValue = null;
49 
KeyValueData(DataType dataType, String key, String value)50     private KeyValueData(DataType dataType, String key, String value) {
51         mDataType = dataType;
52         mKey = key;
53         mValue = value;
54     }
55 
56     /** Returns the data type. */
getDataType()57     public DataType getDataType() {
58         return mDataType;
59     }
60 
61     /** Returns the key. */
getKey()62     public String getKey() {
63         return mKey;
64     }
65 
66     /** Returns the raw value. */
getValue()67     public String getValue() {
68         return mValue;
69     }
70 
KeyValueData()71     private KeyValueData() {}
72 
73     /** Builder class for {@link KeyValueData} */
74     public static class Builder {
75         private DataType mDataType = null;
76         private String mKey = null;
77         private String mValue = null;
78 
79         /** See {@link KeyValueData#getDataType()} ()} */
setDataType(@onNull DataType dataType)80         public Builder setDataType(@NonNull DataType dataType) {
81             mDataType = dataType;
82             return this;
83         }
84 
85         /** See {@link KeyValueData#getKey()} */
setKey(@onNull String key)86         public Builder setKey(@NonNull String key) {
87             mKey = key;
88             return this;
89         }
90 
91         /** See {@link KeyValueData#getValue()} */
setValue(@ullable String value)92         public Builder setValue(@Nullable String value) {
93             mValue = value;
94             return this;
95         }
96 
97         /** Build the {@link KeyValueData} */
build()98         public KeyValueData build() {
99             Objects.requireNonNull(mDataType);
100             Objects.requireNonNull(mKey);
101             return new KeyValueData(mDataType, mKey, mValue);
102         }
103     }
104 
105     /** Get the Registration Count value */
getRegistrationRedirectCount()106     public int getRegistrationRedirectCount() {
107         if (mDataType != DataType.REGISTRATION_REDIRECT_COUNT) {
108             throw new IllegalStateException("Illegal method call");
109         }
110         if (mValue == null) {
111             // Default value is 1, because the first registration will be the only case when value
112             // can be null.
113             return 1;
114         }
115         return Integer.parseInt(mValue);
116     }
117 
118     /** Set the Registration Count value */
setRegistrationRedirectCount(int value)119     public void setRegistrationRedirectCount(int value) {
120         if (mDataType != DataType.REGISTRATION_REDIRECT_COUNT) {
121             throw new IllegalStateException("Illegal method call");
122         }
123         mValue = String.valueOf(value);
124     }
125 
126     /** Set the Aggregate/Event/Debug Report Retry Count value */
getReportRetryCount()127     public int getReportRetryCount() {
128         validateOfTypeReport();
129         if (mValue == null) {
130             // Default value is 0,
131             return 0;
132         }
133         return Integer.parseInt(mValue);
134     }
135 
136     /** Set the Aggregate/Event/Debug Report Retry Count value */
setReportRetryCount(int value)137     public void setReportRetryCount(int value) {
138         validateOfTypeReport();
139         mValue = String.valueOf(value);
140     }
141 
142     /** Get the last execution time of the Reporting Service Job */
getReportingJobLastExecutionTime()143     public Long getReportingJobLastExecutionTime() {
144         validateOfTypeReport();
145         if (mValue == null) {
146             return null;
147         }
148         return Long.parseLong(mValue);
149     }
150 
151     /** Set the last execution time of the Reporting Service Job */
setReportingJobLastExecutionTime(long value)152     public void setReportingJobLastExecutionTime(long value) {
153         validateOfTypeReport();
154         mValue = String.valueOf(value);
155     }
156 
157     /** Get the next execution time of the Reporting Service Job */
getReportingJobNextExecutionTime()158     public Long getReportingJobNextExecutionTime() {
159         validateOfTypeReport();
160         if (mValue == null) {
161             return null;
162         }
163         return Long.parseLong(mValue);
164     }
165 
166     /** Set the next execution time of the Reporting Service Job */
setReportingJobNextExecutionTime(Long value)167     public void setReportingJobNextExecutionTime(Long value) {
168         validateOfTypeReport();
169         mValue = String.valueOf(value);
170     }
171 
validateOfTypeReport()172     private void validateOfTypeReport() {
173         if (mDataType != DataType.AGGREGATE_REPORT_RETRY_COUNT
174                 && mDataType != DataType.DEBUG_AGGREGATE_REPORT_RETRY_COUNT
175                 && mDataType != DataType.EVENT_REPORT_RETRY_COUNT
176                 && mDataType != DataType.DEBUG_EVENT_REPORT_RETRY_COUNT
177                 && mDataType != DataType.DEBUG_REPORT_RETRY_COUNT
178                 && mDataType != DataType.JOB_LAST_EXECUTION_TIME
179                 && mDataType != DataType.JOB_NEXT_EXECUTION_TIME) {
180             throw new IllegalStateException("Illegal method call");
181         }
182     }
183 }
184