• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.app.slice;
18 
19 import java.util.Iterator;
20 import java.util.LinkedList;
21 import java.util.List;
22 import java.util.Objects;
23 import java.util.Queue;
24 import java.util.Spliterators;
25 import java.util.stream.Collectors;
26 import java.util.stream.Stream;
27 import java.util.stream.StreamSupport;
28 
29 /**
30  * A bunch of utilities for searching the contents of a slice.
31  * @hide
32  */
33 public class SliceQuery {
34     private static final String TAG = "SliceQuery";
35 
36     /**
37      * @hide
38      */
getPrimaryIcon(Slice slice)39     public static SliceItem getPrimaryIcon(Slice slice) {
40         for (SliceItem item : slice.getItems()) {
41             if (Objects.equals(item.getFormat(), SliceItem.FORMAT_IMAGE)) {
42                 return item;
43             }
44             if (!(compareTypes(item, SliceItem.FORMAT_SLICE)
45                     && item.hasHint(Slice.HINT_LIST))
46                     && !item.hasHint(Slice.HINT_ACTIONS)
47                     && !item.hasHint(Slice.HINT_LIST_ITEM)
48                     && !compareTypes(item, SliceItem.FORMAT_ACTION)) {
49                 SliceItem icon = SliceQuery.find(item, SliceItem.FORMAT_IMAGE);
50                 if (icon != null) {
51                     return icon;
52                 }
53             }
54         }
55         return null;
56     }
57 
58     /**
59      * @hide
60      */
findNotContaining(SliceItem container, List<SliceItem> list)61     public static SliceItem findNotContaining(SliceItem container, List<SliceItem> list) {
62         SliceItem ret = null;
63         while (ret == null && list.size() != 0) {
64             SliceItem remove = list.remove(0);
65             if (!contains(container, remove)) {
66                 ret = remove;
67             }
68         }
69         return ret;
70     }
71 
72     /**
73      * @hide
74      */
contains(SliceItem container, SliceItem item)75     private static boolean contains(SliceItem container, SliceItem item) {
76         if (container == null || item == null) return false;
77         return stream(container).filter(s -> (s == item)).findAny().isPresent();
78     }
79 
80     /**
81      * @hide
82      */
findAll(SliceItem s, String type)83     public static List<SliceItem> findAll(SliceItem s, String type) {
84         return findAll(s, type, (String[]) null, null);
85     }
86 
87     /**
88      * @hide
89      */
findAll(SliceItem s, String type, String hints, String nonHints)90     public static List<SliceItem> findAll(SliceItem s, String type, String hints, String nonHints) {
91         return findAll(s, type, new String[]{ hints }, new String[]{ nonHints });
92     }
93 
94     /**
95      * @hide
96      */
findAll(SliceItem s, String type, String[] hints, String[] nonHints)97     public static List<SliceItem> findAll(SliceItem s, String type, String[] hints,
98             String[] nonHints) {
99         return stream(s).filter(item -> compareTypes(item, type)
100                 && (item.hasHints(hints) && !item.hasAnyHints(nonHints)))
101                 .collect(Collectors.toList());
102     }
103 
104     /**
105      * @hide
106      */
find(Slice s, String type, String hints, String nonHints)107     public static SliceItem find(Slice s, String type, String hints, String nonHints) {
108         return find(s, type, new String[]{ hints }, new String[]{ nonHints });
109     }
110 
111     /**
112      * @hide
113      */
find(Slice s, String type)114     public static SliceItem find(Slice s, String type) {
115         return find(s, type, (String[]) null, null);
116     }
117 
118     /**
119      * @hide
120      */
find(SliceItem s, String type)121     public static SliceItem find(SliceItem s, String type) {
122         return find(s, type, (String[]) null, null);
123     }
124 
125     /**
126      * @hide
127      */
find(SliceItem s, String type, String hints, String nonHints)128     public static SliceItem find(SliceItem s, String type, String hints, String nonHints) {
129         return find(s, type, new String[]{ hints }, new String[]{ nonHints });
130     }
131 
132     /**
133      * @hide
134      */
find(Slice s, String type, String[] hints, String[] nonHints)135     public static SliceItem find(Slice s, String type, String[] hints, String[] nonHints) {
136         List<String> h = s.getHints();
137         return find(new SliceItem(s, SliceItem.FORMAT_SLICE, null, h.toArray(new String[h.size()])),
138                 type, hints, nonHints);
139     }
140 
141     /**
142      * @hide
143      */
find(SliceItem s, String type, String[] hints, String[] nonHints)144     public static SliceItem find(SliceItem s, String type, String[] hints, String[] nonHints) {
145         return stream(s).filter(item -> compareTypes(item, type)
146                 && (item.hasHints(hints) && !item.hasAnyHints(nonHints))).findFirst().orElse(null);
147     }
148 
149     /**
150      * @hide
151      */
stream(SliceItem slice)152     public static Stream<SliceItem> stream(SliceItem slice) {
153         Queue<SliceItem> items = new LinkedList();
154         items.add(slice);
155         Iterator<SliceItem> iterator = new Iterator<SliceItem>() {
156             @Override
157             public boolean hasNext() {
158                 return items.size() != 0;
159             }
160 
161             @Override
162             public SliceItem next() {
163                 SliceItem item = items.poll();
164                 if (compareTypes(item, SliceItem.FORMAT_SLICE)
165                         || compareTypes(item, SliceItem.FORMAT_ACTION)) {
166                     items.addAll(item.getSlice().getItems());
167                 }
168                 return item;
169             }
170         };
171         return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
172     }
173 
174     /**
175      * @hide
176      */
compareTypes(SliceItem item, String desiredType)177     public static boolean compareTypes(SliceItem item, String desiredType) {
178         final int typeLength = desiredType.length();
179         if (typeLength == 3 && desiredType.equals("*/*")) {
180             return true;
181         }
182         if (item.getSubType() == null && desiredType.indexOf('/') < 0) {
183             return item.getFormat().equals(desiredType);
184         }
185         return (item.getFormat() + "/" + item.getSubType())
186                 .matches(desiredType.replaceAll("\\*", ".*"));
187     }
188 }
189