/* rule.c generated by valac 0.40.8, the Vala compiler
 * generated from rule.vala, do not modify */

/*
 * Copyright (C) 2011-2018 Daiki Ueno <ueno@gnu.org>
 * Copyright (C) 2011-2018 Red Hat, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <gee.h>
#include <json-glib/json-glib.h>
#include <glib/gstdio.h>


#define SKK_TYPE_MAP_FILE (skk_map_file_get_type ())
#define SKK_MAP_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_MAP_FILE, SkkMapFile))
#define SKK_MAP_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_MAP_FILE, SkkMapFileClass))
#define SKK_IS_MAP_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_MAP_FILE))
#define SKK_IS_MAP_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_MAP_FILE))
#define SKK_MAP_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_MAP_FILE, SkkMapFileClass))

typedef struct _SkkMapFile SkkMapFile;
typedef struct _SkkMapFileClass SkkMapFileClass;
typedef struct _SkkMapFilePrivate SkkMapFilePrivate;

#define SKK_TYPE_KEYMAP_MAP_FILE (skk_keymap_map_file_get_type ())
#define SKK_KEYMAP_MAP_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_KEYMAP_MAP_FILE, SkkKeymapMapFile))
#define SKK_KEYMAP_MAP_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_KEYMAP_MAP_FILE, SkkKeymapMapFileClass))
#define SKK_IS_KEYMAP_MAP_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_KEYMAP_MAP_FILE))
#define SKK_IS_KEYMAP_MAP_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_KEYMAP_MAP_FILE))
#define SKK_KEYMAP_MAP_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_KEYMAP_MAP_FILE, SkkKeymapMapFileClass))

typedef struct _SkkKeymapMapFile SkkKeymapMapFile;
typedef struct _SkkKeymapMapFileClass SkkKeymapMapFileClass;
typedef struct _SkkKeymapMapFilePrivate SkkKeymapMapFilePrivate;

#define SKK_TYPE_KEYMAP (skk_keymap_get_type ())
#define SKK_KEYMAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_KEYMAP, SkkKeymap))
#define SKK_KEYMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_KEYMAP, SkkKeymapClass))
#define SKK_IS_KEYMAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_KEYMAP))
#define SKK_IS_KEYMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_KEYMAP))
#define SKK_KEYMAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_KEYMAP, SkkKeymapClass))

typedef struct _SkkKeymap SkkKeymap;
typedef struct _SkkKeymapClass SkkKeymapClass;
enum  {
	SKK_KEYMAP_MAP_FILE_0_PROPERTY,
	SKK_KEYMAP_MAP_FILE_NUM_PROPERTIES
};
static GParamSpec* skk_keymap_map_file_properties[SKK_KEYMAP_MAP_FILE_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#define SKK_TYPE_RULE_METADATA (skk_rule_metadata_get_type ())
typedef struct _SkkRuleMetadata SkkRuleMetadata;
#define __vala_JsonNode_free0(var) ((var == NULL) ? NULL : (var = (_vala_JsonNode_free (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))

#define SKK_TYPE_ROM_KANA_MAP_FILE (skk_rom_kana_map_file_get_type ())
#define SKK_ROM_KANA_MAP_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_ROM_KANA_MAP_FILE, SkkRomKanaMapFile))
#define SKK_ROM_KANA_MAP_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_ROM_KANA_MAP_FILE, SkkRomKanaMapFileClass))
#define SKK_IS_ROM_KANA_MAP_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_ROM_KANA_MAP_FILE))
#define SKK_IS_ROM_KANA_MAP_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_ROM_KANA_MAP_FILE))
#define SKK_ROM_KANA_MAP_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_ROM_KANA_MAP_FILE, SkkRomKanaMapFileClass))

typedef struct _SkkRomKanaMapFile SkkRomKanaMapFile;
typedef struct _SkkRomKanaMapFileClass SkkRomKanaMapFileClass;
typedef struct _SkkRomKanaMapFilePrivate SkkRomKanaMapFilePrivate;

#define SKK_TYPE_ROM_KANA_NODE (skk_rom_kana_node_get_type ())
#define SKK_ROM_KANA_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_ROM_KANA_NODE, SkkRomKanaNode))
#define SKK_ROM_KANA_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_ROM_KANA_NODE, SkkRomKanaNodeClass))
#define SKK_IS_ROM_KANA_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_ROM_KANA_NODE))
#define SKK_IS_ROM_KANA_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_ROM_KANA_NODE))
#define SKK_ROM_KANA_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_ROM_KANA_NODE, SkkRomKanaNodeClass))

typedef struct _SkkRomKanaNode SkkRomKanaNode;
typedef struct _SkkRomKanaNodeClass SkkRomKanaNodeClass;
enum  {
	SKK_ROM_KANA_MAP_FILE_0_PROPERTY,
	SKK_ROM_KANA_MAP_FILE_NUM_PROPERTIES
};
static GParamSpec* skk_rom_kana_map_file_properties[SKK_ROM_KANA_MAP_FILE_NUM_PROPERTIES];

#define SKK_TYPE_ROM_KANA_ENTRY (skk_rom_kana_entry_get_type ())
typedef struct _SkkRomKanaEntry SkkRomKanaEntry;
#define _json_array_unref0(var) ((var == NULL) ? NULL : (var = (json_array_unref (var), NULL)))

#define SKK_TYPE_RULE (skk_rule_get_type ())
#define SKK_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_RULE, SkkRule))
#define SKK_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_RULE, SkkRuleClass))
#define SKK_IS_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_RULE))
#define SKK_IS_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_RULE))
#define SKK_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_RULE, SkkRuleClass))

typedef struct _SkkRule SkkRule;
typedef struct _SkkRuleClass SkkRuleClass;
typedef struct _SkkRulePrivate SkkRulePrivate;

#define SKK_TYPE_KEY_EVENT_FILTER (skk_key_event_filter_get_type ())
#define SKK_KEY_EVENT_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_KEY_EVENT_FILTER, SkkKeyEventFilter))
#define SKK_KEY_EVENT_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_KEY_EVENT_FILTER, SkkKeyEventFilterClass))
#define SKK_IS_KEY_EVENT_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_KEY_EVENT_FILTER))
#define SKK_IS_KEY_EVENT_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_KEY_EVENT_FILTER))
#define SKK_KEY_EVENT_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_KEY_EVENT_FILTER, SkkKeyEventFilterClass))

typedef struct _SkkKeyEventFilter SkkKeyEventFilter;
typedef struct _SkkKeyEventFilterClass SkkKeyEventFilterClass;
enum  {
	SKK_RULE_0_PROPERTY,
	SKK_RULE_METADATA_PROPERTY,
	SKK_RULE_NUM_PROPERTIES
};
static GParamSpec* skk_rule_properties[SKK_RULE_NUM_PROPERTIES];

#define SKK_TYPE_KANA_MODE (skk_kana_mode_get_type ())

#define SKK_TYPE_INPUT_MODE (skk_input_mode_get_type ())

#define SKK_RULE_TYPE_KEYMAP_NAME_ENTRY (skk_rule_keymap_name_entry_get_type ())
typedef struct _SkkRuleKeymapNameEntry SkkRuleKeymapNameEntry;
#define _json_object_unref0(var) ((var == NULL) ? NULL : (var = (json_object_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
#define _skk_rule_metadata_free0(var) ((var == NULL) ? NULL : (var = (skk_rule_metadata_free (var), NULL)))
#define _g_dir_close0(var) ((var == NULL) ? NULL : (var = (g_dir_close (var), NULL)))

#define SKK_TYPE_SIMPLE_KEY_EVENT_FILTER (skk_simple_key_event_filter_get_type ())
#define SKK_SIMPLE_KEY_EVENT_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_SIMPLE_KEY_EVENT_FILTER, SkkSimpleKeyEventFilter))
#define SKK_SIMPLE_KEY_EVENT_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_SIMPLE_KEY_EVENT_FILTER, SkkSimpleKeyEventFilterClass))
#define SKK_IS_SIMPLE_KEY_EVENT_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_SIMPLE_KEY_EVENT_FILTER))
#define SKK_IS_SIMPLE_KEY_EVENT_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_SIMPLE_KEY_EVENT_FILTER))
#define SKK_SIMPLE_KEY_EVENT_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_SIMPLE_KEY_EVENT_FILTER, SkkSimpleKeyEventFilterClass))

typedef struct _SkkSimpleKeyEventFilter SkkSimpleKeyEventFilter;
typedef struct _SkkSimpleKeyEventFilterClass SkkSimpleKeyEventFilterClass;

#define SKK_TYPE_NICOLA_KEY_EVENT_FILTER (skk_nicola_key_event_filter_get_type ())
#define SKK_NICOLA_KEY_EVENT_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_NICOLA_KEY_EVENT_FILTER, SkkNicolaKeyEventFilter))
#define SKK_NICOLA_KEY_EVENT_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_NICOLA_KEY_EVENT_FILTER, SkkNicolaKeyEventFilterClass))
#define SKK_IS_NICOLA_KEY_EVENT_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_NICOLA_KEY_EVENT_FILTER))
#define SKK_IS_NICOLA_KEY_EVENT_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_NICOLA_KEY_EVENT_FILTER))
#define SKK_NICOLA_KEY_EVENT_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_NICOLA_KEY_EVENT_FILTER, SkkNicolaKeyEventFilterClass))

typedef struct _SkkNicolaKeyEventFilter SkkNicolaKeyEventFilter;
typedef struct _SkkNicolaKeyEventFilterClass SkkNicolaKeyEventFilterClass;

struct _SkkMapFile {
	GObject parent_instance;
	SkkMapFilePrivate * priv;
};

struct _SkkMapFileClass {
	GObjectClass parent_class;
};

struct _SkkKeymapMapFile {
	SkkMapFile parent_instance;
	SkkKeymapMapFilePrivate * priv;
	SkkKeymap* keymap;
};

struct _SkkKeymapMapFileClass {
	SkkMapFileClass parent_class;
};

struct _SkkRuleMetadata {
	gchar* base_dir;
	gchar* name;
	gchar* label;
	gchar* description;
	gchar* filter;
};

typedef enum  {
	SKK_RULE_PARSE_ERROR_FAILED
} SkkRuleParseError;
#define SKK_RULE_PARSE_ERROR skk_rule_parse_error_quark ()
struct _SkkRomKanaMapFile {
	SkkMapFile parent_instance;
	SkkRomKanaMapFilePrivate * priv;
	SkkRomKanaNode* root_node;
};

struct _SkkRomKanaMapFileClass {
	SkkMapFileClass parent_class;
};

struct _SkkRomKanaEntry {
	gchar* rom;
	gchar* carryover;
	gchar* hiragana;
	gchar* katakana;
	gchar* hankaku_katakana;
};

struct _SkkRule {
	GObject parent_instance;
	SkkRulePrivate * priv;
	SkkKeymapMapFile** keymaps;
	gint keymaps_length1;
	gint _keymaps_size_;
	SkkRomKanaMapFile* rom_kana;
};

struct _SkkRuleClass {
	GObjectClass parent_class;
};

struct _SkkRulePrivate {
	SkkRuleMetadata _metadata;
	SkkKeyEventFilter* filter;
};

typedef enum  {
	SKK_KANA_MODE_HIRAGANA,
	SKK_KANA_MODE_KATAKANA,
	SKK_KANA_MODE_HANKAKU_KATAKANA
} SkkKanaMode;

typedef enum  {
	SKK_INPUT_MODE_HIRAGANA = SKK_KANA_MODE_HIRAGANA,
	SKK_INPUT_MODE_KATAKANA = SKK_KANA_MODE_KATAKANA,
	SKK_INPUT_MODE_HANKAKU_KATAKANA = SKK_KANA_MODE_HANKAKU_KATAKANA,
	SKK_INPUT_MODE_LATIN,
	SKK_INPUT_MODE_WIDE_LATIN,
	SKK_INPUT_MODE_LAST,
	SKK_INPUT_MODE_DEFAULT = SKK_INPUT_MODE_HIRAGANA
} SkkInputMode;

struct _SkkRuleKeymapNameEntry {
	SkkInputMode key;
	gchar* value;
};


static gpointer skk_keymap_map_file_parent_class = NULL;
static gpointer skk_rom_kana_map_file_parent_class = NULL;
static gpointer skk_rule_parent_class = NULL;
static gchar** skk_rule_rules_path;
static gint skk_rule_rules_path_length1;
static gchar** skk_rule_rules_path = NULL;
static gint skk_rule_rules_path_length1 = 0;
static gint _skk_rule_rules_path_size_ = 0;
static GeeMap* skk_rule_filter_types;
static GeeMap* skk_rule_filter_types = NULL;
static GeeMap* skk_rule_rule_cache;
static GeeMap* skk_rule_rule_cache = NULL;

GType skk_map_file_get_type (void) G_GNUC_CONST;
GType skk_keymap_map_file_get_type (void) G_GNUC_CONST;
GType skk_keymap_get_type (void) G_GNUC_CONST;
GType skk_rule_metadata_get_type (void) G_GNUC_CONST;
SkkRuleMetadata* skk_rule_metadata_dup (const SkkRuleMetadata* self);
void skk_rule_metadata_free (SkkRuleMetadata* self);
void skk_rule_metadata_copy (const SkkRuleMetadata* self,
                             SkkRuleMetadata* dest);
void skk_rule_metadata_destroy (SkkRuleMetadata* self);
GQuark skk_rule_parse_error_quark (void);
SkkKeymapMapFile* skk_keymap_map_file_new (SkkRuleMetadata* metadata,
                                           const gchar* mode,
                                           GError** error);
SkkKeymapMapFile* skk_keymap_map_file_construct (GType object_type,
                                                 SkkRuleMetadata* metadata,
                                                 const gchar* mode,
                                                 GError** error);
SkkMapFile* skk_map_file_construct (GType object_type,
                                    SkkRuleMetadata* metadata,
                                    const gchar* type,
                                    const gchar* name,
                                    GError** error);
gboolean skk_map_file_has_map (SkkMapFile* self,
                               const gchar* name);
GeeMap* skk_map_file_get (SkkMapFile* self,
                          const gchar* name);
SkkKeymap* skk_keymap_new (void);
SkkKeymap* skk_keymap_construct (GType object_type);
void skk_keymap_set (SkkKeymap* self,
                     const gchar* key,
                     const gchar* command);
static void _vala_JsonNode_free (JsonNode* self);
static void skk_keymap_map_file_finalize (GObject * obj);
GType skk_rom_kana_map_file_get_type (void) G_GNUC_CONST;
GType skk_rom_kana_node_get_type (void) G_GNUC_CONST;
static SkkRomKanaNode* skk_rom_kana_map_file_parse_rule (SkkRomKanaMapFile* self,
                                                  GeeMap* map,
                                                  GError** error);
GType skk_rom_kana_entry_get_type (void) G_GNUC_CONST;
SkkRomKanaEntry* skk_rom_kana_entry_dup (const SkkRomKanaEntry* self);
void skk_rom_kana_entry_free (SkkRomKanaEntry* self);
void skk_rom_kana_entry_copy (const SkkRomKanaEntry* self,
                              SkkRomKanaEntry* dest);
void skk_rom_kana_entry_destroy (SkkRomKanaEntry* self);
SkkRomKanaNode* skk_rom_kana_node_new (SkkRomKanaEntry* entry);
SkkRomKanaNode* skk_rom_kana_node_construct (GType object_type,
                                             SkkRomKanaEntry* entry);
gchar* skk_util_get_katakana (const gchar* kana);
gchar* skk_util_get_hankaku_katakana (const gchar* kana);
void skk_rom_kana_node_insert (SkkRomKanaNode* self,
                               const gchar* key,
                               SkkRomKanaEntry* entry);
SkkRomKanaMapFile* skk_rom_kana_map_file_new (SkkRuleMetadata* metadata,
                                              GError** error);
SkkRomKanaMapFile* skk_rom_kana_map_file_construct (GType object_type,
                                                    SkkRuleMetadata* metadata,
                                                    GError** error);
static void skk_rom_kana_map_file_finalize (GObject * obj);
gchar* skk_rule_metadata_locate_map_file (SkkRuleMetadata *self,
                                          const gchar* type,
                                          const gchar* name);
GType skk_rule_get_type (void) G_GNUC_CONST;
GType skk_key_event_filter_get_type (void) G_GNUC_CONST;
#define SKK_RULE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SKK_TYPE_RULE, SkkRulePrivate))
void skk_key_event_filter_reset (SkkKeyEventFilter* self);
GType skk_kana_mode_get_type (void) G_GNUC_CONST;
GType skk_input_mode_get_type (void) G_GNUC_CONST;
static GType* _g_type_dup (GType* self);
static GType skk_rule_keymap_name_entry_get_type (void) G_GNUC_CONST G_GNUC_UNUSED;
static SkkRuleKeymapNameEntry* skk_rule_keymap_name_entry_dup (const SkkRuleKeymapNameEntry* self);
static void skk_rule_keymap_name_entry_free (SkkRuleKeymapNameEntry* self);
static void skk_rule_keymap_name_entry_copy (const SkkRuleKeymapNameEntry* self,
                                      SkkRuleKeymapNameEntry* dest);
static void skk_rule_keymap_name_entry_destroy (SkkRuleKeymapNameEntry* self);
static void skk_rule_load_metadata (const gchar* filename,
                             SkkRuleMetadata* result,
                             GError** error);
static JsonNode* _vala_JsonNode_copy (JsonNode* self);
SkkKeyEventFilter* skk_rule_get_filter (SkkRule* self);
void skk_rule_get_metadata (SkkRule* self,
                            SkkRuleMetadata * result);
SkkRule* skk_rule_new (const gchar* name,
                       GError** error);
SkkRule* skk_rule_construct (GType object_type,
                             const gchar* name,
                             GError** error);
SkkRuleMetadata* skk_rule_find_rule (const gchar* name);
static void skk_rule_set_metadata (SkkRule* self,
                            SkkRuleMetadata * value);
SkkRuleMetadata* skk_rule_list (int* result_length1);
static void _vala_SkkRuleMetadata_array_free (SkkRuleMetadata * array,
                                       gint array_length);
static void _vala_array_add1 (SkkRuleMetadata* * array,
                       int* length,
                       int* size,
                       const SkkRuleMetadata* value);
static gboolean _skk_rule_metadata_equal (const SkkRuleMetadata * s1,
                                   const SkkRuleMetadata * s2);
gchar** skk_util_build_data_path (const gchar* subdir,
                                  int* result_length1);
GType skk_simple_key_event_filter_get_type (void) G_GNUC_CONST;
GType skk_nicola_key_event_filter_get_type (void) G_GNUC_CONST;
static void skk_rule_finalize (GObject * obj);
static void _vala_skk_rule_get_property (GObject * object,
                                  guint property_id,
                                  GValue * value,
                                  GParamSpec * pspec);
static void _vala_skk_rule_set_property (GObject * object,
                                  guint property_id,
                                  const GValue * value,
                                  GParamSpec * pspec);
static void _vala_array_destroy (gpointer array,
                          gint array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gint array_length,
                       GDestroyNotify destroy_func);

static const SkkRuleKeymapNameEntry SKK_RULE_keymap_names[5] = {{SKK_INPUT_MODE_HIRAGANA, "hiragana"}, {SKK_INPUT_MODE_KATAKANA, "katakana"}, {SKK_INPUT_MODE_HANKAKU_KATAKANA, "hankaku-katakana"}, {SKK_INPUT_MODE_LATIN, "latin"}, {SKK_INPUT_MODE_WIDE_LATIN, "wide-latin"}};

static void
_vala_JsonNode_free (JsonNode* self)
{
	g_boxed_free (json_node_get_type (), self);
}


SkkKeymapMapFile*
skk_keymap_map_file_construct (GType object_type,
                               SkkRuleMetadata* metadata,
                               const gchar* mode,
                               GError** error)
{
	SkkKeymapMapFile * self = NULL;
	SkkRuleMetadata _tmp0_;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (metadata != NULL, NULL);
	g_return_val_if_fail (mode != NULL, NULL);
	_tmp0_ = *metadata;
	self = (SkkKeymapMapFile*) skk_map_file_construct (object_type, &_tmp0_, "keymap", mode, &_inner_error_);
	if (G_UNLIKELY (_inner_error_ != NULL)) {
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	if (skk_map_file_has_map ((SkkMapFile*) self, "keymap")) {
		GeeMap* map = NULL;
		GeeMap* _tmp1_;
		SkkKeymap* _tmp2_;
		_tmp1_ = skk_map_file_get ((SkkMapFile*) self, "keymap");
		map = _tmp1_;
		_tmp2_ = skk_keymap_new ();
		_g_object_unref0 (self->keymap);
		self->keymap = _tmp2_;
		{
			GeeIterator* _key_it = NULL;
			GeeMap* _tmp3_;
			GeeSet* _tmp4_;
			GeeSet* _tmp5_;
			GeeSet* _tmp6_;
			GeeIterator* _tmp7_;
			GeeIterator* _tmp8_;
			_tmp3_ = map;
			_tmp4_ = gee_map_get_keys (_tmp3_);
			_tmp5_ = _tmp4_;
			_tmp6_ = _tmp5_;
			_tmp7_ = gee_iterable_iterator ((GeeIterable*) _tmp6_);
			_tmp8_ = _tmp7_;
			_g_object_unref0 (_tmp6_);
			_key_it = _tmp8_;
			while (TRUE) {
				GeeIterator* _tmp9_;
				gchar* key = NULL;
				GeeIterator* _tmp10_;
				gpointer _tmp11_;
				JsonNode* value = NULL;
				GeeMap* _tmp12_;
				const gchar* _tmp13_;
				gpointer _tmp14_;
				SkkKeymap* _tmp15_;
				const gchar* _tmp16_;
				JsonNode* _tmp17_;
				const gchar* _tmp18_;
				_tmp9_ = _key_it;
				if (!gee_iterator_next (_tmp9_)) {
					break;
				}
				_tmp10_ = _key_it;
				_tmp11_ = gee_iterator_get (_tmp10_);
				key = (gchar*) _tmp11_;
				_tmp12_ = map;
				_tmp13_ = key;
				_tmp14_ = gee_map_get (_tmp12_, _tmp13_);
				value = (JsonNode*) _tmp14_;
				_tmp15_ = self->keymap;
				_tmp16_ = key;
				_tmp17_ = value;
				_tmp18_ = json_node_get_string (_tmp17_);
				skk_keymap_set (_tmp15_, _tmp16_, _tmp18_);
				__vala_JsonNode_free0 (value);
				_g_free0 (key);
			}
			_g_object_unref0 (_key_it);
		}
		_g_object_unref0 (map);
	} else {
		GError* _tmp19_;
		_tmp19_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "no keymap entry");
		_inner_error_ = _tmp19_;
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	return self;
}


SkkKeymapMapFile*
skk_keymap_map_file_new (SkkRuleMetadata* metadata,
                         const gchar* mode,
                         GError** error)
{
	return skk_keymap_map_file_construct (SKK_TYPE_KEYMAP_MAP_FILE, metadata, mode, error);
}


static void
skk_keymap_map_file_class_init (SkkKeymapMapFileClass * klass)
{
	skk_keymap_map_file_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = skk_keymap_map_file_finalize;
}


static void
skk_keymap_map_file_instance_init (SkkKeymapMapFile * self)
{
}


static void
skk_keymap_map_file_finalize (GObject * obj)
{
	SkkKeymapMapFile * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, SKK_TYPE_KEYMAP_MAP_FILE, SkkKeymapMapFile);
	_g_object_unref0 (self->keymap);
	G_OBJECT_CLASS (skk_keymap_map_file_parent_class)->finalize (obj);
}


GType
skk_keymap_map_file_get_type (void)
{
	static volatile gsize skk_keymap_map_file_type_id__volatile = 0;
	if (g_once_init_enter (&skk_keymap_map_file_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (SkkKeymapMapFileClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) skk_keymap_map_file_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SkkKeymapMapFile), 0, (GInstanceInitFunc) skk_keymap_map_file_instance_init, NULL };
		GType skk_keymap_map_file_type_id;
		skk_keymap_map_file_type_id = g_type_register_static (SKK_TYPE_MAP_FILE, "SkkKeymapMapFile", &g_define_type_info, 0);
		g_once_init_leave (&skk_keymap_map_file_type_id__volatile, skk_keymap_map_file_type_id);
	}
	return skk_keymap_map_file_type_id__volatile;
}


static gpointer
_json_array_ref0 (gpointer self)
{
	return self ? json_array_ref (self) : NULL;
}


static SkkRomKanaNode*
skk_rom_kana_map_file_parse_rule (SkkRomKanaMapFile* self,
                                  GeeMap* map,
                                  GError** error)
{
	SkkRomKanaNode* result = NULL;
	SkkRomKanaNode* node = NULL;
	SkkRomKanaNode* _tmp0_;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (map != NULL, NULL);
	_tmp0_ = skk_rom_kana_node_new (NULL);
	node = _tmp0_;
	{
		GeeIterator* _key_it = NULL;
		GeeSet* _tmp1_;
		GeeSet* _tmp2_;
		GeeSet* _tmp3_;
		GeeIterator* _tmp4_;
		GeeIterator* _tmp5_;
		_tmp1_ = gee_map_get_keys (map);
		_tmp2_ = _tmp1_;
		_tmp3_ = _tmp2_;
		_tmp4_ = gee_iterable_iterator ((GeeIterable*) _tmp3_);
		_tmp5_ = _tmp4_;
		_g_object_unref0 (_tmp3_);
		_key_it = _tmp5_;
		while (TRUE) {
			GeeIterator* _tmp6_;
			gchar* key = NULL;
			GeeIterator* _tmp7_;
			gpointer _tmp8_;
			JsonNode* value = NULL;
			const gchar* _tmp9_;
			gpointer _tmp10_;
			JsonNode* _tmp11_;
			_tmp6_ = _key_it;
			if (!gee_iterator_next (_tmp6_)) {
				break;
			}
			_tmp7_ = _key_it;
			_tmp8_ = gee_iterator_get (_tmp7_);
			key = (gchar*) _tmp8_;
			_tmp9_ = key;
			_tmp10_ = gee_map_get (map, _tmp9_);
			value = (JsonNode*) _tmp10_;
			_tmp11_ = value;
			if (json_node_get_node_type (_tmp11_) == JSON_NODE_ARRAY) {
				JsonArray* components = NULL;
				JsonNode* _tmp12_;
				JsonArray* _tmp13_;
				JsonArray* _tmp14_;
				guint length = 0U;
				JsonArray* _tmp15_;
				gboolean _tmp16_ = FALSE;
				guint _tmp17_;
				_tmp12_ = value;
				_tmp13_ = json_node_get_array (_tmp12_);
				_tmp14_ = _json_array_ref0 (_tmp13_);
				components = _tmp14_;
				_tmp15_ = components;
				length = json_array_get_length (_tmp15_);
				_tmp17_ = length;
				if (((guint) 2) <= _tmp17_) {
					guint _tmp18_;
					_tmp18_ = length;
					_tmp16_ = _tmp18_ <= ((guint) 4);
				} else {
					_tmp16_ = FALSE;
				}
				if (_tmp16_) {
					gchar* carryover = NULL;
					JsonArray* _tmp19_;
					const gchar* _tmp20_;
					gchar* _tmp21_;
					gchar* hiragana = NULL;
					JsonArray* _tmp22_;
					const gchar* _tmp23_;
					gchar* _tmp24_;
					gchar* _tmp25_ = NULL;
					guint _tmp26_;
					gchar* katakana = NULL;
					gchar* _tmp32_;
					gchar* _tmp33_ = NULL;
					guint _tmp34_;
					gchar* hankaku_katakana = NULL;
					gchar* _tmp40_;
					SkkRomKanaEntry entry = {0};
					const gchar* _tmp41_;
					gchar* _tmp42_;
					const gchar* _tmp43_;
					gchar* _tmp44_;
					const gchar* _tmp45_;
					gchar* _tmp46_;
					const gchar* _tmp47_;
					gchar* _tmp48_;
					const gchar* _tmp49_;
					gchar* _tmp50_;
					SkkRomKanaEntry _tmp51_ = {0};
					SkkRomKanaNode* _tmp52_;
					const gchar* _tmp53_;
					SkkRomKanaEntry _tmp54_;
					_tmp19_ = components;
					_tmp20_ = json_array_get_string_element (_tmp19_, (guint) 0);
					_tmp21_ = g_strdup (_tmp20_);
					carryover = _tmp21_;
					_tmp22_ = components;
					_tmp23_ = json_array_get_string_element (_tmp22_, (guint) 1);
					_tmp24_ = g_strdup (_tmp23_);
					hiragana = _tmp24_;
					_tmp26_ = length;
					if (_tmp26_ >= ((guint) 3)) {
						JsonArray* _tmp27_;
						const gchar* _tmp28_;
						gchar* _tmp29_;
						_tmp27_ = components;
						_tmp28_ = json_array_get_string_element (_tmp27_, (guint) 2);
						_tmp29_ = g_strdup (_tmp28_);
						_g_free0 (_tmp25_);
						_tmp25_ = _tmp29_;
					} else {
						const gchar* _tmp30_;
						gchar* _tmp31_;
						_tmp30_ = hiragana;
						_tmp31_ = skk_util_get_katakana (_tmp30_);
						_g_free0 (_tmp25_);
						_tmp25_ = _tmp31_;
					}
					_tmp32_ = g_strdup (_tmp25_);
					katakana = _tmp32_;
					_tmp34_ = length;
					if (_tmp34_ == ((guint) 4)) {
						JsonArray* _tmp35_;
						const gchar* _tmp36_;
						gchar* _tmp37_;
						_tmp35_ = components;
						_tmp36_ = json_array_get_string_element (_tmp35_, (guint) 3);
						_tmp37_ = g_strdup (_tmp36_);
						_g_free0 (_tmp33_);
						_tmp33_ = _tmp37_;
					} else {
						const gchar* _tmp38_;
						gchar* _tmp39_;
						_tmp38_ = katakana;
						_tmp39_ = skk_util_get_hankaku_katakana (_tmp38_);
						_g_free0 (_tmp33_);
						_tmp33_ = _tmp39_;
					}
					_tmp40_ = g_strdup (_tmp33_);
					hankaku_katakana = _tmp40_;
					_tmp41_ = key;
					_tmp42_ = g_strdup (_tmp41_);
					_tmp43_ = carryover;
					_tmp44_ = g_strdup (_tmp43_);
					_tmp45_ = hiragana;
					_tmp46_ = g_strdup (_tmp45_);
					_tmp47_ = katakana;
					_tmp48_ = g_strdup (_tmp47_);
					_tmp49_ = hankaku_katakana;
					_tmp50_ = g_strdup (_tmp49_);
					_g_free0 (_tmp51_.rom);
					_tmp51_.rom = _tmp42_;
					_g_free0 (_tmp51_.carryover);
					_tmp51_.carryover = _tmp44_;
					_g_free0 (_tmp51_.hiragana);
					_tmp51_.hiragana = _tmp46_;
					_g_free0 (_tmp51_.katakana);
					_tmp51_.katakana = _tmp48_;
					_g_free0 (_tmp51_.hankaku_katakana);
					_tmp51_.hankaku_katakana = _tmp50_;
					entry = _tmp51_;
					_tmp52_ = node;
					_tmp53_ = key;
					_tmp54_ = entry;
					skk_rom_kana_node_insert (_tmp52_, _tmp53_, &_tmp54_);
					skk_rom_kana_entry_destroy (&entry);
					_g_free0 (hankaku_katakana);
					_g_free0 (_tmp33_);
					_g_free0 (katakana);
					_g_free0 (_tmp25_);
					_g_free0 (hiragana);
					_g_free0 (carryover);
				} else {
					GError* _tmp55_;
					_tmp55_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "\"rom-kana\" must have two to four elements");
					_inner_error_ = _tmp55_;
					if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
						g_propagate_error (error, _inner_error_);
						_json_array_unref0 (components);
						__vala_JsonNode_free0 (value);
						_g_free0 (key);
						_g_object_unref0 (_key_it);
						_g_object_unref0 (node);
						return NULL;
					} else {
						_json_array_unref0 (components);
						__vala_JsonNode_free0 (value);
						_g_free0 (key);
						_g_object_unref0 (_key_it);
						_g_object_unref0 (node);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
						g_clear_error (&_inner_error_);
						return NULL;
					}
				}
				_json_array_unref0 (components);
			} else {
				GError* _tmp56_;
				_tmp56_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "\"rom-kana\" member must be either an array or null");
				_inner_error_ = _tmp56_;
				if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
					g_propagate_error (error, _inner_error_);
					__vala_JsonNode_free0 (value);
					_g_free0 (key);
					_g_object_unref0 (_key_it);
					_g_object_unref0 (node);
					return NULL;
				} else {
					__vala_JsonNode_free0 (value);
					_g_free0 (key);
					_g_object_unref0 (_key_it);
					_g_object_unref0 (node);
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return NULL;
				}
			}
			__vala_JsonNode_free0 (value);
			_g_free0 (key);
		}
		_g_object_unref0 (_key_it);
	}
	result = node;
	return result;
}


SkkRomKanaMapFile*
skk_rom_kana_map_file_construct (GType object_type,
                                 SkkRuleMetadata* metadata,
                                 GError** error)
{
	SkkRomKanaMapFile * self = NULL;
	SkkRuleMetadata _tmp0_;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (metadata != NULL, NULL);
	_tmp0_ = *metadata;
	self = (SkkRomKanaMapFile*) skk_map_file_construct (object_type, &_tmp0_, "rom-kana", "default", &_inner_error_);
	if (G_UNLIKELY (_inner_error_ != NULL)) {
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	if (skk_map_file_has_map ((SkkMapFile*) self, "rom-kana")) {
		SkkRomKanaNode* _tmp1_ = NULL;
		GeeMap* _tmp2_;
		GeeMap* _tmp3_;
		SkkRomKanaNode* _tmp4_;
		SkkRomKanaNode* _tmp5_;
		SkkRomKanaNode* _tmp6_;
		_tmp2_ = skk_map_file_get ((SkkMapFile*) self, "rom-kana");
		_tmp3_ = _tmp2_;
		_tmp4_ = skk_rom_kana_map_file_parse_rule (self, _tmp3_, &_inner_error_);
		_tmp5_ = _tmp4_;
		_g_object_unref0 (_tmp3_);
		_tmp1_ = _tmp5_;
		if (G_UNLIKELY (_inner_error_ != NULL)) {
			if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
				g_propagate_error (error, _inner_error_);
				_g_object_unref0 (self);
				return NULL;
			} else {
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
				g_clear_error (&_inner_error_);
				return NULL;
			}
		}
		_tmp6_ = _tmp1_;
		_tmp1_ = NULL;
		_g_object_unref0 (self->root_node);
		self->root_node = _tmp6_;
		_g_object_unref0 (_tmp1_);
	} else {
		GError* _tmp7_;
		_tmp7_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "no rom-kana entry");
		_inner_error_ = _tmp7_;
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	return self;
}


SkkRomKanaMapFile*
skk_rom_kana_map_file_new (SkkRuleMetadata* metadata,
                           GError** error)
{
	return skk_rom_kana_map_file_construct (SKK_TYPE_ROM_KANA_MAP_FILE, metadata, error);
}


static void
skk_rom_kana_map_file_class_init (SkkRomKanaMapFileClass * klass)
{
	skk_rom_kana_map_file_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = skk_rom_kana_map_file_finalize;
}


static void
skk_rom_kana_map_file_instance_init (SkkRomKanaMapFile * self)
{
}


static void
skk_rom_kana_map_file_finalize (GObject * obj)
{
	SkkRomKanaMapFile * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, SKK_TYPE_ROM_KANA_MAP_FILE, SkkRomKanaMapFile);
	_g_object_unref0 (self->root_node);
	G_OBJECT_CLASS (skk_rom_kana_map_file_parent_class)->finalize (obj);
}


GType
skk_rom_kana_map_file_get_type (void)
{
	static volatile gsize skk_rom_kana_map_file_type_id__volatile = 0;
	if (g_once_init_enter (&skk_rom_kana_map_file_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (SkkRomKanaMapFileClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) skk_rom_kana_map_file_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SkkRomKanaMapFile), 0, (GInstanceInitFunc) skk_rom_kana_map_file_instance_init, NULL };
		GType skk_rom_kana_map_file_type_id;
		skk_rom_kana_map_file_type_id = g_type_register_static (SKK_TYPE_MAP_FILE, "SkkRomKanaMapFile", &g_define_type_info, 0);
		g_once_init_leave (&skk_rom_kana_map_file_type_id__volatile, skk_rom_kana_map_file_type_id);
	}
	return skk_rom_kana_map_file_type_id__volatile;
}


GQuark
skk_rule_parse_error_quark (void)
{
	return g_quark_from_static_string ("skk_rule_parse_error-quark");
}


/**
         * Return the path of the map file.
         *
         * @param type type of the map file
         * @param name name of the map file
         *
         * @return the absolute path of the map file
         */
