<commit_before>package io.github.deltajulio.pantrybank.ui.adapter;

import android.content.Context;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.Query;

import java.util.HashMap;
import java.util.TreeMap;

import io.github.deltajulio.pantrybank.R;
import io.github.deltajulio.pantrybank.data.Category;
import io.github.deltajulio.pantrybank.data.FoodItem;

/**
 * Base class for our adapters.
 */
public abstract class BaseRecyclerAdapter
	extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
	private static final String TAG = BaseRecyclerAdapter.class.getSimpleName();

	// Firebase objects
	private Query categoriesRef;
	private Query itemsRef;
	private ChildEventListener categoryListener;
	private ChildEventListener itemListener;

	// Stored copy of our categories, used to sort data by category name
	private HashMap<String, Category> allCategories;
	// Categories that are VISIBLE. (has corresponding FoodItems that are also visible)
	private HashMap<String, Category> visibleCategories;
	// List of food items, to be used by the adapter
	private TreeMap<FoodKey, FoodItem> sortedFood;

	// Category vars
	private static final int categoryResourceId = R.layout.category;
	protected static final int CATEGORY_TYPE = 2;
	protected static final int FOOD_TYPE = 1;
	private final Context context;

	protected BaseRecyclerAdapter(Query categoriesRef, Query itemsRef, Context context)
	{
		this.categoriesRef = categoriesRef;
		this.itemsRef = itemsRef;
		this.context = context;
		allCategories = new HashMap<>();
		visibleCategories = new HashMap<>();
		sortedFood = new TreeMap<>();

		// Monitor changes to allCategories
		categoryListener = new ChildEventListener()
		{
			@Override
			public void onChildAdded(DataSnapshot dataSnapshot, String s)
			{
				// create Category from data snapshot
				Category category = dataSnapshot.getValue(Category.class);
				// add new category to containers
				allCategories.put(category.getCategoryId(), category);
			}

			@Override
			public void onChildChanged(DataSnapshot dataSnapshot, String s)
			{
				// create Category from data snapshot
				Category category = dataSnapshot.getValue(Category.class);
				// update stored version of category
				allCategories.put(category.getCategoryId(), category);
			}

			@Override
			public void onChildRemoved(DataSnapshot dataSnapshot)
			{
				// create Category from data snapshot
				Category category = dataSnapshot.getValue(Category.class);
				// remove category from container
				allCategories.remove(category.getCategoryId());
				visibleCategories.remove(category.getCategoryId());
			}

			@Override
			public void onChildMoved(DataSnapshot dataSnapshot, String s)
			{
				// Intentionally left blank
			}

			@Override
			public void onCancelled(DatabaseError databaseError)
			{
				Log.e(TAG, databaseError.toString());
			}
		};
		categoriesRef.addChildEventListener(categoryListener);

		// Monitor changes to food items
		itemListener = new ChildEventListener()
		{
			/**
			 * Searches for the category name, given the provided ID.
			 *
			 * @param categoryId The ID of the category being searched for.
			 * @return First returns TRUE if a match was found, with second being the name of the match.
			 * First returns FALSE if no match was found, with second being null.
			 */
			private Pair<Boolean, String> GetCategoryName(String categoryId)
			{
				Category category = allCategories.get(categoryId);
				if (category != null)
				{
					return Pair.create(true, category.getName());
				}

				return Pair.create(false, null);
			}

			@Override
			public void onChildAdded(final DataSnapshot dataSnapshot, final String s)
			{
				// create FoodItem from data snapshot
				FoodItem item = dataSnapshot.getValue(FoodItem.class);
				if (!ShouldBeDisplayed(item))
				{
					return;
				}

				// find category name
				Pair<Boolean, String> result = GetCategoryName(item.getCategoryId());
				if (result.first)
				{
					// add to container
					sortedFood.put(new FoodKey(result.second, item.getName()), item);
				} else
				{
					// category was not found, delay (wait for database to finish syncing)
					Log.w(TAG, "itemListener:onChildAdded: category was not found. Retrying!");
					Handler handler = new Handler();
					handler.postDelayed(new Runnable()
					{
						@Override
						public void run()
						{
							onChildAdded(dataSnapshot, s);
						}
					}, 100);
					return;
				}

				UpdateCategoryVisibility(item.getCategoryId());
				notifyDataSetChanged();
			}

			@Override
			public void onChildChanged(DataSnapshot dataSnapshot, String s)
			{
				// Create FoodItem from snapshot
				FoodItem item = dataSnapshot.getValue(FoodItem.class);

				// check if old key needs to be replaced
				for (FoodItem itemItr : sortedFood.values())
				{
					if (itemItr.getFoodId().equals(item.getFoodId()))
					{
						// if category has been changed, replace key
						if (!itemItr.getCategoryId().equals(item.getCategoryId()))
						{
							// Remove item from container
							Pair<Boolean, String> result = GetCategoryName(item.getCategoryId());
							if (!result.first)
							{
								throw null;
							}
							sortedFood.remove(new FoodKey(result.second, item.getName()));
						}
						break;
					}
				}
<commit_msg>Fix name update on db not updating live<commit_after>package io.github.deltajulio.pantrybank.ui.adapter;

import android.content.Context;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.Query;

import java.util.HashMap;
import java.util.TreeMap;

import io.github.deltajulio.pantrybank.R;
import io.github.deltajulio.pantrybank.data.Category;
import io.github.deltajulio.pantrybank.data.FoodItem;

/**
 * Base class for our adapters.
 */
public abstract class BaseRecyclerAdapter
	extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
	private static final String TAG = BaseRecyclerAdapter.class.getSimpleName();

	// Firebase objects
	private Query categoriesRef;
	private Query itemsRef;
	private ChildEventListener categoryListener;
	private ChildEventListener itemListener;

	// Stored copy of our categories, used to sort data by category name
	private HashMap<String, Category> allCategories;
	// Categories that are VISIBLE. (has corresponding FoodItems that are also visible)
	private HashMap<String, Category> visibleCategories;
	// List of food items, to be used by the adapter
	private TreeMap<FoodKey, FoodItem> sortedFood;

	// Category vars
	private static final int categoryResourceId = R.layout.category;
	protected static final int CATEGORY_TYPE = 2;
	protected static final int FOOD_TYPE = 1;
	private final Context context;

	protected BaseRecyclerAdapter(Query categoriesRef, Query itemsRef, Context context)
	{
		this.categoriesRef = categoriesRef;
		this.itemsRef = itemsRef;
		this.context = context;
		allCategories = new HashMap<>();
		visibleCategories = new HashMap<>();
		sortedFood = new TreeMap<>();

		// Monitor changes to allCategories
		categoryListener = new ChildEventListener()
		{
			@Override
			public void onChildAdded(DataSnapshot dataSnapshot, String s)
			{
				// create Category from data snapshot
				Category category = dataSnapshot.getValue(Category.class);
				// add new category to containers
				allCategories.put(category.getCategoryId(), category);
			}

			@Override
			public void onChildChanged(DataSnapshot dataSnapshot, String s)
			{
				// create Category from data snapshot
				Category category = dataSnapshot.getValue(Category.class);
				// update stored version of category
				allCategories.put(category.getCategoryId(), category);
			}

			@Override
			public void onChildRemoved(DataSnapshot dataSnapshot)
			{
				// create Category from data snapshot
				Category category = dataSnapshot.getValue(Category.class);
				// remove category from container
				allCategories.remove(category.getCategoryId());
				visibleCategories.remove(category.getCategoryId());
			}

			@Override
			public void onChildMoved(DataSnapshot dataSnapshot, String s)
			{
				// Intentionally left blank
			}

			@Override
			public void onCancelled(DatabaseError databaseError)
			{
				Log.e(TAG, databaseError.toString());
			}
		};
		categoriesRef.addChildEventListener(categoryListener);

		// Monitor changes to food items
		itemListener = new ChildEventListener()
		{
			/**
			 * Searches for the category name, given the provided ID.
			 *
			 * @param categoryId The ID of the category being searched for.
			 * @return First returns TRUE if a match was found, with second being the name of the match.
			 * First returns FALSE if no match was found, with second being null.
			 */
			private Pair<Boolean, String> GetCategoryName(String categoryId)
			{
				Category category = allCategories.get(categoryId);
				if (category != null)
				{
					return Pair.create(true, category.getName());
				}

				return Pair.create(false, null);
			}

			@Override
			public void onChildAdded(final DataSnapshot dataSnapshot, final String s)
			{
				// create FoodItem from data snapshot
				FoodItem item = dataSnapshot.getValue(FoodItem.class);
				if (!ShouldBeDisplayed(item))
				{
					return;
				}

				// find category name
				Pair<Boolean, String> result = GetCategoryName(item.getCategoryId());
				if (result.first)
				{
					// add to container
					sortedFood.put(new FoodKey(result.second, item.getName()), item);
				} else
				{
					// category was not found, delay (wait for database to finish syncing)
					Log.w(TAG, "itemListener:onChildAdded: category was not found. Retrying!");
					Handler handler = new Handler();
					handler.postDelayed(new Runnable()
					{
						@Override
						public void run()
						{
							onChildAdded(dataSnapshot, s);
						}
					}, 100);
					return;
				}

				UpdateCategoryVisibility(item.getCategoryId());
				notifyDataSetChanged();
			}

			@Override
			public void onChildChanged(DataSnapshot dataSnapshot, String s)
			{
				// Create FoodItem from snapshot
				FoodItem item = dataSnapshot.getValue(FoodItem.class);

				// check if old key needs to be replaced
				for (FoodItem itemItr : sortedFood.values())
				{
					if (itemItr.getFoodId().equals(item.getFoodId()))
					{
						// if category/name has been changed, replace key
						if (!itemItr.getCategoryId().equals(item.getCategoryId()) ||
								!itemItr.getName().equals(item.getName()))
						{
							// Remove item from container
							Pair<Boolean, String> result = GetCategoryName(itemItr.getCategoryId());
							if (!result.first)
							{
								throw null;
							}
							sortedFood.remove(new FoodKey(result.second, itemItr.getName()));
						}
						break;
					}
				}

{'fraction_non_alphanumeric': 0.09271465741543798, 'fraction_numerical': 0.0010407632263660018, 'mean_word_length': 3.6013567438148444, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2408895', 'n_tokens_mistral': 3979, 'n_tokens_neox': 3127, 'n_words': 902}