Home | History | Annotate | Download | only in slice
      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      */
     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      */
     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      */
     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      */
     83     public static List<SliceItem> findAll(SliceItem s, String type) {
     84         return findAll(s, type, (String[]) null, null);
     85     }
     86 
     87     /**
     88      * @hide
     89      */
     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      */
     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      */
    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      */
    114     public static SliceItem find(Slice s, String type) {
    115         return find(s, type, (String[]) null, null);
    116     }
    117 
    118     /**
    119      * @hide
    120      */
    121     public static SliceItem find(SliceItem s, String type) {
    122         return find(s, type, (String[]) null, null);
    123     }
    124 
    125     /**
    126      * @hide
    127      */
    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      */
    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      */
    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      */
    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      */
    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