gchar*
skk_rule_metadata_locate_map_file (SkkRuleMetadata *self,
                                   const gchar* type,
                                   const gchar* name)
{
	gchar* result = NULL;
	gchar* filename = NULL;
	const gchar* _tmp0_;
	gchar* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	const gchar* _tmp5_;
	g_return_val_if_fail (type != NULL, NULL);
	g_return_val_if_fail (name != NULL, NULL);
	_tmp0_ = (*self).base_dir;
	_tmp1_ = g_strconcat (name, ".json", NULL);
	_tmp2_ = _tmp1_;
	_tmp3_ = g_build_filename (_tmp0_, type, _tmp2_, NULL);
	_tmp4_ = _tmp3_;
	_g_free0 (_tmp2_);
	filename = _tmp4_;
	_tmp5_ = filename;
	if (g_file_test (_tmp5_, G_FILE_TEST_EXISTS)) {
		result = filename;
		return result;
	}
	result = NULL;
	_g_free0 (filename);
	return result;
}


void
skk_rule_metadata_copy (const SkkRuleMetadata* self,
                        SkkRuleMetadata* dest)
{
	const gchar* _tmp0_;
	gchar* _tmp1_;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	const gchar* _tmp4_;
	gchar* _tmp5_;
	const gchar* _tmp6_;
	gchar* _tmp7_;
	const gchar* _tmp8_;
	gchar* _tmp9_;
	_tmp0_ = (*self).base_dir;
	_tmp1_ = g_strdup (_tmp0_);
	_g_free0 ((*dest).base_dir);
	(*dest).base_dir = _tmp1_;
	_tmp2_ = (*self).name;
	_tmp3_ = g_strdup (_tmp2_);
	_g_free0 ((*dest).name);
	(*dest).name = _tmp3_;
	_tmp4_ = (*self).label;
	_tmp5_ = g_strdup (_tmp4_);
	_g_free0 ((*dest).label);
	(*dest).label = _tmp5_;
	_tmp6_ = (*self).description;
	_tmp7_ = g_strdup (_tmp6_);
	_g_free0 ((*dest).description);
	(*dest).description = _tmp7_;
	_tmp8_ = (*self).filter;
	_tmp9_ = g_strdup (_tmp8_);
	_g_free0 ((*dest).filter);
	(*dest).filter = _tmp9_;
}


