1 /*
2  * Copyright (C) 2020 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.modules.utils;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 
22 import org.xmlpull.v1.XmlPullParser;
23 import org.xmlpull.v1.XmlPullParserException;
24 
25 /**
26  * Specialization of {@link XmlPullParser} which adds explicit methods to
27  * support consistent and efficient conversion of primitive data types.
28  */
29 public interface TypedXmlPullParser extends XmlPullParser {
30     /**
31      * @return index of requested attribute, otherwise {@code -1} if undefined
32      */
getAttributeIndex(@ullable String namespace, @NonNull String name)33     default int getAttributeIndex(@Nullable String namespace, @NonNull String name) {
34         final boolean namespaceNull = (namespace == null);
35         final int count = getAttributeCount();
36         for (int i = 0; i < count; i++) {
37             if ((namespaceNull || namespace.equals(getAttributeNamespace(i)))
38                     && name.equals(getAttributeName(i))) {
39                 return i;
40             }
41         }
42         return -1;
43     }
44 
45     /**
46      * @return index of requested attribute
47      * @throws XmlPullParserException if the value is undefined
48      */
getAttributeIndexOrThrow(@ullable String namespace, @NonNull String name)49     default int getAttributeIndexOrThrow(@Nullable String namespace, @NonNull String name)
50             throws XmlPullParserException {
51         final int index = getAttributeIndex(namespace, name);
52         if (index == -1) {
53             throw new XmlPullParserException("Missing attribute " + name);
54         } else {
55             return index;
56         }
57     }
58 
59     /**
60      * @return decoded strongly-typed {@link #getAttributeValue}
61      * @throws XmlPullParserException if the value is malformed
62      */
getAttributeBytesHex(int index)63     @NonNull byte[] getAttributeBytesHex(int index) throws XmlPullParserException;
64 
65     /**
66      * @return decoded strongly-typed {@link #getAttributeValue}
67      * @throws XmlPullParserException if the value is malformed
68      */
getAttributeBytesBase64(int index)69     @NonNull byte[] getAttributeBytesBase64(int index) throws XmlPullParserException;
70 
71     /**
72      * @return decoded strongly-typed {@link #getAttributeValue}
73      * @throws XmlPullParserException if the value is malformed
74      */
getAttributeInt(int index)75     int getAttributeInt(int index) throws XmlPullParserException;
76 
77     /**
78      * @return decoded strongly-typed {@link #getAttributeValue}
79      * @throws XmlPullParserException if the value is malformed
80      */
getAttributeIntHex(int index)81     int getAttributeIntHex(int index) throws XmlPullParserException;
82 
83     /**
84      * @return decoded strongly-typed {@link #getAttributeValue}
85      * @throws XmlPullParserException if the value is malformed
86      */
getAttributeLong(int index)87     long getAttributeLong(int index) throws XmlPullParserException;
88 
89     /**
90      * @return decoded strongly-typed {@link #getAttributeValue}
91      * @throws XmlPullParserException if the value is malformed
92      */
getAttributeLongHex(int index)93     long getAttributeLongHex(int index) throws XmlPullParserException;
94 
95     /**
96      * @return decoded strongly-typed {@link #getAttributeValue}
97      * @throws XmlPullParserException if the value is malformed
98      */
getAttributeFloat(int index)99     float getAttributeFloat(int index) throws XmlPullParserException;
100 
101     /**
102      * @return decoded strongly-typed {@link #getAttributeValue}
103      * @throws XmlPullParserException if the value is malformed
104      */
getAttributeDouble(int index)105     double getAttributeDouble(int index) throws XmlPullParserException;
106 
107     /**
108      * @return decoded strongly-typed {@link #getAttributeValue}
109      * @throws XmlPullParserException if the value is malformed
110      */
getAttributeBoolean(int index)111     boolean getAttributeBoolean(int index) throws XmlPullParserException;
112 
113     /**
114      * @return decoded strongly-typed {@link #getAttributeValue}
115      * @throws XmlPullParserException if the value is malformed or undefined
116      */
getAttributeBytesHex(@ullable String namespace, @NonNull String name)117     default @NonNull byte[] getAttributeBytesHex(@Nullable String namespace,
118             @NonNull String name) throws XmlPullParserException {
119         return getAttributeBytesHex(getAttributeIndexOrThrow(namespace, name));
120     }
121 
122     /**
123      * @return decoded strongly-typed {@link #getAttributeValue}
124      * @throws XmlPullParserException if the value is malformed or undefined
125      */
getAttributeBytesBase64(@ullable String namespace, @NonNull String name)126     default @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace,
127             @NonNull String name) throws XmlPullParserException {
128         return getAttributeBytesBase64(getAttributeIndexOrThrow(namespace, name));
129     }
130 
131     /**
132      * @return decoded strongly-typed {@link #getAttributeValue}
133      * @throws XmlPullParserException if the value is malformed or undefined
134      */
getAttributeInt(@ullable String namespace, @NonNull String name)135     default int getAttributeInt(@Nullable String namespace, @NonNull String name)
136             throws XmlPullParserException {
137         return getAttributeInt(getAttributeIndexOrThrow(namespace, name));
138     }
139 
140     /**
141      * @return decoded strongly-typed {@link #getAttributeValue}
142      * @throws XmlPullParserException if the value is malformed or undefined
143      */
getAttributeIntHex(@ullable String namespace, @NonNull String name)144     default int getAttributeIntHex(@Nullable String namespace, @NonNull String name)
145             throws XmlPullParserException {
146         return getAttributeIntHex(getAttributeIndexOrThrow(namespace, name));
147     }
148 
149     /**
150      * @return decoded strongly-typed {@link #getAttributeValue}
151      * @throws XmlPullParserException if the value is malformed or undefined
152      */
getAttributeLong(@ullable String namespace, @NonNull String name)153     default long getAttributeLong(@Nullable String namespace, @NonNull String name)
154             throws XmlPullParserException {
155         return getAttributeLong(getAttributeIndexOrThrow(namespace, name));
156     }
157 
158     /**
159      * @return decoded strongly-typed {@link #getAttributeValue}
160      * @throws XmlPullParserException if the value is malformed or undefined
161      */
getAttributeLongHex(@ullable String namespace, @NonNull String name)162     default long getAttributeLongHex(@Nullable String namespace, @NonNull String name)
163             throws XmlPullParserException {
164         return getAttributeLongHex(getAttributeIndexOrThrow(namespace, name));
165     }
166 
167     /**
168      * @return decoded strongly-typed {@link #getAttributeValue}
169      * @throws XmlPullParserException if the value is malformed or undefined
170      */
getAttributeFloat(@ullable String namespace, @NonNull String name)171     default float getAttributeFloat(@Nullable String namespace, @NonNull String name)
172             throws XmlPullParserException {
173         return getAttributeFloat(getAttributeIndexOrThrow(namespace, name));
174     }
175 
176     /**
177      * @return decoded strongly-typed {@link #getAttributeValue}
178      * @throws XmlPullParserException if the value is malformed or undefined
179      */
getAttributeDouble(@ullable String namespace, @NonNull String name)180     default double getAttributeDouble(@Nullable String namespace, @NonNull String name)
181             throws XmlPullParserException {
182         return getAttributeDouble(getAttributeIndexOrThrow(namespace, name));
183     }
184 
185     /**
186      * @return decoded strongly-typed {@link #getAttributeValue}
187      * @throws XmlPullParserException if the value is malformed or undefined
188      */
getAttributeBoolean(@ullable String namespace, @NonNull String name)189     default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name)
190             throws XmlPullParserException {
191         return getAttributeBoolean(getAttributeIndexOrThrow(namespace, name));
192     }
193 
194     /**
195      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
196      *         default value if the value is malformed or undefined
197      */
getAttributeBytesHex(@ullable String namespace, @NonNull String name, @Nullable byte[] defaultValue)198     default @Nullable byte[] getAttributeBytesHex(@Nullable String namespace,
199             @NonNull String name, @Nullable byte[] defaultValue) {
200         final int index = getAttributeIndex(namespace, name);
201         if (index == -1) return defaultValue;
202         try {
203             return getAttributeBytesHex(index);
204         } catch (Exception ignored) {
205             return defaultValue;
206         }
207     }
208 
209     /**
210      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
211      *         default value if the value is malformed or undefined
212      */
getAttributeBytesBase64(@ullable String namespace, @NonNull String name, @Nullable byte[] defaultValue)213     default @Nullable byte[] getAttributeBytesBase64(@Nullable String namespace,
214             @NonNull String name, @Nullable byte[] defaultValue) {
215         final int index = getAttributeIndex(namespace, name);
216         if (index == -1) return defaultValue;
217         try {
218             return getAttributeBytesBase64(index);
219         } catch (Exception ignored) {
220             return defaultValue;
221         }
222     }
223 
224     /**
225      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
226      *         default value if the value is malformed or undefined
227      */
getAttributeInt(@ullable String namespace, @NonNull String name, int defaultValue)228     default int getAttributeInt(@Nullable String namespace, @NonNull String name,
229             int defaultValue) {
230         final int index = getAttributeIndex(namespace, name);
231         if (index == -1) return defaultValue;
232         try {
233             return getAttributeInt(index);
234         } catch (Exception ignored) {
235             return defaultValue;
236         }
237     }
238 
239     /**
240      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
241      *         default value if the value is malformed or undefined
242      */
getAttributeIntHex(@ullable String namespace, @NonNull String name, int defaultValue)243     default int getAttributeIntHex(@Nullable String namespace, @NonNull String name,
244             int defaultValue) {
245         final int index = getAttributeIndex(namespace, name);
246         if (index == -1) return defaultValue;
247         try {
248             return getAttributeIntHex(index);
249         } catch (Exception ignored) {
250             return defaultValue;
251         }
252     }
253 
254     /**
255      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
256      *         default value if the value is malformed or undefined
257      */
getAttributeLong(@ullable String namespace, @NonNull String name, long defaultValue)258     default long getAttributeLong(@Nullable String namespace, @NonNull String name,
259             long defaultValue) {
260         final int index = getAttributeIndex(namespace, name);
261         if (index == -1) return defaultValue;
262         try {
263             return getAttributeLong(index);
264         } catch (Exception ignored) {
265             return defaultValue;
266         }
267     }
268 
269     /**
270      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
271      *         default value if the value is malformed or undefined
272      */
getAttributeLongHex(@ullable String namespace, @NonNull String name, long defaultValue)273     default long getAttributeLongHex(@Nullable String namespace, @NonNull String name,
274             long defaultValue) {
275         final int index = getAttributeIndex(namespace, name);
276         if (index == -1) return defaultValue;
277         try {
278             return getAttributeLongHex(index);
279         } catch (Exception ignored) {
280             return defaultValue;
281         }
282     }
283 
284     /**
285      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
286      *         default value if the value is malformed or undefined
287      */
getAttributeFloat(@ullable String namespace, @NonNull String name, float defaultValue)288     default float getAttributeFloat(@Nullable String namespace, @NonNull String name,
289             float defaultValue) {
290         final int index = getAttributeIndex(namespace, name);
291         if (index == -1) return defaultValue;
292         try {
293             return getAttributeFloat(index);
294         } catch (Exception ignored) {
295             return defaultValue;
296         }
297     }
298 
299     /**
300      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
301      *         default value if the value is malformed or undefined
302      */
getAttributeDouble(@ullable String namespace, @NonNull String name, double defaultValue)303     default double getAttributeDouble(@Nullable String namespace, @NonNull String name,
304             double defaultValue) {
305         final int index = getAttributeIndex(namespace, name);
306         if (index == -1) return defaultValue;
307         try {
308             return getAttributeDouble(index);
309         } catch (Exception ignored) {
310             return defaultValue;
311         }
312     }
313 
314     /**
315      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
316      *         default value if the value is malformed or undefined
317      */
getAttributeBoolean(@ullable String namespace, @NonNull String name, boolean defaultValue)318     default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name,
319             boolean defaultValue) {
320         final int index = getAttributeIndex(namespace, name);
321         if (index == -1) return defaultValue;
322         try {
323             return getAttributeBoolean(index);
324         } catch (Exception ignored) {
325             return defaultValue;
326         }
327     }
328 }
329