1 /*
2  * Copyright (C) 2022 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 android.safetycenter.config;
18 
19 import static android.os.Build.VERSION_CODES.TIRAMISU;
20 
21 import android.annotation.AnyRes;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.content.res.Resources;
25 
26 import androidx.annotation.RequiresApi;
27 
28 import java.util.Collection;
29 import java.util.Objects;
30 import java.util.regex.Pattern;
31 
32 @RequiresApi(TIRAMISU)
33 final class BuilderUtils {
34 
BuilderUtils()35     private BuilderUtils() {}
36 
validateAttribute( @ullable Object attribute, @NonNull String name, boolean required, boolean prohibited, @Nullable Object defaultValue)37     private static void validateAttribute(
38             @Nullable Object attribute,
39             @NonNull String name,
40             boolean required,
41             boolean prohibited,
42             @Nullable Object defaultValue) {
43         if (attribute == null && required) {
44             throwRequiredAttributeMissing(name);
45         }
46         boolean nonDefaultValueProvided = !Objects.equals(attribute, defaultValue);
47         boolean checkProhibited = prohibited && nonDefaultValueProvided;
48         if (attribute != null && checkProhibited) {
49             throwProhibitedAttributePresent(name);
50         }
51     }
52 
validateAttribute( @ullable Object attribute, @NonNull String name, boolean required, boolean prohibited)53     static void validateAttribute(
54             @Nullable Object attribute,
55             @NonNull String name,
56             boolean required,
57             boolean prohibited) {
58         validateAttribute(attribute, name, required, prohibited, null);
59     }
60 
validateId( @ullable String id, @NonNull String name, boolean required, boolean prohibited)61     static void validateId(
62             @Nullable String id,
63             @NonNull String name,
64             boolean required,
65             boolean prohibited) {
66         validateAttribute(id, name, required, prohibited, null);
67         if (!Pattern.compile("[0-9a-zA-Z_]+").matcher(id).matches()) {
68             throw new IllegalStateException("Attribute " + name + " invalid");
69         }
70     }
71 
72     @AnyRes
validateResId( @ullable @nyRes Integer value, @NonNull String name, boolean required, boolean prohibited)73     static int validateResId(
74             @Nullable @AnyRes Integer value,
75             @NonNull String name,
76             boolean required,
77             boolean prohibited) {
78         validateAttribute(value, name, required, prohibited, Resources.ID_NULL);
79         if (value == null) {
80             return Resources.ID_NULL;
81         }
82         if (required && value == Resources.ID_NULL) {
83             throwRequiredAttributeInvalid(name);
84         }
85         return value;
86     }
87 
validateIntDef( @ullable Integer value, @NonNull String name, boolean required, boolean prohibited, int defaultValue, int... validValues)88     static int validateIntDef(
89             @Nullable Integer value,
90             @NonNull String name,
91             boolean required,
92             boolean prohibited,
93             int defaultValue,
94             int... validValues) {
95         validateAttribute(value, name, required, prohibited, defaultValue);
96         if (value == null) {
97             return defaultValue;
98         }
99 
100         boolean found = false;
101         for (int i = 0; i < validValues.length; i++) {
102             found |= (value == validValues[i]);
103         }
104         if (!found) {
105             throw new IllegalStateException("Attribute " + name + " invalid");
106         }
107         return value;
108     }
109 
validateInteger( @ullable Integer value, @NonNull String name, boolean required, boolean prohibited, int defaultValue)110     static int validateInteger(
111             @Nullable Integer value,
112             @NonNull String name,
113             boolean required,
114             boolean prohibited,
115             int defaultValue) {
116         validateAttribute(value, name, required, prohibited, defaultValue);
117         if (value == null) {
118             return defaultValue;
119         }
120         return value;
121     }
122 
validateBoolean( @ullable Boolean value, @NonNull String name, boolean required, boolean prohibited, boolean defaultValue)123     static boolean validateBoolean(
124             @Nullable Boolean value,
125             @NonNull String name,
126             boolean required,
127             boolean prohibited,
128             boolean defaultValue) {
129         validateAttribute(value, name, required, prohibited, defaultValue);
130         if (value == null) {
131             return defaultValue;
132         }
133         return value;
134     }
135 
136     /**
137      * Validates a collection argument from a builder.
138      *
139      * <ul>
140      *   <li>If {@code required}, a non-empty collection must be supplied.
141      *   <li>If {@code prohibited}, an empty collection must be supplied.
142      * </ul>
143      */
validateCollection( @onNull Collection<T> value, @NonNull String name, boolean required, boolean prohibited)144     static <T> void validateCollection(
145             @NonNull Collection<T> value,
146             @NonNull String name,
147             boolean required,
148             boolean prohibited) {
149         if (value.isEmpty() && required) {
150             throwRequiredAttributeMissing(name);
151         }
152         if (!value.isEmpty() && prohibited) {
153             throwProhibitedAttributePresent(name);
154         }
155     }
156 
throwRequiredAttributeMissing(@onNull String attribute)157     static void throwRequiredAttributeMissing(@NonNull String attribute) {
158         throw new IllegalStateException("Required attribute " + attribute + " missing");
159     }
160 
throwProhibitedAttributePresent(@onNull String attribute)161     static void throwProhibitedAttributePresent(@NonNull String attribute) {
162         throw new IllegalStateException("Prohibited attribute " + attribute + " present");
163     }
164 
throwRequiredAttributeInvalid(@onNull String attribute)165     static void throwRequiredAttributeInvalid(@NonNull String attribute) {
166         throw new IllegalStateException("Required attribute " + attribute + " invalid");
167     }
168 }
169