void
skk_rule_metadata_destroy (SkkRuleMetadata* self)
{
	_g_free0 ((*self).base_dir);
	_g_free0 ((*self).name);
	_g_free0 ((*self).label);
	_g_free0 ((*self).description);
	_g_free0 ((*self).filter);
}


SkkRuleMetadata*
skk_rule_metadata_dup (const SkkRuleMetadata* self)
{
	SkkRuleMetadata* dup;
	dup = g_new0 (SkkRuleMetadata, 1);
	skk_rule_metadata_copy (self, dup);
	return dup;
}


void
skk_rule_metadata_free (SkkRuleMetadata* self)
{
	skk_rule_metadata_destroy (self);
	g_free (self);
}


GType
skk_rule_metadata_get_type (void)
{
	static volatile gsize skk_rule_metadata_type_id__volatile = 0;
	if (g_once_init_enter (&skk_rule_metadata_type_id__volatile)) {
		GType skk_rule_metadata_type_id;
		skk_rule_metadata_type_id = g_boxed_type_register_static ("SkkRuleMetadata", (GBoxedCopyFunc) skk_rule_metadata_dup, (GBoxedFreeFunc) skk_rule_metadata_free);
		g_once_init_leave (&skk_rule_metadata_type_id__volatile, skk_rule_metadata_type_id);
	}
	return skk_rule_metadata_type_id__volatile;
}


