<commit_before>package trikita.anvil;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.lang.reflect.InvocationTargetException;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

/**
 * Anvil class is a namespace for top-level static methods and interfaces. Most
 * users would only use it to call {@code Anvil.render()}.
 *
 * Internally, Anvil class defines how Renderables are mounted into Views
 * and how they are lazily rendered, and this is the key functionality of the
 * Anvil library.
 */
public final class Anvil {

	private final static Map<View, Mount> mounts = new WeakHashMap<>();
	private static Mount currentMount = null;

	private static Handler anvilUIHandler = null;

	/** Renderable can be mounted and rendered using Anvil library. */
	public interface Renderable {
		/** This method is a place to define the structure of your layout, its view
		 * properties and data bindings. */
		void view();
	}

	/** AttrFunc replaces the old value with the new value in the given view. */
	public interface AttrFunc<T> {
		void apply(View v, T newValue, T oldValue);
	}

	interface ViewFactory {
		View fromClass(Context c, Class<? extends View> v);
		View fromXml(Context c, int xmlId);
		View fromId(View v, int viewId);
	}

	final static ViewFactory viewFactory = new ViewFactory() {
		public View fromClass(Context c, Class<? extends View> viewClass) {
			try {
				return viewClass.getConstructor(Context.class).newInstance(c);
			} catch (InvocationTargetException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			} catch (NoSuchMethodException e) {
				throw new RuntimeException(e);
			} catch (InstantiationException e) {
				throw new RuntimeException(e);
			}
		}
		public View fromXml(Context c, int xmlId) {
			return LayoutInflater.from(c).inflate(xmlId, null, false);
		}
		public View fromId(View v, int viewId) {
			return v.findViewById(viewId);
		}
	};

	private Anvil() {}

	private final static Runnable anvilRenderRunnable = new Runnable() {
		public void run() {
			Anvil.render();
		}
	};

	/** Starts the new rendering cycle updating all mounted
	 * renderables. Update happens in a lazy manner, only the values that has
	 * been changed since last rendering cycle will be actually updated in the
	 * views. This method can be called from any thread, so it's safe to use
	 * {@code Anvil.render()} in background services. */
	public static void render() {
		// If Anvil.render() is called on a non-UI thread, use UI Handler
		if (Looper.myLooper() != Looper.getMainLooper()) {
			synchronized (Anvil.class) {
				if (anvilUIHandler == null) {
					anvilUIHandler = new Handler(Looper.getMainLooper());
				}
			}
			anvilUIHandler.removeCallbacksAndMessages(null);
			anvilUIHandler.post(anvilRenderRunnable);
			return;
		}
		Set<Mount> keys = new HashSet<>();
		keys.addAll(mounts.values());
		for (Mount m : keys) {
			render(m);
		}
	}

	/**
	 * Mounts a renderable function defining the layout into a View. If host is a
	 * viewgroup it is assumed to be empty, so the Renderable would define what
	 * its child views would be.
	 * @param v a View into which the renderable r will be mounted
	 * @param r a Renderable to mount into a View
	 */
	public static <T extends View> T mount(T v, Renderable r) {
		Mount m = mounts.get(v);
		if (m == null) {
			m = new Mount(v, r);
			mounts.put(v, m);
		} else {
			m.setRenderable(r);
		}
		render(m);
		return v;
	}

	/**
	 * Unmounts a  mounted renderable. This would also clean up all the child
	 * views inside the parent ViewGroup, which acted as a mount point.
	 * @param v A mount point to unmount from its View
	 */
	public static void unmount(View v) {
		Mount m = mounts.get(v);
		if (m != null) {
			mounts.remove(v);
			if (v instanceof ViewGroup) {
				ViewGroup vg = (ViewGroup) v;
				vg.removeViews(0, vg.getChildCount());
			}
		}
	}

	/**
	 * Returns currently rendered Mount point. Must be called from the
	 * Renderable's view() method, otherwise it returns null 
	 * @return current mount point 
	 */
	static Mount currentMount() {
		return currentMount;
	}

	/**
	 * Returns currently rendered View. It allows to access the real view from
	 * inside the Renderable.
	 * @return currently rendered View
	 */
	@SuppressWarnings("unchecked")
	public static <T extends View> T currentView() {
		if (currentMount() == null) {
			return null;
		}
		Node node = currentMount.stack.peek();
		return (T) (node == null ? currentMount.rootView.get() : node.view);
	}

