1d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk/* 2d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * Copyright (C) 2017 The Android Open Source Project 3d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * 4d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 5d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * you may not use this file except in compliance with the License. 6d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * You may obtain a copy of the License at 7d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * 8d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 9d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * 10d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * Unless required by applicable law or agreed to in writing, software 11d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 12d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * See the License for the specific language governing permissions and 14d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * limitations under the License. 15d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 16d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 17d18651fa892b70afd21ded4ee56e1f2e3e7614c6Jason Monkpackage android.app.slice; 18d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 19d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.Iterator; 20d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.LinkedList; 21d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.List; 22d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monkimport java.util.Objects; 23d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.Queue; 24d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.Spliterators; 25d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.stream.Collectors; 26d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.stream.Stream; 27d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkimport java.util.stream.StreamSupport; 28d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 29d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk/** 30d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * A bunch of utilities for searching the contents of a slice. 31d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 32d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 33d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monkpublic class SliceQuery { 34d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk private static final String TAG = "SliceQuery"; 35d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 36d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 37d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 38d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 39800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor public static SliceItem getPrimaryIcon(Slice slice) { 40800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor for (SliceItem item : slice.getItems()) { 41d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk if (Objects.equals(item.getFormat(), SliceItem.FORMAT_IMAGE)) { 42800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor return item; 43800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor } 44d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk if (!(compareTypes(item, SliceItem.FORMAT_SLICE) 45d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk && item.hasHint(Slice.HINT_LIST)) 46800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor && !item.hasHint(Slice.HINT_ACTIONS) 47800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor && !item.hasHint(Slice.HINT_LIST_ITEM) 48d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk && !compareTypes(item, SliceItem.FORMAT_ACTION)) { 49d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk SliceItem icon = SliceQuery.find(item, SliceItem.FORMAT_IMAGE); 50800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor if (icon != null) { 51800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor return icon; 52800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor } 53800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor } 54800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor } 55800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor return null; 56800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor } 57800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor 58800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor /** 59800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor * @hide 60800ba36336d86fc8f26209cb30b845127133d7c2Mady Mellor */ 61d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk public static SliceItem findNotContaining(SliceItem container, List<SliceItem> list) { 62d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk SliceItem ret = null; 63d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk while (ret == null && list.size() != 0) { 64d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk SliceItem remove = list.remove(0); 65d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk if (!contains(container, remove)) { 66d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk ret = remove; 67d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 68d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 69d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return ret; 70d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 71d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 72d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 73d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 74d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 75d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk private static boolean contains(SliceItem container, SliceItem item) { 76d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk if (container == null || item == null) return false; 77d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return stream(container).filter(s -> (s == item)).findAny().isPresent(); 78d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 79d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 80d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 81d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 82d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 83d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static List<SliceItem> findAll(SliceItem s, String type) { 844575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor return findAll(s, type, (String[]) null, null); 854575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor } 864575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor 874575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor /** 884575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor * @hide 894575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor */ 90d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static List<SliceItem> findAll(SliceItem s, String type, String hints, String nonHints) { 91d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return findAll(s, type, new String[]{ hints }, new String[]{ nonHints }); 92d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 93d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 94d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 95d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 96d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 97d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static List<SliceItem> findAll(SliceItem s, String type, String[] hints, 98d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk String[] nonHints) { 99d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk return stream(s).filter(item -> compareTypes(item, type) 100d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk && (item.hasHints(hints) && !item.hasAnyHints(nonHints))) 101d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk .collect(Collectors.toList()); 102d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 103d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 104d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 105d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 106d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 107d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static SliceItem find(Slice s, String type, String hints, String nonHints) { 108d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return find(s, type, new String[]{ hints }, new String[]{ nonHints }); 109d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 110d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 111d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 112d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 113d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 114d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static SliceItem find(Slice s, String type) { 1154575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor return find(s, type, (String[]) null, null); 1164575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor } 1174575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor 1184575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor /** 1194575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor * @hide 1204575aa52d7736ab51a4f72f5852b98d357783839Mady Mellor */ 121d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static SliceItem find(SliceItem s, String type) { 122d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return find(s, type, (String[]) null, null); 123d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 124d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 125d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 126d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 127d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 128d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static SliceItem find(SliceItem s, String type, String hints, String nonHints) { 129d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return find(s, type, new String[]{ hints }, new String[]{ nonHints }); 130d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 131d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 132d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 133d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 134d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 135d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static SliceItem find(Slice s, String type, String[] hints, String[] nonHints) { 136d18651fa892b70afd21ded4ee56e1f2e3e7614c6Jason Monk List<String> h = s.getHints(); 137d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk return find(new SliceItem(s, SliceItem.FORMAT_SLICE, null, h.toArray(new String[h.size()])), 138d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk type, hints, nonHints); 139d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 140d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 141d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 142d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 143d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 144d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static SliceItem find(SliceItem s, String type, String[] hints, String[] nonHints) { 145d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk return stream(s).filter(item -> compareTypes(item, type) 146d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk && (item.hasHints(hints) && !item.hasAnyHints(nonHints))).findFirst().orElse(null); 147d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 148d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 149d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk /** 150d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk * @hide 151d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk */ 152d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk public static Stream<SliceItem> stream(SliceItem slice) { 153d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk Queue<SliceItem> items = new LinkedList(); 154d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk items.add(slice); 155d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk Iterator<SliceItem> iterator = new Iterator<SliceItem>() { 156d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk @Override 157d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk public boolean hasNext() { 158d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return items.size() != 0; 159d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 160d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk 161d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk @Override 162d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk public SliceItem next() { 163d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk SliceItem item = items.poll(); 164d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk if (compareTypes(item, SliceItem.FORMAT_SLICE) 165d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk || compareTypes(item, SliceItem.FORMAT_ACTION)) { 166d18651fa892b70afd21ded4ee56e1f2e3e7614c6Jason Monk items.addAll(item.getSlice().getItems()); 167d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 168d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return item; 169d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 170d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk }; 171d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); 172d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk } 173d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk 174d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk /** 175d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk * @hide 176d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk */ 177d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk public static boolean compareTypes(SliceItem item, String desiredType) { 178d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk final int typeLength = desiredType.length(); 179d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk if (typeLength == 3 && desiredType.equals("*/*")) { 180d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk return true; 181d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk } 182d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk if (item.getSubType() == null && desiredType.indexOf('/') < 0) { 183d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk return item.getFormat().equals(desiredType); 184d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk } 185d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk return (item.getFormat() + "/" + item.getSubType()) 186d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk .matches(desiredType.replaceAll("\\*", ".*")); 187d054fb36c79e4d10c8d35e2518923dc6f7c85e50Jason Monk } 188d9edfa94b0e2a3f294e8c6ad01d4403bb7a8b971Jason Monk} 189