static GType*
_g_type_dup (GType* self)
{
	GType* dup;
	dup = g_new0 (GType, 1);
	memcpy (dup, self, sizeof (GType));
	return dup;
}


static JsonNode*
_vala_JsonNode_copy (JsonNode* self)
{
	return g_boxed_copy (json_node_get_type (), self);
}


static gpointer
__vala_JsonNode_copy0 (gpointer self)
{
	return self ? _vala_JsonNode_copy (self) : NULL;
}


static gpointer
_json_object_ref0 (gpointer self)
{
	return self ? json_object_ref (self) : NULL;
}


static void
skk_rule_load_metadata (const gchar* filename,
                        SkkRuleMetadata* result,
                        GError** error)
{
	JsonParser* parser = NULL;
	JsonParser* _tmp0_;
	GError * _inner_error_ = NULL;
	g_return_if_fail (filename != NULL);
	_tmp0_ = json_parser_new ();
	parser = _tmp0_;
	{
		gboolean _tmp1_ = FALSE;
		JsonParser* _tmp2_;
		JsonNode* root = NULL;
		JsonParser* _tmp4_;
		JsonNode* _tmp5_;
		JsonNode* _tmp6_;
		JsonNode* _tmp7_;
		JsonObject* object = NULL;
		JsonNode* _tmp9_;
		JsonObject* _tmp10_;
		JsonObject* _tmp11_;
		JsonNode* member = NULL;
		JsonObject* _tmp12_;
		JsonObject* _tmp14_;
		JsonNode* _tmp15_;
		JsonNode* _tmp16_;
		gchar* name = NULL;
		JsonNode* _tmp17_;
		const gchar* _tmp18_;
		gchar* _tmp19_;
		JsonObject* _tmp20_;
		JsonObject* _tmp22_;
		JsonNode* _tmp23_;
		JsonNode* _tmp24_;
		gchar* description = NULL;
		JsonNode* _tmp25_;
		const gchar* _tmp26_;
		gchar* _tmp27_;
		gchar* filter = NULL;
		JsonObject* _tmp28_;
		const gchar* _tmp40_;
		gchar* _tmp41_;
		const gchar* _tmp42_;
		gchar* _tmp43_;
		const gchar* _tmp44_;
		gchar* _tmp45_;
		gchar* _tmp46_;
		SkkRuleMetadata _tmp47_ = {0};
		_tmp2_ = parser;
		_tmp1_ = json_parser_load_from_file (_tmp2_, filename, &_inner_error_);
		if (G_UNLIKELY (_inner_error_ != NULL)) {
			goto __catch24_g_error;
		}
		if (!_tmp1_) {
			GError* _tmp3_;
			_tmp3_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't load %s", filename);
			_inner_error_ = _tmp3_;
			goto __catch24_g_error;
		}
		_tmp4_ = parser;
		_tmp5_ = json_parser_get_root (_tmp4_);
		_tmp6_ = __vala_JsonNode_copy0 (_tmp5_);
		root = _tmp6_;
		_tmp7_ = root;
		if (json_node_get_node_type (_tmp7_) != JSON_NODE_OBJECT) {
			GError* _tmp8_;
			_tmp8_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "metadata must be a JSON object");
			_inner_error_ = _tmp8_;
			__vala_JsonNode_free0 (root);
			goto __catch24_g_error;
		}
		_tmp9_ = root;
		_tmp10_ = json_node_get_object (_tmp9_);
		_tmp11_ = _json_object_ref0 (_tmp10_);
		object = _tmp11_;
		_tmp12_ = object;
		if (!json_object_has_member (_tmp12_, "name")) {
			GError* _tmp13_;
			_tmp13_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "name is not defined in metadata");
			_inner_error_ = _tmp13_;
			__vala_JsonNode_free0 (member);
			_json_object_unref0 (object);
			__vala_JsonNode_free0 (root);
			goto __catch24_g_error;
		}
		_tmp14_ = object;
		_tmp15_ = json_object_get_member (_tmp14_, "name");
		_tmp16_ = __vala_JsonNode_copy0 (_tmp15_);
		__vala_JsonNode_free0 (member);
		member = _tmp16_;
		_tmp17_ = member;
		_tmp18_ = json_node_get_string (_tmp17_);
		_tmp19_ = g_strdup (_tmp18_);
		name = _tmp19_;
		_tmp20_ = object;
		if (!json_object_has_member (_tmp20_, "description")) {
			GError* _tmp21_;
			_tmp21_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "description is not defined in metadata");
			_inner_error_ = _tmp21_;
			_g_free0 (name);
			__vala_JsonNode_free0 (member);
			_json_object_unref0 (object);
			__vala_JsonNode_free0 (root);
			goto __catch24_g_error;
		}
		_tmp22_ = object;
		_tmp23_ = json_object_get_member (_tmp22_, "description");
		_tmp24_ = __vala_JsonNode_copy0 (_tmp23_);
		__vala_JsonNode_free0 (member);
		member = _tmp24_;
		_tmp25_ = member;
		_tmp26_ = json_node_get_string (_tmp25_);
		_tmp27_ = g_strdup (_tmp26_);
		description = _tmp27_;
		_tmp28_ = object;
		if (json_object_has_member (_tmp28_, "filter")) {
			JsonObject* _tmp29_;
			JsonNode* _tmp30_;
			JsonNode* _tmp31_;
			JsonNode* _tmp32_;
			const gchar* _tmp33_;
			gchar* _tmp34_;
			GeeMap* _tmp35_;
			const gchar* _tmp36_;
			_tmp29_ = object;
			_tmp30_ = json_object_get_member (_tmp29_, "filter");
			_tmp31_ = __vala_JsonNode_copy0 (_tmp30_);
			__vala_JsonNode_free0 (member);
			member = _tmp31_;
			_tmp32_ = member;
			_tmp33_ = json_node_get_string (_tmp32_);
			_tmp34_ = g_strdup (_tmp33_);
			_g_free0 (filter);
			filter = _tmp34_;
			_tmp35_ = skk_rule_filter_types;
			_tmp36_ = filter;
			if (!gee_map_has_key (_tmp35_, _tmp36_)) {
				const gchar* _tmp37_;
				GError* _tmp38_;
				_tmp37_ = filter;
				_tmp38_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "unknown filter type %s", _tmp37_);
				_inner_error_ = _tmp38_;
				_g_free0 (filter);
				_g_free0 (description);
				_g_free0 (name);
				__vala_JsonNode_free0 (member);
				_json_object_unref0 (object);
				__vala_JsonNode_free0 (root);
				goto __catch24_g_error;
			}
		} else {
			gchar* _tmp39_;
			_tmp39_ = g_strdup ("simple");
			_g_free0 (filter);
			filter = _tmp39_;
		}
		_tmp40_ = name;
		_tmp41_ = g_strdup (_tmp40_);
		_tmp42_ = description;
		_tmp43_ = g_strdup (_tmp42_);
		_tmp44_ = filter;
		_tmp45_ = g_strdup (_tmp44_);
		_tmp46_ = g_path_get_dirname (filename);
		memset (&_tmp47_, 0, sizeof (SkkRuleMetadata));
		_g_free0 (_tmp47_.label);
		_tmp47_.label = _tmp41_;
		_g_free0 (_tmp47_.description);
		_tmp47_.description = _tmp43_;
		_g_free0 (_tmp47_.filter);
		_tmp47_.filter = _tmp45_;
		_g_free0 (_tmp47_.base_dir);
		_tmp47_.base_dir = _tmp46_;
		*result = _tmp47_;
		_g_free0 (filter);
		_g_free0 (description);
		_g_free0 (name);
		__vala_JsonNode_free0 (member);
		_json_object_unref0 (object);
		__vala_JsonNode_free0 (root);
		_g_object_unref0 (parser);
		return;
	}
	goto __finally24;
	__catch24_g_error:
	{
		GError* e = NULL;
		GError* _tmp48_;
		const gchar* _tmp49_;
		GError* _tmp50_;
		e = _inner_error_;
		_inner_error_ = NULL;
		_tmp48_ = e;
		_tmp49_ = _tmp48_->message;
		_tmp50_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't load rule: %s", _tmp49_);
		_inner_error_ = _tmp50_;
		_g_error_free0 (e);
		goto __finally24;
	}
	__finally24:
	if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
		g_propagate_error (error, _inner_error_);
		_g_object_unref0 (parser);
		return;
	} else {
		_g_object_unref0 (parser);
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
		g_clear_error (&_inner_error_);
		return;
	}
	_g_object_unref0 (parser);
}


