[recipes/wip/krecipes-import: 2/2] Wip: import krecipes .kreml format
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes/wip/krecipes-import: 2/2] Wip: import krecipes .kreml format
- Date: Wed, 29 Mar 2017 12:46:58 +0000 (UTC)
commit 368813610e05792b4eb6f2e2fad3291ab8568c9f
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Feb 16 07:57:34 2017 -0500
Wip: import krecipes .kreml format
src/gr-recipe-importer.c | 351 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 351 insertions(+), 0 deletions(-)
---
diff --git a/src/gr-recipe-importer.c b/src/gr-recipe-importer.c
index b41ffb6..20472ea 100644
--- a/src/gr-recipe-importer.c
+++ b/src/gr-recipe-importer.c
@@ -805,6 +805,349 @@ completed_cb (AutoarExtractor *extractor,
}
#endif
+static gboolean
+in_element (GMarkupParseContext *context,
+ ...)
+{
+ va_list args;
+ gboolean result;
+ char *next;
+ const GSList *stack;
+
+ va_start (args, context);
+
+ result = TRUE;
+
+ stack = g_markup_parse_context_get_element_stack (context);
+
+ while ((next = va_arg (args, char*)) != NULL) {
+ const char *elt;
+
+ if (stack == NULL) {
+ result = FALSE;
+ break;
+ }
+
+ elt = stack->data;
+ stack = stack->next;
+
+ if (strcmp (next, elt) != 0) {
+ result = FALSE;
+ break;
+ }
+ }
+
+ va_end (args);
+
+ return result;
+}
+
+static const char *
+find_attribute (const char *name,
+ const char **names,
+ const char **values)
+{
+ int i;
+
+ for (i = 0; names[i]; i++) {
+ if (strcmp (name, names[i]) == 0)
+ return values[i];
+ }
+
+ return NULL;
+}
+
+typedef struct {
+ gboolean collecting_text;
+ GString *text;
+
+ char *author;
+ char *name;
+ GList *categories;
+ int yield;
+ char *prep_time;
+ char *instructions;
+
+ char *ing_group;
+ char *ing_name;
+ double ing_amount;
+ char *ing_unit;
+ GString *ingredients;
+
+ GList *objects;
+} ParserData;
+
+static void
+kreml_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParserData *pd = user_data;
+
+ if (in_element (context, "title", "krecipes-description", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "author", "krecipes-description", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "cat", "category", "krecipes-description", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "amount", "yield", "krecipes-description", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "preparation-time", "krecipes-description", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "krecipes-instructions", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "krecipes-ingredients", "krecipes-recipe", NULL)) {
+ g_string_set_size (pd->ingredients, 0);
+ }
+ else if (in_element (context, "ingredient-group", "krecipes-ingredients", "krecipes-recipe", NULL)) {
+ pd->ing_group = g_strdup (find_attribute ("name", attribute_names, attribute_values));
+ }
+ else if (in_element (context, "name", "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "amount", "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+ else if (in_element (context, "unit", "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ g_string_set_size (pd->text, 0);
+ pd->collecting_text = TRUE;
+ }
+}
+
+static void
+kreml_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParserData *pd = user_data;
+
+ if (in_element (context, "title", "krecipes-description", NULL)) {
+ pd->collecting_text = FALSE;
+ pd->name = g_strdup (pd->text->str);
+ }
+ else if (in_element (context, "author", "krecipes-description", "krecipes-recipe", NULL)) {
+ pd->collecting_text = FALSE;
+ pd->author = g_strdup (pd->text->str);
+ }
+ else if (in_element (context, "cat", "category", "krecipes-description", "krecipes-recipe", NULL)) {
+ char *cat;
+
+ pd->collecting_text = FALSE;
+ cat = g_strdup (pd->text->str);
+ pd->categories = g_list_prepend (pd->categories, cat);
+ }
+ else if (in_element (context, "amount", "yield", "krecipes-description", "krecipes-recipe", NULL)) {
+ g_autofree char *cat = NULL;
+
+ pd->collecting_text = FALSE;
+ cat = g_strdup (pd->text->str);
+ pd->yield = atoi (cat);
+ }
+ else if (in_element (context, "preparation-time", "krecipes-description", "krecipes-recipe", NULL)) {
+ pd->collecting_text = FALSE;
+ pd->prep_time = g_strdup (pd->text->str);
+ }
+ else if (in_element (context, "krecipes-instructions", "krecipes-recipe", NULL)) {
+ pd->collecting_text = FALSE;
+ pd->instructions = g_strdup (pd->text->str);
+ }
+ else if (in_element (context, "name", "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ pd->collecting_text = FALSE;
+ pd->ing_name = g_strdup (pd->text->str);
+ }
+ else if (in_element (context, "amount", "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ g_autofree char *amount = NULL;
+
+ pd->collecting_text = FALSE;
+ amount = g_strdup (pd->text->str);
+ pd->ing_amount = atof (amount);
+ }
+ else if (in_element (context, "unit", "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ pd->collecting_text = FALSE;
+ pd->ing_unit = g_strdup (pd->text->str);
+ }
+ else if (in_element (context, "ingredient", "ingredient-group", "krecipes-ingredients",
"krecipes-recipe", NULL)) {
+ if (pd->ingredients->len > 0)
+ g_string_append (pd->ingredients, "\n");
+ g_string_append_printf (pd->ingredients, "%g\t%s\t\%s\t%s",
+ pd->ing_amount, pd->ing_unit, pd->ing_name, pd->ing_group ?
pd->ing_group : "");
+ g_clear_pointer (&pd->ing_unit, g_free);
+ g_clear_pointer (&pd->ing_name, g_free);
+ pd->ing_amount = 0;
+ }
+ else if (in_element (context, "ingredient-group", "krecipes-ingredients", "krecipes-recipe", NULL)) {
+ g_clear_pointer (&pd->ing_group, g_free);
+ }
+
+ if (strcmp (element_name, "krecipes-recipe") == 0) {
+ GrRecipe *recipe;
+ GrChef *chef;
+ g_auto(GStrv) strv = NULL;
+ g_autofree char *chef_id = NULL;
+ g_autofree char *id = NULL;
+
+ strv = g_strsplit (pd->author, " ", -1);
+ if (strv[1])
+ chef_id = generate_id (strv[0], "_", strv[1], NULL);
+ else
+ chef_id = generate_id (strv[0], NULL);
+
+ /* FIXME: find chef by name */
+ chef = gr_chef_new ();
+ g_object_set (chef,
+ "id", chef_id,
+ "fullname", pd->author,
+ NULL);
+
+ id = generate_id ("R_", pd->name, "_by_", chef_id, NULL);
+
+ recipe = gr_recipe_new ();
+ g_object_set (recipe,
+ "id", id,
+ "author", chef_id,
+ "name", pd->name,
+ "serves", pd->yield,
+ "prep-time", pd->prep_time,
+ "instructions", pd->instructions,
+ "ingredients", pd->ingredients->str,
+ NULL);
+
+ if (pd->categories) {
+ /* FIXME find best match */
+ g_object_set (recipe,
+ "category", pd->categories->data,
+ NULL);
+ }
+
+ pd->objects = g_list_prepend (pd->objects, chef);
+ pd->objects = g_list_prepend (pd->objects, recipe);
+
+ g_clear_pointer (&pd->author, g_free);
+ g_clear_pointer (&pd->name, g_free);
+ g_list_free_full (pd->categories, g_free);
+ pd->categories = NULL;
+ pd->yield = 0;
+ g_clear_pointer (&pd->prep_time, g_free);
+ g_clear_pointer (&pd->instructions, g_free);
+ g_string_set_size (pd->ingredients, 0);
+ }
+}
+
+static void kreml_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ ParserData *pd = user_data;
+
+ if (pd->collecting_text)
+ g_string_append_len (pd->text, text, text_len);
+}
+
+static const GMarkupParser parser = {
+ kreml_start_element,
+ kreml_end_element,
+ kreml_text,
+ NULL,
+ NULL
+};
+
+static void
+import_from_krecipes (GrRecipeImporter *importer,
+ GFile *file)
+{
+ g_autoptr(GMarkupParseContext) context = NULL;
+ g_autofree char *buffer;
+ gsize length;
+ g_autoptr(GError) error = NULL;
+ g_autofree char *path = NULL;
+ ParserData data;
+ GList *l;
+ GrRecipeStore *store;
+
+ path = g_file_get_path (file);
+
+ data.collecting_text = FALSE;
+ data.text = g_string_new ("");
+ data.name = NULL;
+ data.author= NULL;
+ data.categories = NULL;
+ data.objects = NULL;
+ data.yield = 0;
+ data.prep_time = NULL;
+ data.instructions = NULL;
+ data.ing_group = NULL;
+ data.ing_name = NULL;
+ data.ing_unit = NULL;
+ data.ing_amount = 0;
+ data.ingredients = g_string_new ("");
+
+ store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+
+ if (!g_file_load_contents (file, NULL, &buffer, &length, NULL, &error)) {
+ g_message ("Failed to load %s: %s", path, error->message);
+ return;
+ }
+
+ context = g_markup_parse_context_new (&parser, 0, &data, NULL);
+ if (!g_markup_parse_context_parse (context, buffer, length, &error)) {
+ g_message ("Failed to parse %s: %s", path, error->message);
+ }
+
+ for (l = data.objects; l; l = l->next) {
+ GObject *obj = l->data;
+
+ if (GR_IS_CHEF (obj)) {
+ GrChef *chef = GR_CHEF (obj);
+
+ g_print ("chef: id=%s, fullname=%s\n",
+ gr_chef_get_id (chef),
+ gr_chef_get_fullname (chef));
+
+ if (!gr_recipe_store_add_chef (store, chef, &error)) {
+ g_message ("Failed to add chef: %s", error->message);
+ }
+ }
+ else if (GR_IS_RECIPE (obj)) {
+ GrRecipe *recipe = GR_RECIPE (obj);
+
+ g_print ("recipe:\n\tid=%s\n\tname=%s\n\tserves=%d\n\tcategory: %s\n\tprep-time:
%s\n\tinstructions: %s\n",
+ gr_recipe_get_id (recipe),
+ gr_recipe_get_name (recipe),
+ gr_recipe_get_serves (recipe),
+ gr_recipe_get_category (recipe),
+ gr_recipe_get_prep_time (recipe),
+ gr_recipe_get_instructions (recipe));
+
+ if (!gr_recipe_store_add_recipe (store, recipe, &error)) {
+ g_message ("Failed to add recipe: %s", error->message);
+ }
+ }
+ else {
+ g_print ("unknown object: %s\n", g_type_name_from_instance ((GTypeInstance*)obj));
+ }
+ }
+}
+
void
gr_recipe_importer_import_from (GrRecipeImporter *importer,
GFile *file)
@@ -816,6 +1159,14 @@ gr_recipe_importer_import_from (GrRecipeImporter *importer,
_("This build does not support importing"));
error_cb (NULL, error, importer);
#else
+ g_autofree char *basename = NULL;
+
+ basename = g_file_get_basename (file);
+ if (g_str_has_suffix (basename , ".kreml")) {
+ import_from_krecipes (importer, file);
+ return;
+ }
+
importer->dir = g_mkdtemp (g_build_filename (g_get_tmp_dir (), "recipeXXXXXX", NULL));
importer->output = g_file_new_for_path (importer->dir);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]