	static void render(Mount m) {<commit_msg>Unmounting views recursively<commit_after>package trikita.anvil;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.lang.reflect.InvocationTargetException;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

/**
 * Anvil class is a namespace for top-level static methods and interfaces. Most
 * users would only use it to call {@code Anvil.render()}.
 *
 * Internally, Anvil class defines how Renderables are mounted into Views
 * and how they are lazily rendered, and this is the key functionality of the
 * Anvil library.
 */
public final class Anvil {

	private final static Map<View, Mount> mounts = new WeakHashMap<>();
	private static Mount currentMount = null;

	private static Handler anvilUIHandler = null;

	/** Renderable can be mounted and rendered using Anvil library. */
	public interface Renderable {
		/** This method is a place to define the structure of your layout, its view
		 * properties and data bindings. */
		void view();
	}

	/** AttrFunc replaces the old value with the new value in the given view. */
	public interface AttrFunc<T> {
		void apply(View v, T newValue, T oldValue);
	}

	interface ViewFactory {
		View fromClass(Context c, Class<? extends View> v);
		View fromXml(Context c, int xmlId);
		View fromId(View v, int viewId);
	}

	final static ViewFactory viewFactory = new ViewFactory() {
		public View fromClass(Context c, Class<? extends View> viewClass) {
			try {
				return viewClass.getConstructor(Context.class).newInstance(c);
			} catch (InvocationTargetException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			} catch (NoSuchMethodException e) {
				throw new RuntimeException(e);
			} catch (InstantiationException e) {
				throw new RuntimeException(e);
			}
		}
		public View fromXml(Context c, int xmlId) {
			return LayoutInflater.from(c).inflate(xmlId, null, false);
		}
		public View fromId(View v, int viewId) {
			return v.findViewById(viewId);
		}
	};

	private Anvil() {}

	private final static Runnable anvilRenderRunnable = new Runnable() {
		public void run() {
			Anvil.render();
		}
	};

	/** Starts the new rendering cycle updating all mounted
	 * renderables. Update happens in a lazy manner, only the values that has
	 * been changed since last rendering cycle will be actually updated in the
	 * views. This method can be called from any thread, so it's safe to use
	 * {@code Anvil.render()} in background services. */
	public static void render() {
		// If Anvil.render() is called on a non-UI thread, use UI Handler
		if (Looper.myLooper() != Looper.getMainLooper()) {
			synchronized (Anvil.class) {
				if (anvilUIHandler == null) {
					anvilUIHandler = new Handler(Looper.getMainLooper());
				}
			}
			anvilUIHandler.removeCallbacksAndMessages(null);
			anvilUIHandler.post(anvilRenderRunnable);
			return;
		}
		Set<Mount> keys = new HashSet<>();
		keys.addAll(mounts.values());
		for (Mount m : keys) {
			render(m);
		}
	}

	/**
	 * Mounts a renderable function defining the layout into a View. If host is a
	 * viewgroup it is assumed to be empty, so the Renderable would define what
	 * its child views would be.
	 * @param v a View into which the renderable r will be mounted
	 * @param r a Renderable to mount into a View
	 */
	public static <T extends View> T mount(T v, Renderable r) {
		Mount m = mounts.get(v);
		if (m == null) {
			m = new Mount(v, r);
			mounts.put(v, m);
		} else {
			m.setRenderable(r);
		}
		render(m);
		return v;
	}

	/**
	 * Unmounts a  mounted renderable. This would also clean up all the child
	 * views inside the parent ViewGroup, which acted as a mount point.
	 * @param v A mount point to unmount from its View
	 */
	public static void unmount(View v) {
		Mount m = mounts.get(v);
		if (m != null) {
			mounts.remove(v);
			if (v instanceof ViewGroup) {
				ViewGroup viewGroup = (ViewGroup) v;

				int childCount = viewGroup.getChildCount();
				for (int i = 0; i < childCount; i++) {
					unmount(viewGroup.getChildAt(i));
				}

				viewGroup.removeViews(0, childCount);
			}
		}
	}

	/**
	 * Returns currently rendered Mount point. Must be called from the
	 * Renderable's view() method, otherwise it returns null 
	 * @return current mount point 
	 */
	static Mount currentMount() {
		return currentMount;
	}

	/**
	 * Returns currently rendered View. It allows to access the real view from
	 * inside the Renderable.
	 * @return currently rendered View
	 */
	@SuppressWarnings("unchecked")
	public static <T extends View> T currentView() {
		if (currentMount() == null) {
			return null;
		}
		Node node = currentMount.stack.peek();
		return (T) (node == null ? currentMount.rootView.get() : node.view);
	}

	static void render(Mount m) {
{'fraction_non_alphanumeric': 0.10267722851699589, 'fraction_numerical': 0.00030081219292088637, 'mean_word_length': 3.641228478362029, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, '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': '3303361', 'n_tokens_mistral': 3343, 'n_tokens_neox': 2999, 'n_words': 1103}