static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}


SkkKeyEventFilter*
skk_rule_get_filter (SkkRule* self)
{
	SkkKeyEventFilter* result = NULL;
	SkkKeyEventFilter* _tmp0_;
	SkkKeyEventFilter* _tmp8_;
	SkkKeyEventFilter* _tmp9_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->filter;
	if (_tmp0_ == NULL) {
		GType* type = NULL;
		GeeMap* _tmp1_;
		SkkRuleMetadata _tmp2_;
		const gchar* _tmp3_;
		gpointer _tmp4_;
		GType* _tmp5_;
		GObject* _tmp6_;
		GObject* _tmp7_;
		_tmp1_ = skk_rule_filter_types;
		_tmp2_ = self->priv->_metadata;
		_tmp3_ = _tmp2_.filter;
		_tmp4_ = gee_map_get (_tmp1_, _tmp3_);
		type = (GType*) _tmp4_;
		_tmp5_ = type;
		_tmp6_ = g_object_new (*_tmp5_, NULL);
		_tmp7_ = G_IS_INITIALLY_UNOWNED (_tmp6_) ? g_object_ref_sink (_tmp6_) : _tmp6_;
		_g_object_unref0 (self->priv->filter);
		self->priv->filter = G_TYPE_CHECK_INSTANCE_CAST (_tmp7_, SKK_TYPE_KEY_EVENT_FILTER, SkkKeyEventFilter);
		_g_free0 (type);
	}
	_tmp8_ = self->priv->filter;
	_tmp9_ = _g_object_ref0 (_tmp8_);
	result = _tmp9_;
	return result;
}


