<commit_before>package org.mtransit.android.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.WeakHashMap;

import org.mtransit.android.R;
import org.mtransit.android.commons.CollectionUtils;
import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.PackageManagerUtils;
import org.mtransit.android.commons.TaskUtils;
import org.mtransit.android.commons.task.MTAsyncTask;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.SparseArray;

public class DataSourceProvider implements MTLog.Loggable {

	private static final String TAG = DataSourceProvider.class.getSimpleName();

	@Override
	public String getLogTag() {
		return TAG;
	}

	private static DataSourceProvider instance = null;

	public static DataSourceProvider get(Context context) {
		if (instance == null) {
			initInstance(context);
		}
		return instance;
	}

	private synchronized static void initInstance(Context context) {
		if (instance != null) {
			return;
		}
		if (context == null) {
			return;
		}
		DataSourceProvider newInstance = new DataSourceProvider();
		newInstance.init(context);
		instance = newInstance;
	}

	public static boolean isSet() {
		return instance != null;
	}

	public static void destroy() {
		if (instance != null) {
			instance.onDestroy();
			instance = null;
		}
	}

	private static boolean resumed = false;

	public static void onPause() {
		resumed = false;
	}

	public static void onResume() {
		resumed = true;
		if (triggerModulesUpdated) {
			triggerModulesUpdated();
		}
	}

	private static String agencyProviderMetaData;

	public static String getAgencyProviderMetaData(Context context) {
		if (agencyProviderMetaData == null) {
			agencyProviderMetaData = context == null ? null : context.getString(R.string.agency_provider);
		}
		return agencyProviderMetaData;
	}

	private static String scheduleProviderMetaData;

	public static String getScheduleProviderMetaData(Context context) {
		if (scheduleProviderMetaData == null) {
			scheduleProviderMetaData = context == null ? null : context.getString(R.string.schedule_provider);
		}
		return scheduleProviderMetaData;
	}

	private static String statusProviderMetaData;

	public static String getStatusProviderMetaData(Context context) {
		if (statusProviderMetaData == null) {
			statusProviderMetaData = context == null ? null : context.getString(R.string.status_provider);
		}
		return statusProviderMetaData;
	}

	private static String serviceUpdateProviderMetaData;

	public static String getServiceUpdateProviderMetaData(Context context) {
		if (serviceUpdateProviderMetaData == null) {
			serviceUpdateProviderMetaData = context == null ? null : context.getString(R.string.service_update_provider);
		}
		return serviceUpdateProviderMetaData;
	}

	private static String newsProviderMetaData;

	public static String getNewsProviderMetaData(Context context) {
		if (newsProviderMetaData == null) {
			newsProviderMetaData = context == null ? null : context.getString(R.string.news_provider);
		}
		return newsProviderMetaData;
	}

	public static boolean isProvider(Context context, String pkg) {
		if (TextUtils.isEmpty(pkg)) {
			return false;
		}
		ProviderInfo[] providers = PackageManagerUtils.findContentProvidersWithMetaData(context, pkg);
		if (providers == null || providers.length == 0) {
			return false;
		}
		String agencyProviderMetaData = getAgencyProviderMetaData(context);
		String scheduleProviderMetaData = getScheduleProviderMetaData(context);
		String statusProviderMetaData = getStatusProviderMetaData(context);
		String serviceUpdateProviderMetaData = getServiceUpdateProviderMetaData(context);
		String newsProviderMetaData = getNewsProviderMetaData(context);
		for (ProviderInfo provider : providers) {
			if (provider.metaData != null) {
				if (agencyProviderMetaData.equals(provider.metaData.getString(agencyProviderMetaData))) {
					return true;
				}
				if (scheduleProviderMetaData.equals(provider.metaData.getString(scheduleProviderMetaData))) {
					return true;
				}
				if (statusProviderMetaData.equals(provider.metaData.getString(statusProviderMetaData))) {
					return true;
				}
				if (serviceUpdateProviderMetaData.equals(provider.metaData.getString(serviceUpdateProviderMetaData))) {
					return true;
				}
				if (newsProviderMetaData.equals(provider.metaData.getString(newsProviderMetaData))) {
					return true;
				}
			}
		}
		return false;
	}

