package com.google.firebase.example.fireeats.util; import android.content.Context; import android.support.annotation.WorkerThread; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; import com.google.firebase.example.fireeats.R; import com.google.firebase.example.fireeats.model.Restaurant; import com.google.firebase.firestore.CollectionReference; import com.google.firebase.firestore.DocumentSnapshot; import com.google.firebase.firestore.Query; import com.google.firebase.firestore.QuerySnapshot; import com.google.firebase.firestore.WriteBatch; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * Utilities for Restaurants. */ public class RestaurantUtil { private static final String TAG = "RestaurantUtil"; private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); private static final String RESTAURANT_URL_FMT = "https://storage.googleapis.com/firestorequickstarts.appspot.com/food_%d.png"; private static final int MAX_IMAGE_NUM = 22; private static final String[] NAME_FIRST_WORDS = { "Foo", "Bar", "Baz", "Qux", "Fire", "Sam's", "World Famous", "Google", "The Best", }; private static final String[] NAME_SECOND_WORDS = { "Restaurant", "Cafe", "Spot", "Eatin' Place", "Eatery", "Drive Thru", "Diner", }; /** * Create a random Restaurant POJO. */ public static Restaurant getRandom(Context context) { Restaurant restaurant = new Restaurant(); Random random = new Random(); // Cities (first elemnt is 'Any') String[] cities = context.getResources().getStringArray(R.array.cities); cities = Arrays.copyOfRange(cities, 1, cities.length); // Categories (first element is 'Any') String[] categories = context.getResources().getStringArray(R.array.categories); categories = Arrays.copyOfRange(categories, 1, categories.length); int[] prices = new int[]{1, 2, 3}; restaurant.name = getRandomName(random); restaurant.city = getRandomString(cities, random); restaurant.category = getRandomString(categories, random); restaurant.photo = getRandomImageUrl(random); restaurant.price = getRandomInt(prices, random); restaurant.numRatings = random.nextInt(20); // Note: average rating intentionally not set return restaurant; } /** * Get a random image. */ private static String getRandomImageUrl(Random random) { // Integer between 1 and MAX_IMAGE_NUM (inclusive) int id = random.nextInt(MAX_IMAGE_NUM) + 1; return String.format(Locale.getDefault(), RESTAURANT_URL_FMT, id); } /** * Get price represented as dollar signs. */ public static String getPriceString(Restaurant restaurant) { return restaurant != null ? getPriceString(restaurant.price) : null; } /** * Get price represented as dollar signs. */ public static String getPriceString(int priceInt) { switch (priceInt) { case 1: return "$"; case 2: return "$$"; case 3: default: return "$$$"; } } /** * Delete all documents in a collection. Uses an Executor to perform work on a background * thread. This does *not* automatically discover and delete subcollections. */ private static Task<Void> deleteCollection(final CollectionReference collection, final int batchSize, Executor executor) { // Perform the delete operation on the provided Executor, which allows us to use // simpler synchronous logic without blocking the main thread. return Tasks.call(executor, () -> { // Get the first batch of documents in the collection Query query = collection.orderBy("__name__").limit(batchSize); // Get a list of deleted documents List<DocumentSnapshot> deleted = deleteQueryBatch(query); // While the deleted documents in the last batch indicate that there // may still be more documents in the collection, page down to the // next batch and delete again while (deleted.size() >= batchSize) { // Move the query cursor to start after the last doc in the batch DocumentSnapshot last = deleted.get(deleted.size() - 1); query = collection.orderBy("__name__") .startAfter(last.getId()) .limit(batchSize); deleted = deleteQueryBatch(query); } return null; }); } /** * Delete all results from a query in a single WriteBatch. Must be run on a worker thread * to avoid blocking/crashing the main thread. */ @WorkerThread private static List<DocumentSnapshot> deleteQueryBatch(final Query query) throws Exception { QuerySnapshot querySnapshot = Tasks.await(query.get()); WriteBatch batch = query.getFirestore().batch(); for (DocumentSnapshot snapshot : querySnapshot) { batch.delete(snapshot.getReference()); } Tasks.await(batch.commit()); return querySnapshot.getDocuments(); } /** * Delete all restaurants. */ public static Task<Void> deleteAll(final CollectionReference ref) { return deleteCollection(ref, 25, EXECUTOR); } private static double getRandomRating(Random random) { double min = 1.0; return min + (random.nextDouble() * 4.0); } private static String getRandomName(Random random) { return getRandomString(NAME_FIRST_WORDS, random) + " " + getRandomString(NAME_SECOND_WORDS, random); } private static String getRandomString(String[] array, Random random) { int ind = random.nextInt(array.length); return array[ind]; } private static int getRandomInt(int[] array, Random random) { int ind = random.nextInt(array.length); return array[ind]; } }