/**
         * Create a rule.
         *
         * @param name name of the rule to load
         *
         * @return a new Rule
         */
static gpointer
_skk_rule_metadata_dup0 (gpointer self)
{
	return self ? skk_rule_metadata_dup (self) : NULL;
}


SkkRule*
skk_rule_construct (GType object_type,
                    const gchar* name,
                    GError** error)
{
	SkkRule * self = NULL;
	SkkRuleMetadata* metadata = NULL;
	SkkRuleMetadata* _tmp0_;
	SkkRuleMetadata* _tmp1_;
	SkkRuleMetadata* _tmp3_;
	SkkRuleMetadata* default_metadata = NULL;
	SkkRuleMetadata* _tmp4_;
	SkkRuleMetadata* _tmp5_;
	SkkRuleMetadata* _tmp28_;
	gchar* _tmp29_;
	gchar* _tmp30_;
	gboolean _tmp31_;
	SkkRomKanaMapFile* _tmp34_ = NULL;
	SkkRuleMetadata _tmp35_;
	SkkRomKanaMapFile* _tmp36_;
	SkkRomKanaMapFile* _tmp37_;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (name != NULL, NULL);
	self = (SkkRule*) g_object_new (object_type, NULL);
	_tmp0_ = skk_rule_find_rule (name);
	metadata = _tmp0_;
	_tmp1_ = metadata;
	if (_tmp1_ == NULL) {
		GError* _tmp2_;
		_tmp2_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't find metadata for \"%s\"", name);
		_inner_error_ = _tmp2_;
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_skk_rule_metadata_free0 (metadata);
			_g_object_unref0 (self);
			return NULL;
		} else {
			_skk_rule_metadata_free0 (metadata);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	_tmp3_ = metadata;
	skk_rule_set_metadata (self, _tmp3_);
	_tmp4_ = skk_rule_find_rule ("default");
	default_metadata = _tmp4_;
	_tmp5_ = default_metadata;
	if (_tmp5_ == NULL) {
		GError* _tmp6_;
		_tmp6_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't find default metadata");
		_inner_error_ = _tmp6_;
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_skk_rule_metadata_free0 (default_metadata);
			_skk_rule_metadata_free0 (metadata);
			_g_object_unref0 (self);
			return NULL;
		} else {
			_skk_rule_metadata_free0 (default_metadata);
			_skk_rule_metadata_free0 (metadata);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	{
		SkkRuleKeymapNameEntry* entry_collection = NULL;
		gint entry_collection_length1 = 0;
		gint _entry_collection_size_ = 0;
		gint entry_it = 0;
		entry_collection = SKK_RULE_keymap_names;
		entry_collection_length1 = G_N_ELEMENTS (SKK_RULE_keymap_names);
		for (entry_it = 0; entry_it < G_N_ELEMENTS (SKK_RULE_keymap_names); entry_it = entry_it + 1) {
			SkkRuleKeymapNameEntry entry = {0};
			entry = entry_collection[entry_it];
			{
				SkkRuleMetadata* _metadata = NULL;
				SkkRuleMetadata* _tmp7_;
				SkkRuleMetadata* _tmp8_;
				SkkRuleMetadata* _tmp9_;
				SkkRuleKeymapNameEntry _tmp10_;
				const gchar* _tmp11_;
				gchar* _tmp12_;
				gchar* _tmp13_;
				gboolean _tmp14_;
				SkkKeymapMapFile* _tmp17_ = NULL;
				SkkRuleMetadata* _tmp18_;
				SkkRuleKeymapNameEntry _tmp19_;
				const gchar* _tmp20_;
				SkkRuleMetadata _tmp21_;
				SkkKeymapMapFile* _tmp22_;
				SkkKeymapMapFile** _tmp23_;
				gint _tmp23__length1;
				SkkRuleKeymapNameEntry _tmp24_;
				SkkInputMode _tmp25_;
				SkkKeymapMapFile* _tmp26_;
				SkkKeymapMapFile* _tmp27_;
				_tmp7_ = metadata;
				_tmp8_ = _skk_rule_metadata_dup0 (_tmp7_);
				_metadata = _tmp8_;
				_tmp9_ = metadata;
				_tmp10_ = entry;
				_tmp11_ = _tmp10_.value;
				_tmp12_ = skk_rule_metadata_locate_map_file (_tmp9_, "keymap", _tmp11_);
				_tmp13_ = _tmp12_;
				_tmp14_ = _tmp13_ == NULL;
				_g_free0 (_tmp13_);
				if (_tmp14_) {
					SkkRuleMetadata* _tmp15_;
					SkkRuleMetadata* _tmp16_;
					_tmp15_ = default_metadata;
					_tmp16_ = _skk_rule_metadata_dup0 (_tmp15_);
					_skk_rule_metadata_free0 (_metadata);
					_metadata = _tmp16_;
				}
				_tmp18_ = _metadata;
				_tmp19_ = entry;
				_tmp20_ = _tmp19_.value;
				_tmp21_ = *_tmp18_;
				_tmp22_ = skk_keymap_map_file_new (&_tmp21_, _tmp20_, &_inner_error_);
				_tmp17_ = _tmp22_;
				if (G_UNLIKELY (_inner_error_ != NULL)) {
					if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
						g_propagate_error (error, _inner_error_);
						_skk_rule_metadata_free0 (_metadata);
						_skk_rule_metadata_free0 (default_metadata);
						_skk_rule_metadata_free0 (metadata);
						_g_object_unref0 (self);
						return NULL;
					} else {
						_skk_rule_metadata_free0 (_metadata);
						_skk_rule_metadata_free0 (default_metadata);
						_skk_rule_metadata_free0 (metadata);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
						g_clear_error (&_inner_error_);
						return NULL;
					}
				}
				_tmp23_ = self->keymaps;
				_tmp23__length1 = self->keymaps_length1;
				_tmp24_ = entry;
				_tmp25_ = _tmp24_.key;
				_tmp26_ = _tmp17_;
				_tmp17_ = NULL;
				_g_object_unref0 (_tmp23_[_tmp25_]);
				_tmp23_[_tmp25_] = _tmp26_;
				_tmp27_ = _tmp23_[_tmp25_];
				_g_object_unref0 (_tmp17_);
				_skk_rule_metadata_free0 (_metadata);
			}
		}
	}
	_tmp28_ = metadata;
	_tmp29_ = skk_rule_metadata_locate_map_file (_tmp28_, "rom-kana", "default");
	_tmp30_ = _tmp29_;
	_tmp31_ = _tmp30_ == NULL;
	_g_free0 (_tmp30_);
	if (_tmp31_) {
		SkkRuleMetadata* _tmp32_;
		SkkRuleMetadata _tmp33_ = {0};
		_tmp32_ = default_metadata;
		skk_rule_metadata_copy (_tmp32_, &_tmp33_);
		skk_rule_metadata_destroy (&self->priv->_metadata);
		self->priv->_metadata = _tmp33_;
	}
	_tmp35_ = self->priv->_metadata;
	_tmp36_ = skk_rom_kana_map_file_new (&_tmp35_, &_inner_error_);
	_tmp34_ = _tmp36_;
	if (G_UNLIKELY (_inner_error_ != NULL)) {
		if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_skk_rule_metadata_free0 (default_metadata);
			_skk_rule_metadata_free0 (metadata);
			_g_object_unref0 (self);
			return NULL;
		} else {
			_skk_rule_metadata_free0 (default_metadata);
			_skk_rule_metadata_free0 (metadata);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	_tmp37_ = _tmp34_;
	_tmp34_ = NULL;
	_g_object_unref0 (self->rom_kana);
	self->rom_kana = _tmp37_;
	_g_object_unref0 (_tmp34_);
	_skk_rule_metadata_free0 (default_metadata);
	_skk_rule_metadata_free0 (metadata);
	return self;
}


SkkRule*
skk_rule_new (const gchar* name,
              GError** error)
{
	return skk_rule_construct (SKK_TYPE_RULE, name, error);
}


/**
         * Locate a rule by name.
         *
         * @param name name of the rule
         *
         * @return a RuleMetadata or `null`
         */
SkkRuleMetadata*
skk_rule_find_rule (const gchar* name)
{
	SkkRuleMetadata* result = NULL;
	GeeMap* _tmp0_;
	gchar** _tmp3_;
	gint _tmp3__length1;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (name != NULL, NULL);
	_tmp0_ = skk_rule_rule_cache;
	if (gee_map_has_key (_tmp0_, name)) {
		GeeMap* _tmp1_;
		gpointer _tmp2_;
		_tmp1_ = skk_rule_rule_cache;
		_tmp2_ = gee_map_get (_tmp1_, name);
		result = (SkkRuleMetadata*) _tmp2_;
		return result;
	}
	_tmp3_ = skk_rule_rules_path;
	_tmp3__length1 = skk_rule_rules_path_length1;
	{
		gchar** dir_collection = NULL;
		gint dir_collection_length1 = 0;
		gint _dir_collection_size_ = 0;
		gint dir_it = 0;
		dir_collection = _tmp3_;
		dir_collection_length1 = _tmp3__length1;
		for (dir_it = 0; dir_it < _tmp3__length1; dir_it = dir_it + 1) {
			gchar* _tmp4_;
			gchar* dir = NULL;
			_tmp4_ = g_strdup (dir_collection[dir_it]);
			dir = _tmp4_;
			{
				gchar* base_dir_filename = NULL;
				const gchar* _tmp5_;
				gchar* _tmp6_;
				gchar* metadata_filename = NULL;
				const gchar* _tmp7_;
				gchar* _tmp8_;
				const gchar* _tmp9_;
				_tmp5_ = dir;
				_tmp6_ = g_build_filename (_tmp5_, name, NULL);
				base_dir_filename = _tmp6_;
				_tmp7_ = base_dir_filename;
				_tmp8_ = g_build_filename (_tmp7_, "metadata.json", NULL);
				metadata_filename = _tmp8_;
				_tmp9_ = metadata_filename;
				if (g_file_test (_tmp9_, G_FILE_TEST_EXISTS)) {
					{
						SkkRuleMetadata metadata = {0};
						const gchar* _tmp10_;
						SkkRuleMetadata _tmp11_ = {0};
						gchar* _tmp12_;
						GeeMap* _tmp13_;
						SkkRuleMetadata _tmp14_;
						SkkRuleMetadata _tmp15_;
						SkkRuleMetadata* _tmp16_;
						SkkRuleMetadata* _tmp17_;
						_tmp10_ = metadata_filename;
						skk_rule_load_metadata (_tmp10_, &_tmp11_, &_inner_error_);
						metadata = _tmp11_;
						if (G_UNLIKELY (_inner_error_ != NULL)) {
							if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
								goto __catch25_skk_rule_parse_error;
							}
							_g_free0 (metadata_filename);
							_g_free0 (base_dir_filename);
							_g_free0 (dir);
							g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
							g_clear_error (&_inner_error_);
							return NULL;
						}
						_tmp12_ = g_strdup (name);
						_g_free0 (metadata.name);
						metadata.name = _tmp12_;
						_tmp13_ = skk_rule_rule_cache;
						_tmp14_ = metadata;
						gee_map_set (_tmp13_, name, &_tmp14_);
						_tmp15_ = metadata;
						_tmp16_ = _skk_rule_metadata_dup0 (&_tmp15_);
						_tmp17_ = _tmp16_;
						skk_rule_metadata_destroy (&_tmp15_);
						result = _tmp17_;
						_g_free0 (metadata_filename);
						_g_free0 (base_dir_filename);
						_g_free0 (dir);
						return result;
					}
					goto __finally25;
					__catch25_skk_rule_parse_error:
					{
						GError* e = NULL;
						e = _inner_error_;
						_inner_error_ = NULL;
						_g_error_free0 (e);
						_g_free0 (metadata_filename);
						_g_free0 (base_dir_filename);
						_g_free0 (dir);
						continue;
					}
					__finally25:
					_g_free0 (metadata_filename);
					_g_free0 (base_dir_filename);
					_g_free0 (dir);
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return NULL;
				}
				_g_free0 (metadata_filename);
				_g_free0 (base_dir_filename);
				_g_free0 (dir);
			}
		}
	}
	result = NULL;
	return result;
}


/**
         * List rules.
         *
         * @return an array of RuleMetadata
         */
static void
_vala_SkkRuleMetadata_array_free (SkkRuleMetadata * array,
                                  gint array_length)
{
	if (array != NULL) {
		int i;
		for (i = 0; i < array_length; i = i + 1) {
			skk_rule_metadata_destroy (&array[i]);
		}
	}
	g_free (array);
}


static void
_vala_array_add1 (SkkRuleMetadata* * array,
                  int* length,
                  int* size,
                  const SkkRuleMetadata* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (SkkRuleMetadata, *array, *size);
	}
	(*array)[(*length)++] = *value;
}


