18a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk/*
28a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Copyright 2017 The Android Open Source Project
38a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk *
48a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
58a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * you may not use this file except in compliance with the License.
68a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * You may obtain a copy of the License at
78a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk *
88a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
98a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk *
108a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Unless required by applicable law or agreed to in writing, software
118a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
128a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * See the License for the specific language governing permissions and
148a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * limitations under the License.
158a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk */
168a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1785ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikaspackage androidx.slice.core;
188a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
190c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monkimport static android.app.slice.SliceItem.FORMAT_ACTION;
200c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monkimport static android.app.slice.SliceItem.FORMAT_SLICE;
210c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk
228a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkimport android.text.TextUtils;
238a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
24f68dde011de8fb4d616a09292524869f56d94110Jason Monkimport androidx.annotation.RestrictTo;
2585ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.Slice;
2685ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.SliceItem;
27dcb5e2f13fa8471f62a7f4625b4dc6e449358cbdJason Monk
28f68dde011de8fb4d616a09292524869f56d94110Jason Monkimport java.util.ArrayList;
29f68dde011de8fb4d616a09292524869f56d94110Jason Monkimport java.util.Iterator;
30f68dde011de8fb4d616a09292524869f56d94110Jason Monkimport java.util.List;
31f68dde011de8fb4d616a09292524869f56d94110Jason Monk
328a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk/**
338a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Utilities for finding content within a Slice.
348a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * @hide
358a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk */
368a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
378a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkpublic class SliceQuery {
388a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
398a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
408a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
418a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    public static boolean hasAnyHints(SliceItem item, String... hints) {
428a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        if (hints == null) return false;
438a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        List<String> itemHints = item.getHints();
448a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        for (String hint : hints) {
458a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            if (itemHints.contains(hint)) {
468a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                return true;
478a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            }
488a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        }
498a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        return false;
508a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
518a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
528a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
538a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
548a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    public static boolean hasHints(SliceItem item, String... hints) {
558a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        if (hints == null) return true;
568a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        List<String> itemHints = item.getHints();
578a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        for (String hint : hints) {
588a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            if (!TextUtils.isEmpty(hint) && !itemHints.contains(hint)) {
598a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                return false;
608a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            }
618a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        }
628a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        return true;
638a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
648a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
658a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
668a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
678a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    public static boolean hasHints(Slice item, String... hints) {
688a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        if (hints == null) return true;
698a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        List<String> itemHints = item.getHints();
708a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        for (String hint : hints) {
718a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            if (!TextUtils.isEmpty(hint) && !itemHints.contains(hint)) {
728a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                return false;
738a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            }
748a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        }
758a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        return true;
768a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
778a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
788a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
798a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
808a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    public static SliceItem findNotContaining(SliceItem container, List<SliceItem> list) {
818a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        SliceItem ret = null;
828a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        while (ret == null && list.size() != 0) {
838a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            SliceItem remove = list.remove(0);
848a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            if (!contains(container, remove)) {
858a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                ret = remove;
868a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            }
878a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        }
888a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        return ret;
898a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
908a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
918a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
928a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
932a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk    private static boolean contains(SliceItem container, final SliceItem item) {
948a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        if (container == null || item == null) return false;
95f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return findFirst(filter(stream(container), new Filter<SliceItem>() {
962a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            @Override
97f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem s) {
982a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                return s == item;
992a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            }
100f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }), null) != null;
1018a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1028a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1038a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1048a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1050c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static List<SliceItem> findAll(SliceItem s, String format) {
1060c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return findAll(s, format, (String[]) null, null);
1078a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1088a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1098a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1108a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1110c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static List<SliceItem> findAll(Slice s, String format, String hints, String nonHints) {
1120c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return findAll(s, format, new String[]{ hints }, new String[]{ nonHints });
1138a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1148a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1158a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1168a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1170c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static List<SliceItem> findAll(SliceItem s, String format, String hints,
1180c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk            String nonHints) {
1190c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return findAll(s, format, new String[]{ hints }, new String[]{ nonHints });
1208a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1218a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1228a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1238a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1242a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk    public static List<SliceItem> findAll(Slice s, final String format, final String[] hints,
1252a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            final String[] nonHints) {
126f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return collect(filter(stream(s), new Filter<SliceItem>() {
1272a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            @Override
128f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem item) {
1292a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                return checkFormat(item, format)
1302a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
1312a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            }
132f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }));
1338a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1348a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1358a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1368a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1372a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk    public static List<SliceItem> findAll(SliceItem s, final String format, final String[] hints,
1382a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            final String[] nonHints) {
139f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return collect(filter(stream(s), new Filter<SliceItem>() {
1402a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            @Override
141f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem item) {
1422a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                return checkFormat(item, format)
1432a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
1442a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            }
145f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }));
1468a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1478a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1488a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1498a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1500c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static SliceItem find(Slice s, String format, String hints, String nonHints) {
1510c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return find(s, format, new String[]{ hints }, new String[]{ nonHints });
1528a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1538a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1548a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1558a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1560c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static SliceItem find(Slice s, String format) {
1570c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return find(s, format, (String[]) null, null);
1588a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1598a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1608a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1618a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1620c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static SliceItem find(SliceItem s, String format) {
1630c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return find(s, format, (String[]) null, null);
1648a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1658a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1668a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1678a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1680c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    public static SliceItem find(SliceItem s, String format, String hints, String nonHints) {
1690c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return find(s, format, new String[]{ hints }, new String[]{ nonHints });
1708a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1718a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1728a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1738a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
1742a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk    public static SliceItem find(Slice s, final String format, final String[] hints,
1752a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            final String[] nonHints) {
176f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return findFirst(filter(stream(s), new Filter<SliceItem>() {
1772a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            @Override
178f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem item) {
1792a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                return checkFormat(item, format)
1802a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
1812a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            }
182f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }), null);
1838a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
1848a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
1858a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
1868a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
18798ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk    public static SliceItem findSubtype(Slice s, final String format, final String subtype) {
188f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return findFirst(filter(stream(s), new Filter<SliceItem>() {
18998ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk            @Override
190f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem item) {
19198ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk                return checkFormat(item, format) && checkSubtype(item, subtype);
19298ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk            }
193f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }), null);
19498ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk    }
19598ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk
19698ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk    /**
19798ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monk     */
1982a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk    public static SliceItem findSubtype(SliceItem s, final String format, final String subtype) {
199f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return findFirst(filter(stream(s), new Filter<SliceItem>() {
2002a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            @Override
201f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem item) {
2022a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                return checkFormat(item, format) && checkSubtype(item, subtype);
2032a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            }
204f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }), null);
2050c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    }
2060c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk
2075b2c0ce4135a0531d1b8ddb4bd35698859678b83Mady Mellor    /**
2085b2c0ce4135a0531d1b8ddb4bd35698859678b83Mady Mellor     */
2092a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk    public static SliceItem find(SliceItem s, final String format, final String[] hints,
2102a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            final String[] nonHints) {
211f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return findFirst(filter(stream(s), new Filter<SliceItem>() {
2122a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            @Override
213f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean filter(SliceItem item) {
2142a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                return checkFormat(item, format)
2152a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
2162a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk            }
217f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }), null);
2188a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
2198a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
2200c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    private static boolean checkFormat(SliceItem item, String format) {
2210c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return format == null || format.equals(item.getFormat());
2220c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    }
2230c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk
2240c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    private static boolean checkSubtype(SliceItem item, String subtype) {
2250c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk        return subtype == null || subtype.equals(item.getSubType());
2260c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk    }
2270c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk
2288a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
2298a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
230f68dde011de8fb4d616a09292524869f56d94110Jason Monk    public static Iterator<SliceItem> stream(SliceItem slice) {
231f68dde011de8fb4d616a09292524869f56d94110Jason Monk        ArrayList<SliceItem> items = new ArrayList<>();
2328a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        items.add(slice);
2338a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        return getSliceItemStream(items);
2348a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
2358a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
2368a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
2378a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
238f68dde011de8fb4d616a09292524869f56d94110Jason Monk    public static Iterator<SliceItem> stream(Slice slice) {
239f68dde011de8fb4d616a09292524869f56d94110Jason Monk        ArrayList<SliceItem> items = new ArrayList<>();
2408a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        items.addAll(slice.getItems());
2418a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        return getSliceItemStream(items);
2428a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
2438a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
2448a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    /**
2458a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk     */
246f68dde011de8fb4d616a09292524869f56d94110Jason Monk    private static Iterator<SliceItem> getSliceItemStream(final ArrayList<SliceItem> items) {
247f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return new Iterator<SliceItem>() {
2488a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            @Override
2498a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            public boolean hasNext() {
2508a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                return items.size() != 0;
2518a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            }
2528a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk
2538a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            @Override
2548a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            public SliceItem next() {
255f68dde011de8fb4d616a09292524869f56d94110Jason Monk                SliceItem item = items.remove(0);
2560c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk                if (FORMAT_SLICE.equals(item.getFormat())
2570c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk                        || FORMAT_ACTION.equals(item.getFormat())) {
2588a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                    items.addAll(item.getSlice().getItems());
2598a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                }
2608a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk                return item;
2618a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk            }
2628a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk        };
263f68dde011de8fb4d616a09292524869f56d94110Jason Monk    }
264f68dde011de8fb4d616a09292524869f56d94110Jason Monk
265f68dde011de8fb4d616a09292524869f56d94110Jason Monk    private static <T> List<T> collect(Iterator<T> iter) {
266f68dde011de8fb4d616a09292524869f56d94110Jason Monk        List<T> list = new ArrayList<>();
267f68dde011de8fb4d616a09292524869f56d94110Jason Monk        while (iter.hasNext()) list.add(iter.next());
268f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return list;
269f68dde011de8fb4d616a09292524869f56d94110Jason Monk    }
270f68dde011de8fb4d616a09292524869f56d94110Jason Monk
271f68dde011de8fb4d616a09292524869f56d94110Jason Monk    private static <T> Iterator<T> filter(final Iterator<T> input, final Filter<T> f) {
272f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return new Iterator<T>() {
273f68dde011de8fb4d616a09292524869f56d94110Jason Monk            T mNext = findNext();
274f68dde011de8fb4d616a09292524869f56d94110Jason Monk
275f68dde011de8fb4d616a09292524869f56d94110Jason Monk            private T findNext() {
276f68dde011de8fb4d616a09292524869f56d94110Jason Monk                while (input.hasNext()) {
277f68dde011de8fb4d616a09292524869f56d94110Jason Monk                    T i = input.next();
278f68dde011de8fb4d616a09292524869f56d94110Jason Monk                    if (f.filter(i)) {
279f68dde011de8fb4d616a09292524869f56d94110Jason Monk                        return i;
280f68dde011de8fb4d616a09292524869f56d94110Jason Monk                    }
281f68dde011de8fb4d616a09292524869f56d94110Jason Monk                }
282f68dde011de8fb4d616a09292524869f56d94110Jason Monk                return null;
283f68dde011de8fb4d616a09292524869f56d94110Jason Monk            }
284f68dde011de8fb4d616a09292524869f56d94110Jason Monk
285f68dde011de8fb4d616a09292524869f56d94110Jason Monk            @Override
286f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public boolean hasNext() {
287f68dde011de8fb4d616a09292524869f56d94110Jason Monk                return mNext != null;
288f68dde011de8fb4d616a09292524869f56d94110Jason Monk            }
289f68dde011de8fb4d616a09292524869f56d94110Jason Monk
290f68dde011de8fb4d616a09292524869f56d94110Jason Monk            @Override
291f68dde011de8fb4d616a09292524869f56d94110Jason Monk            public T next() {
292f68dde011de8fb4d616a09292524869f56d94110Jason Monk                T ret = mNext;
293f68dde011de8fb4d616a09292524869f56d94110Jason Monk                mNext = findNext();
294f68dde011de8fb4d616a09292524869f56d94110Jason Monk                return ret;
295f68dde011de8fb4d616a09292524869f56d94110Jason Monk            }
296f68dde011de8fb4d616a09292524869f56d94110Jason Monk        };
297f68dde011de8fb4d616a09292524869f56d94110Jason Monk    }
298f68dde011de8fb4d616a09292524869f56d94110Jason Monk
299f68dde011de8fb4d616a09292524869f56d94110Jason Monk    private static <T> T findFirst(Iterator<T> filter, T def) {
300f68dde011de8fb4d616a09292524869f56d94110Jason Monk        while (filter.hasNext()) {
301f68dde011de8fb4d616a09292524869f56d94110Jason Monk            T r = filter.next();
302f68dde011de8fb4d616a09292524869f56d94110Jason Monk            if (r != null) return r;
303f68dde011de8fb4d616a09292524869f56d94110Jason Monk        }
304f68dde011de8fb4d616a09292524869f56d94110Jason Monk        return def;
305f68dde011de8fb4d616a09292524869f56d94110Jason Monk    }
306f68dde011de8fb4d616a09292524869f56d94110Jason Monk
307f68dde011de8fb4d616a09292524869f56d94110Jason Monk    private interface Filter<T> {
308f68dde011de8fb4d616a09292524869f56d94110Jason Monk        boolean filter(T input);
3098a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk    }
3100f4ca634bbc43ddff900c35f7d2a43b55d8c830dJake Wharton
3110f4ca634bbc43ddff900c35f7d2a43b55d8c830dJake Wharton    private SliceQuery() {
3120f4ca634bbc43ddff900c35f7d2a43b55d8c830dJake Wharton    }
3138a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk}
314