	public static boolean resetIfNecessary(Context optContext) {
		if (instance != null) {
			if (optContext == null) { // cannot compare w/o context
				destroy();
				triggerModulesUpdated();
				return true;
			} else {
				if (hasChanged(instance, optContext)) {
					destroy();
					triggerModulesUpdated();
					return true;
				}
			}
		}
		return false;
	}

	private synchronized static boolean hasChanged(DataSourceProvider current, Context optContext) {
		if (current == null) {
			return true;
		}
		if (optContext == null) {
			return true;
		}
		String agencyProviderMetaData = getAgencyProviderMetaData(optContext);
		String scheduleProviderMetaData = getScheduleProviderMetaData(optContext);
		String statusProviderMetaData = getStatusProviderMetaData(optContext);
		String serviceUpdateProviderMetaData = getServiceUpdateProviderMetaData(optContext);
		String newsProviderMetaData = getNewsProviderMetaData(optContext);
		int nbAgencyProviders = 0, nbScheduleProviders = 0, nbStatusProviders = 0, nbServiceUpdateProviders = 0, nbNewsProviders = 0;
		PackageManager pm = optContext.getPackageManager();
		for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA)) {
			ProviderInfo[] providers = packageInfo.providers;
			if (providers != null) {
				for (ProviderInfo provider : providers) {
					if (provider.metaData != null) {
						if (agencyProviderMetaData.equals(provider.metaData.getString(agencyProviderMetaData))) {
							if (!instance.hasAgency(provider.authority)) {
								return true;
							}
							nbAgencyProviders++;
						}
						if (statusProviderMetaData.equals(provider.metaData.getString(statusProviderMetaData))) {
							if (instance.getStatusProvider(provider.authority) == null) {
								return true;<commit_msg>Fix NPE crash in production #GAV4<commit_after>package org.mtransit.android.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.WeakHashMap;

import org.mtransit.android.R;
import org.mtransit.android.commons.CollectionUtils;
import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.PackageManagerUtils;
import org.mtransit.android.commons.TaskUtils;
import org.mtransit.android.commons.task.MTAsyncTask;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.SparseArray;

public class DataSourceProvider implements MTLog.Loggable {

	private static final String TAG = DataSourceProvider.class.getSimpleName();

	@Override
	public String getLogTag() {
		return TAG;
	}

	private static DataSourceProvider instance = null;

	public static DataSourceProvider get(Context context) {
		if (instance == null) {
			initInstance(context);
		}
		return instance;
	}

	private synchronized static void initInstance(Context context) {
		if (instance != null) {
			return;
		}
		if (context == null) {
			return;
		}
		DataSourceProvider newInstance = new DataSourceProvider();
		newInstance.init(context);
		instance = newInstance;
	}

	public static boolean isSet() {
		return instance != null;
	}

	public static void destroy() {
		if (instance != null) {
			instance.onDestroy();
			instance = null;
		}
	}

	private static boolean resumed = false;

	public static void onPause() {
		resumed = false;
	}

	public static void onResume() {
		resumed = true;
		if (triggerModulesUpdated) {
			triggerModulesUpdated();
		}
	}

	private static String agencyProviderMetaData;

	public static String getAgencyProviderMetaData(Context context) {
		if (agencyProviderMetaData == null) {
			agencyProviderMetaData = context == null ? null : context.getString(R.string.agency_provider);
		}
		return agencyProviderMetaData;
	}

	private static String scheduleProviderMetaData;

	public static String getScheduleProviderMetaData(Context context) {
		if (scheduleProviderMetaData == null) {
			scheduleProviderMetaData = context == null ? null : context.getString(R.string.schedule_provider);
		}
		return scheduleProviderMetaData;
	}

	private static String statusProviderMetaData;

	public static String getStatusProviderMetaData(Context context) {
		if (statusProviderMetaData == null) {
			statusProviderMetaData = context == null ? null : context.getString(R.string.status_provider);
		}
		return statusProviderMetaData;
	}

	private static String serviceUpdateProviderMetaData;

	public static String getServiceUpdateProviderMetaData(Context context) {
		if (serviceUpdateProviderMetaData == null) {
			serviceUpdateProviderMetaData = context == null ? null : context.getString(R.string.service_update_provider);
		}
		return serviceUpdateProviderMetaData;
	}

	private static String newsProviderMetaData;

	public static String getNewsProviderMetaData(Context context) {
		if (newsProviderMetaData == null) {
			newsProviderMetaData = context == null ? null : context.getString(R.string.news_provider);
		}
		return newsProviderMetaData;
	}

	public static boolean isProvider(Context context, String pkg) {
		if (TextUtils.isEmpty(pkg)) {
			return false;
		}
		ProviderInfo[] providers = PackageManagerUtils.findContentProvidersWithMetaData(context, pkg);
		if (providers == null || providers.length == 0) {
			return false;
		}
		String agencyProviderMetaData = getAgencyProviderMetaData(context);
		String scheduleProviderMetaData = getScheduleProviderMetaData(context);
		String statusProviderMetaData = getStatusProviderMetaData(context);
		String serviceUpdateProviderMetaData = getServiceUpdateProviderMetaData(context);
		String newsProviderMetaData = getNewsProviderMetaData(context);
		for (ProviderInfo provider : providers) {
			if (provider.metaData != null) {
				if (agencyProviderMetaData.equals(provider.metaData.getString(agencyProviderMetaData))) {
					return true;
				}
				if (scheduleProviderMetaData.equals(provider.metaData.getString(scheduleProviderMetaData))) {
					return true;
				}
				if (statusProviderMetaData.equals(provider.metaData.getString(statusProviderMetaData))) {
					return true;
				}
				if (serviceUpdateProviderMetaData.equals(provider.metaData.getString(serviceUpdateProviderMetaData))) {
					return true;
				}
				if (newsProviderMetaData.equals(provider.metaData.getString(newsProviderMetaData))) {
					return true;
				}
			}
		}
		return false;
	}

	public static boolean resetIfNecessary(Context optContext) {
		if (instance != null) {
			if (optContext == null) { // cannot compare w/o context
				destroy();
				triggerModulesUpdated();
				return true;
			} else {
				if (hasChanged(instance, optContext)) {
					destroy();
					triggerModulesUpdated();
					return true;
				}
			}
		}
		return false;
	}

	private synchronized static boolean hasChanged(DataSourceProvider current, Context optContext) {
		if (current == null) {
			return true;
		}
		if (optContext == null) {
			return true;
		}
		String agencyProviderMetaData = getAgencyProviderMetaData(optContext);
		String scheduleProviderMetaData = getScheduleProviderMetaData(optContext);
		String statusProviderMetaData = getStatusProviderMetaData(optContext);
		String serviceUpdateProviderMetaData = getServiceUpdateProviderMetaData(optContext);
		String newsProviderMetaData = getNewsProviderMetaData(optContext);
		int nbAgencyProviders = 0, nbScheduleProviders = 0, nbStatusProviders = 0, nbServiceUpdateProviders = 0, nbNewsProviders = 0;
		PackageManager pm = optContext.getPackageManager();
		for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA)) {
			ProviderInfo[] providers = packageInfo.providers;
			if (providers != null) {
				for (ProviderInfo provider : providers) {
					if (provider != null && provider.metaData != null) {
						if (agencyProviderMetaData.equals(provider.metaData.getString(agencyProviderMetaData))) {
							if (!instance.hasAgency(provider.authority)) {
								return true;
							}
							nbAgencyProviders++;
						}
						if (statusProviderMetaData.equals(provider.metaData.getString(statusProviderMetaData))) {
							if (instance.getStatusProvider(provider.authority) == null) {
								return true;
{'fraction_non_alphanumeric': 0.09132314343060059, 'fraction_numerical': 0.0010035510267098965, 'mean_word_length': 4.888636363636364, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4665370', 'n_tokens_mistral': 4014, 'n_tokens_neox': 3574, 'n_words': 804}