SkkRuleMetadata*
skk_rule_list (int* result_length1)
{
	SkkRuleMetadata* result = NULL;
	GeeSet* names = NULL;
	GeeHashSet* _tmp0_;
	SkkRuleMetadata* rules = NULL;
	SkkRuleMetadata* _tmp1_;
	gint rules_length1;
	gint _rules_size_;
	gchar** _tmp2_;
	gint _tmp2__length1;
	SkkRuleMetadata* _tmp30_;
	gint _tmp30__length1;
	GError * _inner_error_ = NULL;
	_tmp0_ = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, NULL, NULL, NULL, NULL, NULL, NULL);
	names = (GeeSet*) _tmp0_;
	_tmp1_ = g_new0 (SkkRuleMetadata, 0);
	rules = _tmp1_;
	rules_length1 = 0;
	_rules_size_ = rules_length1;
	_tmp2_ = skk_rule_rules_path;
	_tmp2__length1 = skk_rule_rules_path_length1;
	{
		gchar** dir_collection = NULL;
		gint dir_collection_length1 = 0;
		gint _dir_collection_size_ = 0;
		gint dir_it = 0;
		dir_collection = _tmp2_;
		dir_collection_length1 = _tmp2__length1;
		for (dir_it = 0; dir_it < _tmp2__length1; dir_it = dir_it + 1) {
			gchar* _tmp3_;
			gchar* dir = NULL;
			_tmp3_ = g_strdup (dir_collection[dir_it]);
			dir = _tmp3_;
			{
				GDir* handle = NULL;
				gchar* name = NULL;
				{
					GDir* _tmp4_ = NULL;
					const gchar* _tmp5_;
					GDir* _tmp6_;
					GDir* _tmp7_;
					_tmp5_ = dir;
					_tmp6_ = g_dir_open (_tmp5_, (guint) 0, &_inner_error_);
					_tmp4_ = _tmp6_;
					if (G_UNLIKELY (_inner_error_ != NULL)) {
						goto __catch26_g_error;
					}
					_tmp7_ = _tmp4_;
					_tmp4_ = NULL;
					_g_dir_close0 (handle);
					handle = _tmp7_;
					_g_dir_close0 (_tmp4_);
				}
				goto __finally26;
				__catch26_g_error:
				{
					GError* e = NULL;
					e = _inner_error_;
					_inner_error_ = NULL;
					_g_error_free0 (e);
					_g_dir_close0 (handle);
					_g_free0 (dir);
					continue;
				}
				__finally26:
				if (G_UNLIKELY (_inner_error_ != NULL)) {
					_g_dir_close0 (handle);
					_g_free0 (dir);
					rules = (_vala_SkkRuleMetadata_array_free (rules, rules_length1), NULL);
					_g_object_unref0 (names);
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return NULL;
				}
				while (TRUE) {
					GDir* _tmp8_;
					const gchar* _tmp9_;
					gchar* _tmp10_;
					const gchar* _tmp11_;
					GeeSet* _tmp12_;
					const gchar* _tmp13_;
					gchar* metadata_filename = NULL;
					const gchar* _tmp14_;
					const gchar* _tmp15_;
					gchar* _tmp16_;
					const gchar* _tmp17_;
					_tmp8_ = handle;
					_tmp9_ = g_dir_read_name (_tmp8_);
					_tmp10_ = g_strdup (_tmp9_);
					_g_free0 (name);
					name = _tmp10_;
					_tmp11_ = name;
					if (!(_tmp11_ != NULL)) {
						break;
					}
					_tmp12_ = names;
					_tmp13_ = name;
					if (gee_collection_contains ((GeeCollection*) _tmp12_, _tmp13_)) {
						continue;
					}
					_tmp14_ = dir;
					_tmp15_ = name;
					_tmp16_ = g_build_filename (_tmp14_, _tmp15_, "metadata.json", NULL);
					metadata_filename = _tmp16_;
					_tmp17_ = metadata_filename;
					if (g_file_test (_tmp17_, G_FILE_TEST_EXISTS)) {
						{
							SkkRuleMetadata metadata = {0};
							const gchar* _tmp18_;
							SkkRuleMetadata _tmp19_ = {0};
							GeeSet* _tmp20_;
							const gchar* _tmp21_;
							const gchar* _tmp22_;
							gchar* _tmp23_;
							SkkRuleMetadata* _tmp24_;
							gint _tmp24__length1;
							SkkRuleMetadata _tmp25_;
							SkkRuleMetadata _tmp26_ = {0};
							_tmp18_ = metadata_filename;
							skk_rule_load_metadata (_tmp18_, &_tmp19_, &_inner_error_);
							metadata = _tmp19_;
							if (G_UNLIKELY (_inner_error_ != NULL)) {
								if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
									goto __catch27_skk_rule_parse_error;
								}
								_g_free0 (metadata_filename);
								_g_free0 (name);
								_g_dir_close0 (handle);
								_g_free0 (dir);
								rules = (_vala_SkkRuleMetadata_array_free (rules, rules_length1), NULL);
								_g_object_unref0 (names);
								g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
								g_clear_error (&_inner_error_);
								return NULL;
							}
							_tmp20_ = names;
							_tmp21_ = name;
							gee_collection_add ((GeeCollection*) _tmp20_, _tmp21_);
							_tmp22_ = name;
							_tmp23_ = g_strdup (_tmp22_);
							_g_free0 (metadata.name);
							metadata.name = _tmp23_;
							_tmp24_ = rules;
							_tmp24__length1 = rules_length1;
							_tmp25_ = metadata;
							skk_rule_metadata_copy (&_tmp25_, &_tmp26_);
							_vala_array_add1 (&rules, &rules_length1, &_rules_size_, &_tmp26_);
							skk_rule_metadata_destroy (&metadata);
						}
						goto __finally27;
						__catch27_skk_rule_parse_error:
						{
							GError* e = NULL;
							const gchar* _tmp27_;
							GError* _tmp28_;
							const gchar* _tmp29_;
							e = _inner_error_;
							_inner_error_ = NULL;
							_tmp27_ = metadata_filename;
							_tmp28_ = e;
							_tmp29_ = _tmp28_->message;
							g_warning ("rule.vala:349: can't load metadata %s: %s", _tmp27_, _tmp29_);
							_g_error_free0 (e);
						}
						__finally27:
						if (G_UNLIKELY (_inner_error_ != NULL)) {
							_g_free0 (metadata_filename);
							_g_free0 (name);
							_g_dir_close0 (handle);
							_g_free0 (dir);
							rules = (_vala_SkkRuleMetadata_array_free (rules, rules_length1), NULL);
							_g_object_unref0 (names);
							g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
							g_clear_error (&_inner_error_);
							return NULL;
						}
					}
					_g_free0 (metadata_filename);
				}
				_g_free0 (name);
				_g_dir_close0 (handle);
				_g_free0 (dir);
			}
		}
	}
	_tmp30_ = rules;
	_tmp30__length1 = rules_length1;
	if (result_length1) {
		*result_length1 = _tmp30__length1;
	}
	result = _tmp30_;
	_g_object_unref0 (names);
	return result;
}


