class AppProvider extends FDroidProvider {

    @Override
    public Uri insert(@NonNull Uri uri, ContentValues values) {
        long packageId = PackageProvider.Helper.ensureExists(getContext(), values.getAsString(Cols.Package.PACKAGE_NAME));
        values.remove(Cols.Package.PACKAGE_NAME);
        values.put(Cols.PACKAGE_ID, packageId);

        if (!values.containsKey(Cols.DESCRIPTION) || values.getAsString(Cols.DESCRIPTION) == null) {
            // the current structure assumes that description is always present and non-null
            values.put(Cols.DESCRIPTION, "");
        }

        // Trim these to avoid unwanted newlines in the UI
        values.put(Cols.SUMMARY, values.getAsString(Cols.SUMMARY).trim());
        values.put(Cols.NAME, values.getAsString(Cols.NAME).trim());

        String[] categories = null;
        boolean saveCategories = false;
        if (values.containsKey(Cols.ForWriting.Categories.CATEGORIES)) {
            // Hold onto these categories, so that after we have an ID to reference the newly inserted
            // app metadata we can then specify its categories.
            saveCategories = true;
            categories = Utils.parseCommaSeparatedString(values.getAsString(Cols.ForWriting.Categories.CATEGORIES));
            values.remove(Cols.ForWriting.Categories.CATEGORIES);
        }

        long appMetadataId = db().insertOrThrow(getTableName(), null, values);
        if (!isApplyingBatch()) {
            getContext().getContentResolver().notifyChange(uri, null);
        }

        if (saveCategories) {
            ensureCategories(categories, appMetadataId);
        }

        return getSpecificAppUri(values.getAsString(PackageTable.Cols.PACKAGE_NAME), values.getAsLong(Cols.REPO_ID));
    }

}