void
skk_rule_get_metadata (SkkRule* self,
                       SkkRuleMetadata * result)
{
	SkkRuleMetadata _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_metadata;
	*result = _tmp0_;
	return;
}


static gboolean
_skk_rule_metadata_equal (const SkkRuleMetadata * s1,
                          const SkkRuleMetadata * s2)
{
	if (s1 == s2) {
		return TRUE;
	}
	if (s1 == NULL) {
		return FALSE;
	}
	if (s2 == NULL) {
		return FALSE;
	}
	if (g_strcmp0 (s1->base_dir, s2->base_dir)) {
		return FALSE;
	}
	if (g_strcmp0 (s1->name, s2->name)) {
		return FALSE;
	}
	if (g_strcmp0 (s1->label, s2->label)) {
		return FALSE;
	}
	if (g_strcmp0 (s1->description, s2->description)) {
		return FALSE;
	}
	if (g_strcmp0 (s1->filter, s2->filter)) {
		return FALSE;
	}
	return TRUE;
}


static void
skk_rule_set_metadata (SkkRule* self,
                       SkkRuleMetadata * value)
{
	SkkRuleMetadata old_value;
	g_return_if_fail (self != NULL);
	if (_skk_rule_metadata_equal (value, (skk_rule_get_metadata (self, &old_value), &old_value)) != TRUE) {
		SkkRuleMetadata _tmp0_;
		SkkRuleMetadata _tmp1_ = {0};
		_tmp0_ = *value;
		skk_rule_metadata_copy (&_tmp0_, &_tmp1_);
		skk_rule_metadata_destroy (&self->priv->_metadata);
		self->priv->_metadata = _tmp1_;
		g_object_notify_by_pspec ((GObject *) self, skk_rule_properties[SKK_RULE_METADATA_PROPERTY]);
	}
}


static void
skk_rule_keymap_name_entry_copy (const SkkRuleKeymapNameEntry* self,
                                 SkkRuleKeymapNameEntry* dest)
{
	SkkInputMode _tmp0_;
	const gchar* _tmp1_;
	gchar* _tmp2_;
	_tmp0_ = (*self).key;
	(*dest).key = _tmp0_;
	_tmp1_ = (*self).value;
	_tmp2_ = g_strdup (_tmp1_);
	_g_free0 ((*dest).value);
	(*dest).value = _tmp2_;
}


static void
skk_rule_keymap_name_entry_destroy (SkkRuleKeymapNameEntry* self)
{
	_g_free0 ((*self).value);
}


static SkkRuleKeymapNameEntry*
skk_rule_keymap_name_entry_dup (const SkkRuleKeymapNameEntry* self)
{
	SkkRuleKeymapNameEntry* dup;
	dup = g_new0 (SkkRuleKeymapNameEntry, 1);
	skk_rule_keymap_name_entry_copy (self, dup);
	return dup;
}


static void
skk_rule_keymap_name_entry_free (SkkRuleKeymapNameEntry* self)
{
	skk_rule_keymap_name_entry_destroy (self);
	g_free (self);
}


static GType
skk_rule_keymap_name_entry_get_type (void)
{
	static volatile gsize skk_rule_keymap_name_entry_type_id__volatile = 0;
	if (g_once_init_enter (&skk_rule_keymap_name_entry_type_id__volatile)) {
		GType skk_rule_keymap_name_entry_type_id;
		skk_rule_keymap_name_entry_type_id = g_boxed_type_register_static ("SkkRuleKeymapNameEntry", (GBoxedCopyFunc) skk_rule_keymap_name_entry_dup, (GBoxedFreeFunc) skk_rule_keymap_name_entry_free);
		g_once_init_leave (&skk_rule_keymap_name_entry_type_id__volatile, skk_rule_keymap_name_entry_type_id);
	}
	return skk_rule_keymap_name_entry_type_id__volatile;
}


static void
skk_rule_class_init (SkkRuleClass * klass)
{
	GeeHashMap* _tmp0_;
	GeeHashMap* _tmp1_;
	gint _tmp2_;
	gchar** _tmp3_;
	GeeMap* _tmp4_;
	GType _tmp5_;
	GeeMap* _tmp6_;
	GType _tmp7_;
	skk_rule_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (SkkRulePrivate));
	G_OBJECT_CLASS (klass)->get_property = _vala_skk_rule_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_skk_rule_set_property;
	G_OBJECT_CLASS (klass)->finalize = skk_rule_finalize;
	/**
	         * Metadata associated with the rule.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_RULE_METADATA_PROPERTY, skk_rule_properties[SKK_RULE_METADATA_PROPERTY] = g_param_spec_boxed ("metadata", "metadata", "metadata", SKK_TYPE_RULE_METADATA, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	_tmp0_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, G_TYPE_GTYPE, (GBoxedCopyFunc) _g_type_dup, (GDestroyNotify) g_free, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	skk_rule_filter_types = (GeeMap*) _tmp0_;
	_tmp1_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, SKK_TYPE_RULE_METADATA, (GBoxedCopyFunc) skk_rule_metadata_dup, (GDestroyNotify) skk_rule_metadata_free, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	skk_rule_rule_cache = (GeeMap*) _tmp1_;
	_tmp3_ = skk_util_build_data_path ("rules", &_tmp2_);
	skk_rule_rules_path = (_vala_array_free (skk_rule_rules_path, skk_rule_rules_path_length1, (GDestroyNotify) g_free), NULL);
	skk_rule_rules_path = _tmp3_;
	skk_rule_rules_path_length1 = _tmp2_;
	_skk_rule_rules_path_size_ = skk_rule_rules_path_length1;
	_tmp4_ = skk_rule_filter_types;
	_tmp5_ = SKK_TYPE_SIMPLE_KEY_EVENT_FILTER;
	gee_map_set (_tmp4_, "simple", &_tmp5_);
	_tmp6_ = skk_rule_filter_types;
	_tmp7_ = SKK_TYPE_NICOLA_KEY_EVENT_FILTER;
	gee_map_set (_tmp6_, "nicola", &_tmp7_);
}


static void
skk_rule_instance_init (SkkRule * self)
{
	SkkKeymapMapFile** _tmp0_;
	self->priv = SKK_RULE_GET_PRIVATE (self);
	_tmp0_ = g_new0 (SkkKeymapMapFile*, SKK_INPUT_MODE_LAST + 1);
	self->keymaps = _tmp0_;
	self->keymaps_length1 = SKK_INPUT_MODE_LAST;
	self->_keymaps_size_ = self->keymaps_length1;
}


static void
skk_rule_finalize (GObject * obj)
{
	SkkRule * self;
	SkkKeyEventFilter* _tmp0_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, SKK_TYPE_RULE, SkkRule);
	_tmp0_ = self->priv->filter;
	if (_tmp0_ != NULL) {
		SkkKeyEventFilter* _tmp1_;
		_tmp1_ = self->priv->filter;
		skk_key_event_filter_reset (_tmp1_);
		_g_object_unref0 (self->priv->filter);
		self->priv->filter = NULL;
	}
	skk_rule_metadata_destroy (&self->priv->_metadata);
	self->keymaps = (_vala_array_free (self->keymaps, self->keymaps_length1, (GDestroyNotify) g_object_unref), NULL);
	_g_object_unref0 (self->rom_kana);
	_g_object_unref0 (self->priv->filter);
	G_OBJECT_CLASS (skk_rule_parent_class)->finalize (obj);
}


/**
     * Object representing a typing rule.
     */
GType
skk_rule_get_type (void)
{
	static volatile gsize skk_rule_type_id__volatile = 0;
	if (g_once_init_enter (&skk_rule_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (SkkRuleClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) skk_rule_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SkkRule), 0, (GInstanceInitFunc) skk_rule_instance_init, NULL };
		GType skk_rule_type_id;
		skk_rule_type_id = g_type_register_static (G_TYPE_OBJECT, "SkkRule", &g_define_type_info, 0);
		g_once_init_leave (&skk_rule_type_id__volatile, skk_rule_type_id);
	}
	return skk_rule_type_id__volatile;
}


static void
_vala_skk_rule_get_property (GObject * object,
                             guint property_id,
                             GValue * value,
                             GParamSpec * pspec)
{
	SkkRule * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, SKK_TYPE_RULE, SkkRule);
	switch (property_id) {
		case SKK_RULE_METADATA_PROPERTY:
		{
			SkkRuleMetadata boxed;
			skk_rule_get_metadata (self, &boxed);
			g_value_set_boxed (value, &boxed);
		}
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


static void
_vala_skk_rule_set_property (GObject * object,
                             guint property_id,
                             const GValue * value,
                             GParamSpec * pspec)
{
	SkkRule * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, SKK_TYPE_RULE, SkkRule);
	switch (property_id) {
		case SKK_RULE_METADATA_PROPERTY:
		skk_rule_set_metadata (self, g_value_get_boxed (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


static void
_vala_array_destroy (gpointer array,
                     gint array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		int i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}


static void
_vala_array_free (gpointer array,
                  gint array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}



